1. Overview
1.1. Product Philosophy
1.1.1. Why yuuvis® Momentum?
The digital transformation demands highly customized solutions to serve the needs and expectations of its user and to fully leverage its advantages. These solutions may stress the underlying application from very different angles - think of the different workloads a solution for email archiving poses compared to one facilitating workflows, or to one where analysis and classification and processing of incoming documents are the focus. What they all have in common these times is the need to reliably handle ever-growing amount of documents in an audit-proof manner, guaranteeing performant access via a capable query language over vast amounts of data. All access has to be controllable via an integrated rights management. And deep integration into existing system landscapes should be supported by flexible customization options.
If you are concerned about your archive solution not scaling to your amount of documents, if you are not sure whether to keep your data safe on your own hardware or might to move to the cloud later, if you need a platform offering a performant backend to develop your web applications against, yuuvis® Momentum might be the tool of choice for you. Check out a few use cases here.
1.1.2. Key Features
-
API first
-
Excellent scalability - high performance on big amounts of data
-
Docker/Kubernetes
-
No commercial databases etc. required
-
multi-tenancy
-
hybrid: runs in cloud or on premises
-
Simplified operation and administration
-
Nearly no downtime
Solutions build using yuuvis® Momentum are highly scalable, run either cloud native or on premises and exhibit outstanding performance. yuuvis® Momentum offers you to tap into existing user management and is readily integrated into an existing system environment via its REST API. Functionality is easily expanded using concepts like Webhooks, AMQP Hooks and Interceptors. It offers a complete audit trail, performant Search features in an SQL-like manner and Rights Management. It supports asynchronous document processing via Tagging, evolving documents via the Schema Flow and handling of Compound Documents. And all that with support for multi-tenancy with administration on global system as well as on tenant level.
1.2. Core Services
The core is the heart of the product and connects to your infrastructure. It consists of basic core services that are required for the proper operation of a yuuvis® Momentum instance. Each individual service can be scaled to optimize the usage of your resources.
The entirety of the core’s functions is made available through the API gateway. Depending on the concrete request, multiple core services are involved in the processing chain. Some basic use case flows are illustrated below. Just click to view them.
Authentication Flow (Browser)
-
HTTP request to any API endpoint
-
Redirect to identity provider
-
Verify credentials externally
-
Redirect to authentication with auth code
-
Send auth code to
authentication
service -
Retrieve
userId
using auth code -
Recieve
userId
-
Request role set acquisition
-
Query user role set
-
Recieve user role set
-
Present role set
-
Provide authentication token and proceed with initial API request
-
Request information from other parts of the system
-
Obtain requested information
-
Produce API response
-
Send HTTP response to user
-
user.info
Import Flow
-
HTTP POST request containing metadata and content
-
Enrichment of request with authentication token
-
Defer content to storage services
-
Analyze content file
-
Skip
contentanalyzer
service
-
-
Content storage handling
-
Using custom storage via
archive
service -
Using an interface of the
repository
service
-
-
Create metadata based on previous steps
-
Write metadata to storage / index instances
-
Index new object in Elasticsearch
-
Create initial audit entry
-
Create API response from metadata
-
Return metadata as HTTP response
During asynchronous import operations, the controller
service provides messaging for the boxed in services
-
dms.request.objects.upsert.storage-before
-
dms.request.objects.upsert.database-before
-
dms.response.objects, dms.response.objects.insert
Content Retrieval Flow
-
HTTP GET request to object URL
-
Enrichment of request with authentication token
-
Check for user authorization using search service query
-
Query Elasticsearch for
objectId
-
Elasticsearch metadata response (if user is authorized)
-
Repository URL of
objectId
-
Request content of
objectId
-
Query
objectId
in storage provider -
Storage provider metadata response
-
Return object metadata
-
Write
CONTENT_ACCESSED
audit entry -
Create API response from metadata
-
Return HTTP metadata response
-
dms.request.objects.contents
Metadata Retrieval Flow
-
HTTP GET request to object URL
-
Enrichment of request with authentication token
-
Request metadata
-
Query
objectId
in database -
Database metadata response
-
Return object metadata
-
Write
METADATA_ACCESSED
audit entry -
Create API response from metadata
-
Return HTTP metadata response
-
dms.response.objects
Search Flow
-
HTTP POST request with query
-
Enrichment of request with authentication token
-
Request query execution
-
Translate and send Elasticsearch query
-
Receive Elasticsearch query results
-
Return metadata object list
-
Create API response from metadata
-
Return HTTP metadata response
-
dms.request.search
-
dms.response.objects, dms.response.objects.search
Content Update Flow
-
HTTP POST request to content URL of object
-
Enrichment of the request with authentication token
-
Verify user has writing permissions on object using
search
service -
Query object in Elasticsearch
-
Return Elasticsearch query results
-
Return user authorization verification results
-
Infer analysis of new content item
-
Commit new content to storage
-
Content Storage Handling
-
Using custom storage via
archive
service -
Using an interface of
repository
service
-
-
Update object metadata contentstream attribute
-
Commit updated metadata to database and index
-
Index the updated metadata in Elasticsearch
-
Write
CONTENT_UPDATED
audit entry -
Return updated metadata
-
Create API response from metadata
-
Return updated metadata
-
dms.request.objects.upsert.storage-before
-
dms.request.objects.upsert.database-before
-
dms.response.objects, dms.response.objects.update
Metadata Update Flow
-
HTTP POST request to
objectId
URL -
Enrichment of request with authentication token
-
Query for
objectId
usingsearch
service to verify user authorization -
Query Elasticsearch for object
-
Elasticsearch object response (if user has permissions for update object)
-
Authorization test query response
-
Infer metadata validation and update
-
If expiration date has changed: update content storage via
archive
service -
Infer metadata update
-
Write new metadata to database, write
METADATA_UPDATED
audit entry -
Index new metadata in Elasticsearch
-
Create API response from metadata
-
Return metadata HTTP response
-
dms.request.objects.upsert.storage-before
-
dms.request.objects.upsert.database-before
-
dms.response.objects, dms.response.objects.update
Deletion Flow
-
HTTP DELETE request to
objectId
URL -
Enrichment of request with authentication token
-
Query object using
search
service to verify user authorization -
Query object in Elasticsearch
-
Elasticsearch object reponse
-
Authorization verification results
-
Infer flag for deletion on object
-
Flag as deleted in database,
FLAGGED_FOR_DELETE
audit entry -
Flag as deleted in Elasticsearch via
index
service -
Delete content through
repository
service -
Infer deletion of object in database
-
Infer deletion of object in Elasticsearch
-
OBJECT_DELETED
audit entry -
Return deletion results
-
dms.request.objects.delete
-
dms.response.objects.delete
1.3. Additional Services
A wide range of optional extensions are available. They support developers in the fields of client development, tenant administration and business process management. It is also possible to install components for an SAP® connection or even an AI integration.
1.3.1. Client Development
yuuvis® Momentum client as reference implementation is the first and major example of an application build for yuuvis® Momentum. More than a mere showcase, it comes with own services, delivering reusable functionality for client applications in Angular using the developer libraries.
2. Core
The core system consists of multiple services that can be scaled to the project’s requirements. Using widely configurable and customizable processing flows, the core system provides a REST API for document lifecycle. Hereby, it is especially important to decide for synchronous or asynchronous processing for the individual use case.
The core system furthermore provides API as well as backend tools for resource management, testing and maintenance.
2.1. DMS Objects
Object instances managed in the yuuvis® Momentum document management system (short DMS objects) are structured in JSON format with a very strict convention. The DMS objects are always enclosed in a list. Thus, request and response formats are constant and independent on the handled number of DMS objects.
DMS objects are either
-
document objects (short: documents) or
-
folder objects (short: folders).
Within a document, a binary content file can be referenced and thus be assigned that DMS object.
2.1.1. Object Properties
DMS objects have the following property sections:
Section key | Description | Available in search queries |
---|---|---|
|
Available in all DMS objects. It contains
|
yes, in |
|
Available in DMS objects with a binary content file assigned to them. It is always a list with one entry containing a set of content stream properties that are pre-defined in the global schema. |
yes, in |
|
Process-related controlling information. Only available during the import of objects with a binary content file. It contains a list of rendition specifications. |
no |
|
Process-related controlling information. Only available during specific processing steps. |
no |
Example DMS Object without Binary Content File
{
"objects": [
{
"properties": {
"system:objectId": {
"value": "12345678-90ab-cdef-1234-567890ab"
},
"system:traceId": {
"value": "1234567812345678"
},
"system:objectTypeId": {
"value": "appTest:processdocument"
},
"system:lastModificationDate": {
"value": "2023-06-22T14:40:19.180Z"
},
"system:versionNumber": {
"value": 5
},
"system:baseTypeId": {
"value": "system:document"
},
"system:tenant": {
"value": "yuuvistest"
},
"system:createdBy": {
"value": "abcdef12-3456-7890-abcd-ef123456"
},
"appTest:exampleproperty": {
"value": false
},
"system:creationDate": {
"value": "2023-06-22T14:00:57.260Z"
},
"system:lastModifiedBy": {
"value": "abcdef12-3456-7890-abcd-ef123456"
}
}
}
]
}
Example DMS Object with Binary Content File
{
"objects": [{
"properties": {
"system:objectId": {
"value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee"
},
"system:baseTypeId": {
"value": "system:document"
},
"system:objectTypeId": {
"value": "appEmail:email"
},
"system:createdBy": {
"value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794"
},
"system:creationDate": {
"value": "2018-01-26T15:21:170Z"
},
"system:lastModifiedBy": {
"value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794"
},
"system:lastModificationDate": {
"value": "2018-01-29T13:13:113Z"
},
"system:versionNumber": {
"value": 2
},
"system:tenant": {
"value": "tenant1"
},
"system:traceId": {
"value": "97a35859dbb4c435"
},
"appEmail:from": {
"value": "Maria Schmidt <schmidt@example.de>"
},
"appEmail:to": {
"value": ["Hans Meier <meier@example.de>"]
},
"appEmail:cc": {
"value": ["Conrad Schulze <schulze@example.de>",
"Emilia Lehmann <lehmann@example.de>"]
},
"appEmail:subject": {
"value": "Updated Bewerbungsunterlagen"
},
"table": {
"columnNames": ["iColumn1", "iColumn2", "iColumn3"],
"value": [["something", "to know", true],["more", "infos", false]]
}
},
"contentStreams": [{
"contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7",
"length": 173413,
"mimeType": "message/rfc822",
"fileName": "upload.eml",
"digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855",
"repositoryId": "repo252"
}]
}]
}
Example DMS Object with Binary Content File and Rendition
{
"objects": [{
"properties": {
"enaio:objectTypeId": {
"value": "E13C7EBF4B974B3A9FF296C01F90D0EE"
},
"sysfrom": {
"value": "Garco Meissler <garco@example.de>"
},
"systo": {
"value": "Dudreas Annkel <dudreas@example.de>"
},
"syscc": {
"value": "Kruedeas Anger <kruedeas@example.de>"
},
"syssubject": {
"value": "Wachsmalstift rückwärts kontrollieren"
},
"redline:baseTypeId": {
"value": "DOCUMENT"
},
"redline:mandant": {
"value": "default"
}
},
"contentStreams": [{
"mimeType": "message/rfc822",
"fileName": "upload.eml",
"cid": "cid_63apple"
}],
"renditions": [{
"mimeType": "text/plain",
"kind": "text",
"contentStream": {
"length": 39939,
"mimeType": "text/plain",
"fileName": "content.txt",
"cid": "rendition_0"
}
}]
}]
}
2.1.2. Binary Content Files
One of the key concepts of a document management system (DMS) is the effective handling of binary content files. On top of the basic operations like import, retrieval, update and deletion, further demands have to be considered in many companies. Each content update triggers the creation of a new version of the object whereas the previous object version is moved to the version history. Furthermore, in order to comply with legal bindings regarding the storage time, yuuvis® Momentum allows you to configure strict retention times during which the binary content files can neither be deleted nor updated. Binary content files of suitable formats can be analyzed in order to extract a text rendition that will be included in the full-text search. For many file types, also a PDF rendition can be retrieved.
General Characteristics
-
The file size for binary content files in yuuvis® Momentum is limited to 32 GB per file.
-
The core system can handle any file type as binary content file. For a wide range of file types, the generation of renditions is supported.
-
Binary content files are stored in repositories that are managed by the
repository
service and, if necessary, connected to yuuvis® Momentum via thearchive
service. -
Retention times can be specified in order to protect binary content files from deletion and modification.
-
Binary content files can be assigned only to document objects. It is not possible to assign more than one binary content file per object.
-
Document objects can be created without any binary content file assigned to them. Binary content files can be added to such already existing objects.
-
Objects with a binary content file assigned to them have the section
contentStreams
in their JSON-formatted object representation.
Content Analysis
In the default configuration, each binary content file imported to yuuvis® Momentum passes the content analyzer provided by the repository
service. Its mime type is determined and the contained text is extracted for the most common file types.
Text Extraction
The repository
service can extract the text contained in an imported binary content file. The extracted plain text is stored as text rendition in the search index and will be used for the full-text search together with all values of string properties within the metadata. Details on supported file types, calculation and storage are available in the section.
The file types for which text extraction is available are listed here: Content Renditions
The text rendition can be retrieved via the following endpoint GET /api/dms/objects/{objectId}/contents/renditions/text
Mime Type Determination
The contentanalyzer
service is responsible for the determination of the mime type of binary content files that are imported to yuuvis® Momentum. The determined mime type is stored in the content stream properties section of the corresponding DMS object.
E-mail Metadata Extraction
As of 2024 Spring, yuuvis® Momentum contains a predefined app for the extraction of basic e-mail metadata. The app triggers the contentanalyzer
service to read the following information from binary content files during their import, if they have been identified as EML or MSG e-mail file:
Property | Type | Description |
---|---|---|
|
String |
Optional. Subject of the e-mail. |
|
datetime |
Required. Date and time when the e-mail was sent. |
|
String |
Required. E-mail address of the sender. |
|
List of strings |
Optional. List of direct receivers. |
|
List of strings |
Optional. List of CC receivers. |
|
List of strings |
Optional. List of BCC receivers. |
|
String |
Optional. ID of the message. |
|
List of strings |
Optional. File names of the attachments. |
|
Int |
Optional. Number of attachments. |
The analysis is only available during import requests via POST /api/dms/objects .
|
Required configuration steps:
-
The app
systemmail
has to be activated for the corresponding tenant via app set.Example app set<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <apps xmlns="http://optimal-systems.org/ns/yuuvis/apps/"> <app> <name>systemmail</name> <state>enabled</state> </app> </apps>
-
The app schema for the
systemmail
app has to be available.App schema for 'systemmail'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/"> <version>3</version> <lastModificationDate>2023-06-29T23:23:54.635Z</lastModificationDate> <propertyStringDefinition> <id>appSystemmail:subject</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> <propertyDateTimeDefinition> <id>appSystemmail:sent</id> <propertyType>datetime</propertyType> <cardinality>single</cardinality> <required>true</required> </propertyDateTimeDefinition> <propertyStringDefinition> <id>appSystemmail:from</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>true</required> </propertyStringDefinition> <propertyStringDefinition> <id>appSystemmail:to</id> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>false</required> </propertyStringDefinition> <propertyStringDefinition> <id>appSystemmail:cc</id> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>false</required> </propertyStringDefinition> <propertyStringDefinition> <id>appSystemmail:bcc</id> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>false</required> </propertyStringDefinition> <propertyStringDefinition> <id>appSystemmail:messageId</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> <propertyStringDefinition> <id>appSystemmail:attachments</id> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>false</required> </propertyStringDefinition> <propertyIntegerDefinition> <id>appSystemmail:attachmentCount</id> <propertyType>integer</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyIntegerDefinition> <typeSecondaryDefinition> <id>appSystemmail:email</id> <baseId>system:secondary</baseId> <propertyReference>appSystemmail:subject</propertyReference> <propertyReference>appSystemmail:sent</propertyReference> <propertyReference>appSystemmail:from</propertyReference> <propertyReference>appSystemmail:to</propertyReference> <propertyReference>appSystemmail:cc</propertyReference> <propertyReference>appSystemmail:bcc</propertyReference> <propertyReference>appSystemmail:messageId</propertyReference> <propertyReference>appSystemmail:attachments</propertyReference> <propertyReference>appSystemmail:attachmentCount</propertyReference> <contentStreamAllowed>required</contentStreamAllowed> </typeSecondaryDefinition> </schema>
-
The
contentanalyzer
service must not be skipped and its metadata analysis has to be activated. Check theserviceConfiguration.json
configuration file.Example 'serviceConfiguration.json' with suitable configuration{ "services": { "contentanalyzer": { "skip": false, "analyze": [ { "mimetype": true, "content": true, "metadata": true } ] } } }
Storage
The repository
service is responsible for the storage management of binary content files. For this purpose, an S3 store is the standard archive solution. Alternatively or additionally, many external archive providers are supported to be connected via the archive
Service.
Furthermore, the SHA-256 digest for the binary content files is calculated during the saving processes and stored in the content stream properties section of the corresponding DMS objects.
Large Files
The import of large binary content files via POST /api/dms/objects
might be very slow and often leads to timeouts. Thus, it is useful to split them in pieces and upload them in multiple sub-processes. The steps are described in this section. You can upload up to 10,000 pieces of one binary content file. The DMS object to which the complete content file is finally assigned is created after the successful upload of all pieces.
Before the final step of DMS object creation, the pieces of content are only stored temporarily in the repository service. To ensure that all pieces of one content file are processed by the same repository service instance, the Kubernetes Loadbalancer internally sets a serviceInstanceUrl during the upload initialization. It is stored in a shared cache for all repository service instances. For each piece to be uploaded, the correct instance is read from this cache.
|
-
Split your large binary content file into pieces.
-
Initialize the import via
POST /api/dms/uploads
and extract theuploadId
from the response body. After each processing step of the upload, a maximum time of 2 days (default configuration) inactivity is accepted before the process and all its pieces are automatically deleted.ExamplePOST /api/ms/uploads { "uploadId": "MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5" }
-
Import each individual piece via
PUT /api/dms/uploads/{uploadId}/parts/{partNumber}
.-
Use a single piece of your content file as binary request body (no multipart).
-
For
uploadId
, use the value that was generated during the initialization step. Use the same value for all pieces of one binary content file. -
For
partNumber
, use the index number of the current piece starting with 1.
Example with 3 piecesPUT /api/dms/uploads/MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5/parts/1 200 OK PUT /api/dms/uploads/MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5/parts/2 200 OK PUT /api/dms/uploads/MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5/parts/3 200 OK
-
-
Optionally, you can retrieve an overview of your running upload processes and the already imported pieces via
GET /api/dms/uploads
. -
In case you want to cancel your upload process, you can delete the already uploaded pieces via
DELETE /api/dms/uploads/{uploadId}
. -
Finalize the upload via
POST /api/dms/uploads/{uploadId}
. Optionally, you can validate the total number of imported pieces by appending thenumberOfParts
query parameter.ExamplePOST /api/dms/uploads/MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5?numberOfParts=3 200 OK
After calling this endpoint, no further pieces can be added to the process indicated by the current
uploadId
. -
Connect the completed binary content file to a DMS object in yuuvis® Momentum via
POST /api/dms/uploads/{uploadId}/objects
. Specify the metadata inproperties
section of the JSON request body.The contentStreamId
automatically refers to the binary content file created by the upload process specified byuploadId
. However, thecontentanalyzer
service is SKIPPED. Thus, if you need proper values in thecontentStreams
section forfileName
andmimeType
, you need to set them in the JSON request body.Example request body for the creation of a DMS object after partial upload{ "objects": [{ "properties": { "system:objectTypeId": { "value": "system:document" }, "customproperty": { "value": "myvalue" } }, "contentStreams": [{ "mimeType": "application/pdf", "fileName": "myfilename.pdf" }] }] }
2.2. Schema for DMS Objects
Each object in yuuvis® Momentum instantiates an object type that is defined in the applied tenant schema. Once a DMS object is created, its object type is set and remains unmodifiable during its entire lifecycle.
Depending on the definition of the instantiated object type, a set of properties is available for the corresponding DMS object. The properties themselves have to be defined in a schema as well.
2.2.1. Schema Outline
A schema contains property definitions and object type definitions in XML format in the following mandatory order. It is possible to skip parts but not to change their order.
-
Label (as of 2023 Autumn)
-
Property definitions
-
Object Type definitions:
-
Document type definitions
-
Folder type definitions
-
Secondary object type definitions
-
The label
is an optional string field to specify a project-specific schema versioning information. Its string value is limited to 128 characters.
Display a simple example schema
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://optimal-systems.org/ns/dmscloud/schema/v5.0/dmsCloud-schema.xsd">
<label>1.2.3</label>
<propertyStringDefinition>
<id>from</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>to</id>
<propertyType>string</propertyType>
<cardinality>multi</cardinality>
<required>true</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>subject</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
<defaultValue>hello</defaultValue>
<maxLength>20</maxLength>
<minLength>4</minLength>
</propertyStringDefinition>
<propertyDateTimeDefinition>
<id>received</id>
<propertyType>datetime</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyDateTimeDefinition>
<typeDocumentDefinition>
<id>email</id>
<baseId>system:document</baseId>
<propertyReference>from</propertyReference>
<propertyReference>to</propertyReference>
<propertyReference>received</propertyReference>
<contentStreamAllowed>required</contentStreamAllowed>
</typeDocumentDefinition>
</schema>
2.2.2. Scopes and Endpoints for Schemata
In the multi-tenant landscape of yuuvis® Momentum, it is important to be aware of the scope of property and object type definitions.
-
Any object types or properties that should be available for all tenants should to be introduced to the global schema.
-
To prevent cluttering the global schema and allow for duplicate names, app schemata can be used. They provide a namespace for properties and object types pertaining to a particular use case. An app schema is available in all tenants where the app is enabled.
-
Each tenant can have exactly one tenant schema that allows to define properties and object types for usage only within the specific tenant.
By default, the maximum number of property definitions in a tenant schema is 20. A system integrator can change this limit via the schema.tenant.properties.limit
parameter in the configuration of thesystem
service. If you want to increase this limit, it is recommended to increase the maximum number of fields in your Elasticsearch index as well. -
For each tenant, the global schema and the tenant schema are merged with the app schemata for those apps that are enabled for the tenant. The resulting applied tenant schema is used for DMS operations like object import, update or search.
Depending on the schema scope, the schemata are managed via specific endpoints. Furthermore, their property and object type IDs have specific prefixes.
Retrieval | Validation | Update | |
---|---|---|---|
global schema |
GET |
POST |
POST |
app schema |
GET |
POST |
POST |
tenant schema of any tenant |
GET |
POST |
POST |
tenant schema of the own tenant |
GET |
POST |
POST |
2.2.3. Naming Conventions for Property and Object Type IDs
In every property definition and every object type definition the id
attribute is required. It is used to identify the object type or property. Each ID is a string with a maximum of 63 characters, and it must match the regular expression
([a-zA-Z][a-zA-Z0-9]*:)?[a-zA-Z][a-zA-Z0-9]*
.
The IDs are also used as the name of the type, e.g., in query operations. Hence, it is recommended to choose meaningful values for type IDs.
The part before the :
character is the prefix. It is useful to specify the scope of the corresponding schema. Within the schema file, all references on the same ID have to be EITHER with OR without prefix. Depending on the situation, the prefix can be omitted, for example to broaden a search query across multiple application schemata.
-
In tenant-specific (app-specific) definitions, only prefixes matching
"ten" + <tenant name>
("app" + <app name>
) are allowed. The tenant (app) name is case-insensitive when used as a path or search parameter. If no prefix is specified, the prefix is added automatically in the applied tenant schema. Thus, the same object type name can occur in multiple tenant (app) schemata. -
Some specific requirements for app names are described in the chapter on app management.
-
In the global schema all prefixes are allowed, as long as they do not start with ten or app or equal system. Alternatively, they can also have no prefix.
An exception are column names in Table Property Definitions, where prefixes are prohibited. |
As of 2021 Winter, it is possible to use the -
character as an additional separator within prefixes for tenant-specific IDs if matching the following regular expression:
([a-zA-Z][a-zA-Z0-9-]*:)?[a-zA-Z][a-zA-Z0-9]*
2.2.4. Property Definitions
General Property Attributes
All property definitions have the following attributes:
Attribute | Type | Required | Description | ||
---|---|---|---|---|---|
|
String |
yes |
The ID of the property matching the regular expression. It uniquely identifies the property within in the schema file. |
||
|
URI |
no |
By using namespaces, it is possible to form groups of properties and object types. |
||
|
String |
no |
Describes the property. |
||
|
Enum |
yes |
Specifies the type of this property. The following types are supported:
|
||
|
Enum |
yes |
Defines whether the property can have a maximum of one or an arbitrary number of values. Possible values are |
||
|
Boolean |
yes |
If This attribute can be overwritten in the property references of object type definitions. Hence, the same property can be required in one object type and not required in another object type. Following the concept of secondary object types, the same property can be allowed by multiple ways in an object instance, e.g. if the object type has a reference to the property type and the object has one or more secondary object types, that have references to the property type. If these references have different required values, the value true always dominates over false. Check out the tutorial "Overwriting the 'required' Property Attribute" for further examples. |
||
|
Boolean |
no |
Specifies whether or not the property may appear in the |
||
|
String |
no |
Declares the classifications this property belongs to. There is no validation or use in the system itself. For example, string properties can be classified as email or url and a client application can use this classification to present the property’s content in an appropriate manner. This attribute can be used several times and the corresponding values are delivered in an array.
|
||
|
depending on the |
no |
The value that the system sets for the property if no value is provided during object creation. If the cardinality is multi, there can be more than one default value and a list of all default values is provided. Default values can be also applied by update. Assume a secondary object type has property types with default values. If you add this secondary object type to an existing object by update, these default values are applied, if the update does npt set values for these properties and the properties were not allowed in the object before the update. |
Depending on the property type, a property can have specific attributes.
Attributes for Integer Property Definitions
Attribute | Type | Required | Description | Technical Limit used as Default |
---|---|---|---|---|
|
Integer |
no |
The maximum value allowed for this property. |
9223372036854775807 |
|
Integer |
no |
The minimum value allowed for this property. |
-9223372036854775808 |
Attributes for DateTime Property Definitions
Attribute | Type | Required | Description |
---|---|---|---|
|
Enum |
no |
The only supported value is date. If the resolution is set to date, the property can only store values without a time part and these values have the format |
Attributes for Decimal Property Definitions
Decimal properties support values of 64-bit precision (IEEE 754). The values have to be specified in decimal notation. However in the table below, the technical limits are provided in base 2 scientific notation in order to display the values in a condensed and comfortable format. This format cannot be used to specify the value for a maxValue
or minValue
attribute in a decimal property definition.
Attribute | Type | Required | Description | Technical Limit used as Default |
---|---|---|---|---|
|
Decimal |
no |
The maximum value allowed for this property |
(2-2 -52 )·2 1023 |
|
Decimal |
no |
The minimum value allowed for this property. |
-(2-2 -52)·2 1023 |
Please note the additional limit of precision: values of magnitude smaller than 2-1074 will be rounded to 0. |
Attributes for String Property Definitions
Attribute | Type | Required | Description |
---|---|---|---|
|
Integer |
no |
The maximum length (in characters) allowed for a value of this property. |
|
Integer |
no |
The minimum length (in characters) allowed for a value of this property. |
|
Boolean |
no |
If If |
In general, the length of a string is limited to 8192. Hence, the maximum value for maxLength
and minLength
is 8192.
Attributes for Table Property Definitions
A table property definition contains some attributes and one or more sub-property definitions, the columns.
The number of rows and columns of a table property definition is limited to a maximum of 512 columns and 1024 rows.
Particularities for table property attributes:
Attribute | Type | Required | Description | ||
---|---|---|---|---|---|
|
Enum |
yes |
Defines whether the property can have a maximum of one or an arbitrary number of values. For a table property, only |
||
|
Boolean |
no |
Specifies whether (
|
Particularities for column attributes:
Attribute | Type | Required | Description |
---|---|---|---|
|
String |
yes |
The column names must not contain a prefix. They have to follow the convention |
|
Enum |
yes |
Defines whether the property can have a maximum of one or an arbitrary number of values. For a column definition, both enums |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<propertyTableDefinition>
<id>aTableProperty</id>
<propertyType>table</propertyType>
<cardinality>single</cardinality>
<required>false</required>
<propertyStringDefinition>
<id>col0</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyIntegerDefinition>
<id>col1</id>
<propertyType>integer</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyIntegerDefinition>
<propertyDateTimeDefinition>
<id>col2</id>
<propertyType>datetime</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyDateTimeDefinition>
<propertyDecimalDefinition>
<id>col3</id>
<propertyType>decimal</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyDecimalDefinition>
</propertyTableDefinition>
Structured Data Property Definitions
As of version 2021 Summer, yuuvis® Momentum offers a property type for the storage of structured data in JSON format. Thus, it is possible to store interleaved data structures in a queryable way without defining each single sub-property in the schema.
The structured data properties should NOT be considered to replace the concept of a well-defined schema. They should be used only if the handling of objects' metadata via the conventional property definitions is not reasonable. |
Particularities for structured data property attributes:
Attribute | Type | Required | Description |
---|---|---|---|
|
Enum |
yes |
Defines whether the property can have a maximum of one or an arbitrary number of values. For a structured data property definition, only |
Pre-defined limitations (cannot be overwritten by property attributes):
-
The value for a structured data property has to be a valid JSON structure. It is not allowed to pass a single string, boolean or other variable format.
Display valid and invalid example values.
Valid example value"appTable:customerdetails": { "value": { "id": 2982, "uid": "711e1858-eb24-4183-8743-0292c7b9b93b" } }
Invalid example value 1 - NOT allowed"appTable:customerdetails": { "value": "{\"id\":2982,\"uid\":\"711e1858-eb24-4183-8743-0292c7b9b93b\"}" }
Invalid example value 2 - NOT allowed"appTable:customerdetails": { "value": true }
-
The maximum value for the total number of sub-properties within one JSON value is 500.
-
The maximum depth for JSON structure is 16.
-
The keys have to be strings not longer than 32 characters.
-
As of 2024 Spring: The keys have to follow the convention
[a-zA-Z][a-zA-Z0-9]*
(similar to property type IDs but without prefix).Up to 2023 Winter: The keys have to follow the convention
[a-z][a-z0-9]*
. -
Empty maps are not allowed in any position of the JSON and are replaced by
null
.
1
2
3
4
5
6
<propertyStructuredDataDefinition>
<id>customerdetails</id>
<propertyType>structureddata</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStructuredDataDefinition>
2.2.5. Object Type Definitions
Each object type definition belongs to one of the following base types.
base type | value for baseId attribute |
instantiable |
---|---|---|
document type |
|
yes |
folder type |
|
yes |
secondary object type (SOT) |
|
no |
General Object Type Attributes
All object type definitions have the following attributes:
Attribute | Type | Required | Description |
---|---|---|---|
|
|
yes |
The ID of the object type. It uniquely identifies the object type in the schema. |
|
URI |
no |
By using namespaces, it is possible to form groups of properties and object types. |
|
String |
no |
Describes the object type definition. |
|
Enum |
yes |
Specifies the base type of this object type. The following values are supported:
|
|
String |
no |
Reference by ID to a property. An object type definition can have an arbitrary number of property references. A tenant-specific object type can have references to both tenant-specific and global properties. |
Attributes for Document Type Definitions
Document type definitions have the following specific attributes:
Attribute | Type | Required | Description | ||
---|---|---|---|---|---|
|
Enum |
yes |
Specifies whether objects of this type must, must not, or may have content. Possible values are:
|
||
|
String |
no |
References the ID of a defined secondary object type. Can be specified multiple times to reference multiple SOTs. Additionally, it is possible to specify |
2.2.6. Attributes for Folder Type Definitions
Folder type definitions have the following specific attributes:
Attribute | Type | Required | Description |
---|---|---|---|
|
String |
no |
References the ID of a defined secondary object type. Can be specified multiple times to reference multiple SOTs. Additionally, it is possible to specify |
2.2.7. Secondary Object Type Definitions
A secondary object type (SOT) is abstract and cannot be instantiated. Instead, it can be referenced in document and folder object type definitions via their secondaryObjectTypeId
attribute.
There are two ways for SOTs to be referenced by an object in the schema definition: as static SOT or as floating SOT.
- Static SOT
-
<secondaryObjectTypeId static="true">INV</secondaryObjectTypeId>
If DMS objects are instantiated from an object type with such reference, the SOT will be assigned to them during their entire lifecycle.
- Floating SOT
-
<secondaryObjectTypeId static="false">INV</secondaryObjectTypeId>
If DMS objects are instantiated from an object type with such reference, the SOT is only assigned after explicit activation in the metadata. This allows for flexible typecasting.
Ones assigned to a DMS object, all properties collected in the SOT are available for that DMS object.
If an SOT contains a required property, it will be required for each DMS object with that SOT assigned to itself.
|
Secondary object type definitions have the following specific attributes:
Attribute | Type | Required | Description | ||
---|---|---|---|---|---|
|
Enum |
no |
Can substantiate the
For a finally instantiated DMS object, content will be
If |
Conflict situation leading to invalid documents
Any combination of at least once
|
Example schema containing SOTs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://optimal-systems.org/ns/dmscloud/schema/v5.0/dmsCloud-schema.xsd">
<propertyStringDefinition>
<id>appSot:dateOfReceipt</id>
<propertyType>date</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appSot:comment</id>
<propertyType>date</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appSot:invoiceNo</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appSot:paymentTerm</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<typeDocumentDefinition>
<id>appSot:document</id>
<baseId>system:document</baseId>
<propertyReference>appSot:dateOfReceipt</propertyReference>
<contentStreamAllowed>required</contentStreamAllowed>
<secondaryObjectTypeId>appSot:basicInfo</secondaryObjectTypeId>
</typeDocumentDefinition>
<typeSecondaryDefinition>
<id>appSot:basicInfo</id>
<baseId>system:secondary</baseId>
<propertyReference>appSot:comment</propertyReference>
</typeSecondaryDefinition>
<typeSecondaryDefinition>
<id>appSot:invoice</id>
<baseId>system:secondary</baseId>
<propertyReference>appSot:invoiceNo</propertyReference>
<propertyReference>appSot:paymentTerm</propertyReference>
</typeSecondaryDefinition>
</schema>
Consider the example schema above. If a document of the type appSot:document
is created, it may have values for the properties appSot:dateOfReceipt
and appSot:comment
.
For the appSot:dateOfReceipt
property, this is obvious, because there is a direct reference in the document type definition of appSot:document
.
The appSot:comment
property is not directly referenced but the definition of appSot:document
has a reference to the SOT appSot:basicInfo
which references the appSot:comment
property. Thus, both properties are available for creating documents.
Furthermore, a document of the type appSot:document
not only may have a value for appSot:comment
, it must have a value, because it is a required
property. It makes no difference, whether a document type references the property definitions directly or indirectly via a SOT reference.
2.2.8. Validation
It is not possible to post an invalid schema via yuuvis® Momentum API. A new schema is always validated before it is introduced into the system. Additionally, specific validation endpoints are available to check the new schema before sending an update request.
The response of schema validation (or update) endpoints are always structured as shown in the following example.
{
"validationErrors": [],
"changes": [{
"type": 1000,
"message": "Document type was removed.",
"id": "appEmail:obsoleteType",
"affectedObjects": {
"tenant1": 10,
"tenant2": 4
}
}, {
"type": 1200,
"message": "A property reference was removed from a document type.",
"id": "appEmail:email",
"reference": "appEmail:bcc",
"affectedObjects": {
"tenant1": 1,
"tenant2": 3
}
}
]
}
Failed Validation
If the schema is invalid, the corresponding validation errors are listed in validationErrors
Passed Validation
If the schema is valid, the validationErrors
list is empty. The schema can be (is) updated.
However, the new schema might define different structures for DMS objects that are not matched by previously imported objects. Thus, affected objects are invalidated as soon as the new schema is introduced into the system. Invalidated objects are still stored in the system, but their availability and behavior deviates from expectation as described in the following table and below.
The changes list in the validation request contains all detected differences between the new schema and the previously used schema that could lead to invalidation of existing DMS objects. The following table documents the detectable types of schema changes and their individual values/meanings of the sub-parameters for each element in the changes
list:
-
type
-
message
-
id
-
reference
-
if the validation (or update) endpoint is called with the query parameter
verbose=true
:affectedObjects
A non-empty changes list in the validation request does NOT prevent a schema update. |
type |
message |
id |
reference |
Description and Impact of Schema Update |
---|---|---|---|---|
1000 |
Document type was removed. |
ID of the removed document type |
- |
As it is not possible to replace the object type of existing objects, it is not possible to adjust affected objects. They cannot be updated anymore. |
1001 |
Folder type was removed. |
ID of the removed folder type |
- |
See impacts of change type 1000. |
1100 |
A secondary object type reference was removed from a document type. |
ID of the document type |
ID of the secondary object type |
If the corresponding SOT includes required properties, see the impacts of change type 1200. |
1101 |
A secondary object type reference was removed from a folder type. |
ID of the folder type |
ID of the secondary object type |
If the corresponding SOT includes required properties, see the impacts of change type 1200. |
1110 |
A document type got a new static secondary object type reference. |
ID of the document type |
ID of the secondary object type |
A static secondary object type reference was added to a document type definition. Or an existing non-static secondary object type reference on a document type definition became static. If the corresponding SOT includes required properties, see the impacts of change type 1300. |
1111 |
A folder type got a new static secondary object type reference. |
ID of the folder type |
ID of the secondary object type |
A static secondary object type reference was added to a folder type definition. Or an existing non-static secondary object type reference on a folder type definition became static. If the corresponding SOT includes required properties, see the impacts of change type 1300. |
1200 |
A property reference was removed from a document type. |
ID of the document type |
ID of the property |
Any metadata retrieval of affected objects excludes the removed property. Search result lists, e.g., are affected as well. However, the existing values remain in the database and the search index. Thus, in case of a removed string property, the existing values are still considered for full-text search. The corresponding values are removed automatically during the next PATCH or POST update on the affected objects. |
1201 |
A property reference was removed from a folder type. |
ID of the folder type |
ID of the property |
See impacts of change type 1200. |
1210 |
A property reference was removed from a secondary object type. |
ID of the secondary object type |
ID of the property |
See impacts of change type 1200. |
1300 |
A non-required property type became required. |
ID of the property |
- |
POST metadata updates on affected objects are only allowed if the new required property is properly added. |
1310 |
A required property reference was added to a document type, or a non-required property reference became required. |
ID of the document type |
ID of the property |
See impacts of change type 1300. |
1311 |
A required property reference was added to a folder type, or a non-required property reference became required. |
ID of the folder type |
ID of the property |
See impacts of change type 1300. |
1320 |
A required property reference was added to a secondary object type, or a non-required property reference became required. |
ID of the secondary object type |
ID of the property |
See impacts of change type 1300. |
2000 |
Content stream becomes required on a document type. |
ID of the document type |
- |
Updates on affected objects are only allowed if a binary content file is thereby added. |
2001 |
Content stream becomes not allowed on a document type. |
ID of the document type |
- |
Updates on affected objects are only allowed if a binary content file is thereby deleted. Thus, affected objects with a binary content file under retention cannot be updated via yuuvis® Momentum at all. |
2010 |
Content stream becomes required on a secondary object type. |
ID of the secondary object type |
- |
See impacts of change type 2000. |
2011 |
Content stream becomes not allowed on a secondary object type. |
ID of the secondary object type |
- |
See impacts of change type 2001. |
3000 |
The cardinality of a property becomes 'single'. |
ID of the property |
- |
Updates on affected objects are only allowed if the value of the modified property is properly replaced. Especially, pure tag and content operations are only allowed after a proper update of the metadata. |
Following schema changes are NOT detected during the validation, but can affect existing objects as well:
-
The type of a property definition changed. → See impacts of change type 3000.
-
The range of a property definition changed. → See impacts of change type 3000.
-
A default value was added to a property definition or reference. → The new default value is only used for the creation of new objects.
-
In a table property definition, the value for the queryable attribute was changed. → Affected objects can be adjusted via
commander
service. -
The base type of an object type changed from
system:folder
tosystem:document
with content stream required. → See impacts of change type 2000. -
The base type of an object type changed from
system:document
tosystem:folder
. → See impacts of change type 2001. -
The base type of an object type changed from
system:document
orsystem:folder
tosystem:secondary
. → See impacts of change type 1000.
2.2.9. Pre-defined System Schema
Some properties and object types are pre-defined for the entire system. Their definitions cannot be overwritten via yuuvis® Momentum API. However, their definitions are included in each retrieval of an applied tenant schema.
General System Properties
The following system properties are globally pre-defined and assigned to each DMS object. Some system properties are set by the system and some system properties can be set by the user.
Property | Type | Description | Set by |
---|---|---|---|
|
string |
Identifies the object in the database. |
system |
|
string |
identifies the base type of the object type specified in |
system |
|
string |
Required during an import and cannot be changed lateron. Identifies the object type the object instantiates. Secondary object types are not allowed. |
user |
|
JSON list of strings |
Contains the |
user |
|
string |
User ID of the user that has initially created the object. |
system |
|
string |
Date of the object’s creation in format |
system |
|
string |
User ID of the user that sent the last successful POST request on the object. |
system |
|
string |
Date of the last successful POST request on the object as a string in format |
system |
|
string |
During an import or update operation, the object can be assigned to an existing folder by referencing its |
user |
|
string |
Identifies the folder object type of the parent folder that is specified by |
system |
|
integer |
Integer object version number. Corresponds to the number of POST requests on the object starting with the initial creation. |
system |
|
string |
Identifies the tenant the object belongs to. |
system |
|
Hexadecimal lowercase string with maximum length 16 |
The trace ID of the import operation or last update operation. Unique process number of any operation. If not specified in the request, a random string value will be set. If the specified trace ID has less than 16 characters, the string is extended by adding |
user or system |
|
JSON table of strings and integers |
Contains the properties of the tags assigned to the object. |
user |
|
string |
Only available for documents. Secondary object type The binary content of the object cannot be changed or deleted before this date, but metadata updates are allowed. In an update request, the |
user |
|
string |
Only available for documents. Secondary object type This date defines the start of the retention time. It has to be earlier in time than the |
user |
|
string |
Only available for documents. Secondary object type If |
user |
Content Stream Properties
The following content stream properties are grouped in the contentStreams
section within DMS objects. These system properties are available for document objects containing binary content. Thus, their contentStreamAllowed
attribute has to be required
or allowed
. The properties in contentStreams
contain all information necessary to be able to handle binary content. Depending on the type of operation, different properties are required for import/update requests or are displayed in a response.
Property | Type | Description | In an Import/Update Request | In a Response |
---|---|---|---|---|
|
String |
Points to existing content within a repository. |
Required only for pointing to existing content during an import. If not specified, the system generates a UID. |
displayed |
|
Integer |
Length of the binary content, determined by the system. |
- |
displayed (if system could determine the value) |
|
String |
Mime type of the content file.
The If |
Scenario A: The In an import request, the automatically determined mimeType can be overwritten by specifying a value in the import JSON. Scenario B: In an import request via POST In a content update via POST |
displayed |
|
String |
Name of the content file. |
If In a content update via POST In an import request via POST |
displayed |
|
String |
SHA-256, automatically determined by `repository`service based on the binary content. Can be used to detect changes in the binary content. |
- |
displayed |
|
String |
ID of the repository that will be used for storage of the binary data. |
Required only for pointing to existing content during an import. If not specified, the default repository defined in the repository service configuration will be set. |
displayed |
|
String |
Path structure for the content file within the binary storage. |
Required only for pointing to existing content during an import if reconstruction is not possible with metadata information (e.g,, if a |
displayed if it was set
|
|
String |
Applies to compound documents only. Defines a certain segment of compound documents that should be provided for content retrievals. |
Optional in the import request body and only available for compound documents. |
displayed only if it was set |
|
String |
Assigns the corresponding multipart content. |
Required in the import request body. Not needed later on and therefore not stored in the system. |
- |
Document Object Type 'system:document'
This object type has automatically floating references on all SOTs that are available in the applied tenant schema. It is intended to simplify typecasting of document objects.
Secondary Object Type 'system:rmDestructionRetention'
This SOT allows to specify a retention for an individual DMS object.
2.3. Search Query Language
The query language based on CMIS serves to standardize DMS requests to the yuuvis® API system.
The CMIS query language consists of a subset of the SQL-92 grammar, augmented by a syntax for requesting full text. Thus, the CMIS query language provides a relational view of the data. The virtual tables requested in the FROM clause correspond to DMS object types and the virtual columns requested in the SELECT correspond to the CMIS properties (metadata fields).
2.3.1. Query Language Definition
A query is structured as follows
Position | Keyword | Value | Description |
---|---|---|---|
1 |
|
virtual column list |
property list (metadata fields) |
2 |
|
virtual table names |
object type list |
3 |
|
conditions |
limitations |
4 |
|
sorting specification |
sorting criteria |
-
use
*
as virtual column list to query all metadata fields -
it is possible to use the
SCORE()
function in the virtual columns list -
if
ORDER BY
is not specified, the result list is ordered by thesystem:creationDate
object property -
currently, only the query of a single object type is supported.
The default search on metadata fields is case-sensitive. A case-insensitive search is possible via the CASE_INSENSITIVE() function (as of 2024 Spring) or by means of a CONTAINS statement.
|
2.3.2. Simple 'SELECT' Queries
Queries on Object Types
-- Select all objects of type 'email'.
SELECT * FROM email;
-- Select the customer number and the date of all invoices.
SELECT custno,date FROM invoice;
Queries on Secondary Object Types (as of 2019 Winter)
The search result delivers the entire object and not only the properties of the specified secondary object type.
-- Select all objects of secondary object type system:rmDestructionRetention
SELECT * FROM system:rmDestructionRetention;
2.3.3. Queries with Aliases
Properties can be queried with an alias name. The values of these properties are returned in the result with the alias name. The alias can be specified by a space separated behind the property name or with the keyword AS
between property name and alias name.
-- Alias without keyword: Select the customer number with alias c and the date with alias d of all invoices.
SELECT custno c,date d FROM invoice;
-- Alias with keyword: Select the customer number with alias c and the date with alias d of all invoices.
SELECT custno AS c,date AS d FROM invoice;
2.3.4. Highlighting in Full-text Previews
The HIGHLIGHT()
function can be used within the SELECT
statement. Pass a string argument as shown in the example below. For this string, a full-text query is started. In the result list, all objects have an additional highlight
section that is a list of excerpts from the corresponding object’s text rendition containing the query term. The individual excerpt items are sorted by SCORE()
. Within the plain text of each excerpt, the found query term is highlighted by a surrounding <em></em>
.
Highlighting on large full-texts has high time and memory costs. Thus, the search engine limits the length of full-text for highlighting to 1.000.000 characters. Hits of the query term that may occur in the remaining part of the full-text are found but not represented in the highlight section of the search result.
|
-- Search objects containing 'exiting' in their full-text rendition.
-- Display the object ID and full-text excerpts with highlighted search term.
SELECT system:objectId, HIGHLIGHT('exciting') FROM system:object;
{
"objects": [
{
"properties": {
"system:objectId": {
"value": "2be7b709-745a-4c0c-809e-512f9850876b"
}
},
"highlight": [
"this could also be an <em>exciting</em> custom content",
"what else could be as <em>exciting</em> as this feature"
]
}
],
"numItems": 1,
"hasMoreItems": true,
"totalNumItems": 662763
}
Options for Highlighting
To execute the query, the SQL statement is embedded in a JSON structure as described later. For the HIGHLIGHT()
function, the options
section can be used to configure the following highlight
parameters. If not explicitly specified in each request JSON, the default values are used.
Parameter | Type | Description | Default value |
---|---|---|---|
|
string |
Type of highlighter |
|
|
int |
Length of a single full-text excerpt |
45 |
|
int |
Maximum number of full-text matches to be represented for each object |
30 |
|
string |
Fragmenter to be used. |
|
|
string |
Indication for start of query term highlighting. |
|
|
string |
Indication for end of query term highlighting. |
|
{
"query" : {
"statement" : "SELECT system:objectId, HIGHLIGHT('exciting') FROM system:object",
"skipCount" : 0,
"maxItems" : 1,
"handleDeletedDocuments" : "DELETED_DOCUMENTS_EXCLUDE",
"options": {
"highlight": {
"type": "plain",
"fragment_size": 45,
"number_of_fragments": 30,
"fragmenter": "span",
"pre_tag": "<em>" ,
"post_tag": "</em>"
}
}
}
}
2.3.5. Queries with Conditions
In the WHERE
clause, conditions can be formulated and combined with logical operators.
The following operators are supported:
-
comparison operators:
<
,>
,<=
,>=
,<>
,=
-
join operators:
AND
,OR
,NOT
-
additional predicates:
LIKE
,IN
,NULL
,CONTAINS
-
In the default configuration, the number of
AND
andOR
operators per condition is limited to 20.
Examples
-- Select all invoices in which the invoice amount is greater than 100.
SELECT * FROM invoice WHERE amount>100;
-- Select all invoices in which the invoice amount is greater than 100 and the supplier is 'ACME'.
SELECT * FROM invoice WHERE amount>100 AND supplier='ACME';
-- Select all invoices in which the invoice amount is greater than 100 or less than 10 and the supplier is either 'ACME', 'OS' or 'ICH'.
SELECT * FROM invoice WHERE (amount>100 OR amount<10) AND supplier IN ('ACME','OS','ICH');
Wildcard Example
Wildcard characters are used with the LIKE
operator. There are two wildcards used in conjunction with the LIKE
operator:
-
%
– The percent sign represents zero, one, or multiple characters -
_
– The underscore represents a single character
-- Select all invoices in which the supplier starts with 'ACM' and the index data field 'amount' is not NULL
SELECT * FROM invoice WHERE supplier LIKE 'ACM%' AND amount IS NOT NULL;
The LIKE expressions are limited by their number of included wildcards. Thus, a maximum number of 10 % and _ characters are allowed in one LIKE expression. The limit compliance is verified in the validation.
|
Case-(in)sensitive Metadata Search
As of 2024 Spring.
The CASE_SENSITIVE()
and CASE_INSENSITIVE()
functions are available for conditions on string metadata values. The combination with the =
, LIKE
or IN
operators is possible as shown in the following examples.
-- Select all invoices in which the supplier is 'GE'.
SELECT * FROM invoice WHERE supplier IS 'GE';
SELECT * FROM invoice WHERE supplier IS CASE_SENSITIVE('GE');
-- Select all invoices in which the supplier is 'ge', 'Ge', 'gE' or 'GE'.
SELECT * FROM invoice WHERE supplier IS CASE_INSENSITIVE('GE');
-- Select all invoices in which the supplier starts with 'ge', 'Ge', 'gE' or 'GE'.
SELECT * FROM invoice WHERE supplier LIKE CASE_INSENSITIVE('GE%');
-- Select all invoices in which the supplier is 'ge', 'Ge', 'gE', 'GE' or 'OS'.
SELECT * FROM invoice WHERE supplier IN (CASE_INSENSITIVE('ge'), 'OS');
The default behavior of the metadata search is case-sensitive. This default can be overwritten for an entire query request via the case_sensitivity
option in the JSON format. Thus, the example request below searches for all invoices in which the supplier is ge
, Ge
, gE
or GE
without the usage CASE_INSENSITIVE()
function in the SQL statement.
{
"query" : {
"statement" : "SELECT * FROM invoice WHERE supplier IS 'GE'",
"skipCount" : 0,
"maxItems" : 50,
"options": {
"case_sensitivity": "case_insensitive"
}
}
}
Priorities for overwriting case sensitivity
|
Full-Text Search with 'CONTAINS'
Basics for 'CONTAINS'
To perform full-text search, use CONTAINS
in the WHERE
clause. The string values specified in the CONTAINS
statements are handled without regards to case sensitivity. Their length might be limited by your search engine.
For the result list of a full-text search, it might be useful to sort it by SCORE()
. The best matching results will be presented on top of the result list. If ORDER BY
is not specified, the result list is ordered by the system:creationDate
object property by default.
Please also note that your search engine might need a suitable plug-in and corresponding configuration for optimal search behavior in your language. If you changed the configuration of your search engine, all objects that are imported afterwards will be indexed as defined by the new configuration. All objects that are already in the system remain unchanged and can be searched as before the configuration update. If you need all objects indexed which refer to the new configuration, you need a reindexing via your search engine.
If a field name is specified, only this field is checked for the search term.
-- Select all types in which the term 'QUERY' was found in field 'name'.
SELECT * FROM type WHERE name CONTAINS('QUERY');
If no field name is specified, a full-text search will be performed. This search includes:
-
Each string value within the
properties
metadata section that matches the following conditions:-
It belongs to a defined property, for which the attribute
fulltextIndexed
is NOT set tofalse
AND that has nosystem:
prefix. -
The property must be a string property, a string column of a table property or a structured data property.
-
-
The string values for tag names.
-
The string value for
system:contentStreamFileName
within thecontentstreams
properties. -
If available, each text rendition that was estimated by the
contentanalyzer
service or set manually.
-- Select all types in which in full-text 'QUERY' was found.
SELECT * FROM type WHERE CONTAINS('QUERY');
-- Use 'SCORE()' for the order of the result list instead of the default order by 'system:creationDate'.
SELECT *,SCORE() s FROM type WHERE CONTAINS('QUERY') ORDER BY s ASC;
As of 2023 Winter, it is possible to separately search the text renditions or the mentioned string values within the metadata.
-
Use
system:content
instead of a property name to search only the text renditions.ExampleSELECT * FROM system:document WHERE system:content CONTAINS('search me within the text renditions only')
-
Use
system:metadata
instead of a property name to search only the above described string metadata values.ExampleSELECT * FROM system:document WHERE system:metadata CONTAINS('search me within the string metadata only')
Logical Operators
The following logical operators are supported:
Operator | Description | Syntax | ||
---|---|---|---|---|
+ |
The full-text must contain the term behind the operator. There is no blank space between operator and term. |
+<term> |
||
- |
The full-text must not contain the term behind the operator. There is no blank space between operator and term. |
-<term> |
||
AND |
The full-text must contain both terms connected with the operator. The operator is only identified in capital letters and separated by exactly one blank space from the two terms it is connecting.
|
<term1> AND <term2> |
||
OR |
The full-text must contain at least one of the two terms connected with the operator. The operator is only identified in capital letters and separated by exactly one blank space from the two terms it is connecting.
|
<term1> OR <term2> |
The examples will clarify the use of the individual operators.
- + Operator
-
If the + operator is applied to a term, only objects containing this term in their full-text will match the query. If further terms are specified without an additional + (or -) operator, they are allowed in the full-text but not required. Thus, they influence the ranking (higher score) of the found objects only. They do not have an impact on the number of found objects in the result itself.
-- Select all documents in which 'tree' was found. SELECT * FROM type where CONTAINS('apple +tree')
- - Operator
-
If the - operator is applied to a term, only objects not containing this term in their full-text will match the query. If further terms are specified without an additional - (or +) operator, they are allowed in the full-text but not required. Thus, they influence the ranking (higher score) of the found objects only. They do not have an impact on the number of found objects in the result itself.
-- Select all objects in which 'tree' was found. SELECT * FROM type where CONTAINS('apple -tree') -- Select all objects containing 'tree' and not containing 'pie' in their full-text. The optional words 'apple' and 'exceptional' influences the scoring only. SELECT * FROM type where CONTAINS('exceptional apple +tree -pie')
- OR Operator
-
All objects containing at least one of the connected terms in their full-text are matching the query. A space between several search term combinations is interpreted as logical OR operator (as long as no include or exclude search term condition is used).
-- Select all objects containing at least one of the words 'apple' or 'tree'. SELECT * FROM type where CONTAINS('apple tree') -- The query is equivalent to the previous one without 'OR' operator. SELECT * FROM type where CONTAINS('apple OR tree') Some more examples: -- Select all invoices in which in full-text either 'reminder', 'discount' or 'delay' was found. SELECT * FROM invoice WHERE CONTAINS('reminder discount delay'); -- Select all invoices which the invoice amount is greater than 1000 and in fulltext either 'reminder', 'discount' or 'delay' was found. SELECT * FROM invoice WHERE amount>1000 AND CONTAINS('reminder discount delay');
- AND Operator
-
All objects containing both terms connected with the AND operator in their full-text will match the query. However, we recommend to avoid the operator and apply the + operator to each individual term that should be contained in the object’s full-text.
-- Select all objects containing both words 'apple' and 'tree'. SELECT * FROM type where CONTAINS('apple AND tree') -- The query is equivalent to the previous one and recommended. SELECT * FROM type where CONTAINS('+apple +tree') -- The query is equivalent to the previous one and not recommended. SELECT * FROM type where CONTAINS('+apple AND +tree')
- Combination of Operators with Brackets
-
As of version 2022 Winter, it is possible to use round brackets within a CONTAINS statement in order to specify the evaluation order of operators.
-- Select all objects containing both words 'apple' and 'tree' or both words 'baking' and 'cakes'. SELECT * FROM type where CONTAINS('((apple AND tree) OR (baking AND cakes))')
Phrases
To search for a string consisting of several words in the exact same order (e.g., a sentence), use double quotation marks within the CONTAINS statement. Blank spaces are not interpreted as OR operator within these quotation marks.
-- Select all objects in which the phrase 'exceptional apple tree pie' was found.
SELECT * FROM type where CONTAINS('"exceptional apple tree pie"')
-- Select all invoices in which the amount is greater than 1000 and in full-text the sentence 'color picture 20x30' was found.
SELECT * FROM invoice WHERE amount>1000 AND CONTAINS('"color picture 20x30"');
Phrases are interpreted as terms. Thus, logical operators are applied to the entire phrase.
-- Select all documents in which 'exceptional pie' was found and 'apple tree' was not found.
SELECT * FROM type where CONTAINS('+"exceptional pie" -"apple tree"')
Boosting
Boosting can be applied to the list of matches of full-text search queries. The boost operator ^ influences the relevance of individual terms within a CONTAINS statement. Thus, the sorting of the objects in the hit list is directly influenced.
The relevance of individual terms is specified via a boosting factor. The larger the boosting factor, the higher the relevance of the corresponding term. Here, the ratio between the individual boosting factors is considered and not the absolute values.
To set the boosting factor, append the ^ operator and a decimal value without blank spaces to the corresponding term. A term without a specified boosting factor will get the default boosting factor 1.
-- Select all documents containing 'tree'. Prefer objects containing 'apple', 'pear' or 'chestnut'.
-- Prioritize 'pear' 4 times and 'chestnut' twice over 'apple'.
SELECT * FROM type where CONTAINS('apple pear^4 chestnut^2 +tree')
It is possible to reduce the relevance by applying a boosting value between 0 and 1.
-- Select all documents containing 'pie' and not 'tree'. Prefer objects containing 'apple' and especially 'pear'.
-- Avoid objects containing 'chestnut'.
SELECT * FROM type where CONTAINS('apple pear^2 chestnut^0.2 -tree +pie')
Fuzzy Search
In full-text search queries, partially matching objects can be provided as results. Thus, it is possible to search for similar terms or variant spellings.
The number of characters not matching the search term is called "edit distance". For each search term, a maximum edit distance can be defined that limits the number of unmatching characters.
Append the operator ~ followed by the integer maximum edit distance to a word within the CONTAINS statement. The values 0, 1 and 2 (default) are allowed for the edit distance. If the ~ operator is set without an edit distance, the default value 2 will be used. Since missing, redundant or reversed letters can be handled with edit distance 1, this value should be sufficient in most cases.
-- Select all objects containing words with maximum edit distance 1 to 'exceptionel' or 2 to 'cestnutt'.
-- E.g. objects containing 'exceptional' or 'chestnut' will be found.
SELECT * FROM type where CONTAINS('exceptionel~1 cestnutt~ ')
Proximity Search
It is possible to allow for reversed ordering of words in a phrase or to allow for additional words between the words of a phrase.
Here, the number of words not matching the specified phrase is called "edit distance". A maximum edit distance can be defined that limits the number of unmatching words.
Append the operator ~
followed by the integer maximum edit distance to a word within the CONTAINS statement.
-- Select all documents containing phrases of maximum edit distance 3 to the specified sentence.
SELECT * FROM type where CONTAINS('"Please be patient while this website is under construction."~3')
Escaping in 'CONTAINS' Statements
In a CONTAINS
expression, the system interprets specific symbols as operators. If you want to use those symbols as characters NOT beeing an operator, you have to escape them with a backslash (\
).
The following rules apply:
-
The symbols
<
and>
cannot be escaped. If they are used in terms, they will be ignored. -
All types of quotation marks used within a term have to be escaped.
-
The
^
symbol has to be escaped if not used as boosting operator. -
The
~
symbol has to be escaped if not used as fuzzy operator. -
Further special characters that have to be escaped:
+ - = & | ! ( ) { } [ ] * ? : \ /
-
If an operator
AND
/OR
is followed by a second operatorAND
/OR
, the second operator will be automatically escaped and interpreted as a termand
/or
.
Weighted Score
The SCORE
function returns the score values produced by the CONTAINS
function in the SEARCH_SCORE
field. The score value is a relative ranking, with values in the range of 0 to 1 and increases with the relevance. The SCORE
function can also be queried with an alias name.
-- Select all invoices and their score value where the invoice amount is greater than 1000 and in fulltext either 'reminder', 'discount' or 'delay' was found.
SELECT *,SCORE() FROM invoice WHERE amount>1000 AND CONTAINS('reminder discount delay');
-- With alias: Select all invoices and their score value where the invoice amount is greater than 1000 and in fulltext either 'reminder', 'discount' or 'delay' was found.
SELECT *,SCORE() score FROM invoice WHERE amount>1000 AND CONTAINS('reminder discount delay');
Full-text search only in certain fields:
-- Select all invoices and their score value where the field 'status' either contains 'reminder', 'discount' or 'delay'.
SELECT *,SCORE() FROM invoice WHERE status CONTAINS('reminder discount delay');
Searching Normalized Trace IDs
The TRACEID()
function can be used in WHERE
clauses. It normalizes a specified hexadecimal lowercase sting to the trace ID convention. Thus, you can search for your initially specified values for system:traceId
before they were normalized by the system.
Alternatively, it is possible to specify a trace ID in the header of the search request. This value can be referenced in the search query with the @traceid
parameter. It is normalized by the system as well.
Example:
-
Import a DMS object with specified
"system:traceId": {"value": "1234"}
. -
The value will be normalized and stored as
"system:traceId": {"value": "0000000000001234"}
. -
The DMS object can NOT be found by this search query:
SELECT * FROM system:object WHERE system:traceId = '1234'
-
The DMS object can be found by the following queries:
--- normalization by user SELECT * FROM system:object WHERE system:traceId = '0000000000001234' --- normalization by system SELECT * FROM system:object WHERE system:traceId = TRACEID('1234') --- normalization by system, using value '1234' in X-B3-TraceId request header SELECT * FROM system:object WHERE system:traceId = @traceid
2.3.6. Sorting with 'ORDER BY'
To sort the result list, use the ORDER BY
clause. If ORDER BY
is not specified, the result list is ordered by the system:creationDate
object property by default.
-- Select all invoices where the invoice amount is greater than 1000, with the result list sorted in descending order of the invoice amount.
SELECT * FROM invoice WHERE amount>1000 ORDER BY amount DESC;
-- Select all invoices where the invoice amount is greater than 1000,
-- with the result list sorted in descending order of the invoice amount and in ascending order of the date.
SELECT * FROM invoice WHERE amount>1000 ORDER BY amount DESC, date ASC;
In ORDER BY
clauses, you can use the alias names given in the column definitions.
-- Select the invoice amount with alias 'b' of all invoices where the invoice amount is greater than 1000,
-- with the result list sorted in descending order of the alias b (invoice amount).
SELECT amount b FROM invoice WHERE amount>1000 ORDER BY b DESC;
To sort by the score value, you must assign an alias name to the SCORE()
function.
-- Select all invoices and their score value where the field 'status' either contains 'reminder',
-- 'discount' or 'delay', with the result list sorted in ascending order of alias s (score value).
SELECT *,SCORE() s FROM invoice WHERE status CONTAINS('reminder discount delay') ORDER BY s ASC;
2.3.7. Aggregations
Functions 'GROUP BY' and 'COUNT(*)'
To determine the number of objects with special properties, queries can be aggregated. All objects with the same entry in the field specified after the GROUP BY
clause are summarized. The number of objects is returned to the field OBJECT_COUNT
without the assignment of aliases.
-- Select the number of objects (system:object) with type specification, aggregated by the type of the object.
SELECT COUNT(*),type FROM system:object GROUP BY type;
It is also possible to aggregate several fields. In this case, all combinations of the fields mentioned are returned.
-- Select the number of objects (system:object) with type and title specification, aggregated by the type and title of the object.
SELECT COUNT(*),type,title FROM system:object GROUP BY type,title;
The GROUP BY
function can be used without the COUNT(*)
function. Then all combinations of the mentioned fields are returned without their numbers.
-- Select 'type' of all objects (system:object), aggregated by the type of the object.
SELECT type FROM system:object GROUP BY type;
To sort the result list of an aggregation, use the ORDER BY clause, with or without alias.
-- Select the number of objects (system:object) with type specification,
-- aggregated by the type of the object, with the result list sorted in ascending order of 'type'.
SELECT COUNT(*),type FROM system:object GROUP BY type ORDER BY type ASC;
-- With alias: Select the number and 'type' with alias 't' of all objects (system:object),
-- aggregated by 'type', with the result list sorted in descending order of alias t (type).
SELECT COUNT(*),type t FROM system:object GROUP BY type ORDER BY t DESC;
In order to be able to sort by the score value, you must assign an alias name to the SCORE()
function.
-- Select the number with alias 'c' and 'type' of all objects (system:object), aggregated by 'type',
-- with the result list sorted in descending order of alias c (number of objects).
SELECT COUNT(*) c,type FROM system:object GROUP BY type ORDER BY c DESC;
Function 'SUM()'
As of 2023 Autumn.
The SUM()
function can be used in the SELECT
statement of the search query. Similar to the SQL SUM function, it calculates the sum of numeric values for a specified numeric property. The result is retrieved as a single entry in the result list.
|
- Simple Example
-
-- Sum the values of all 'amount' properties SELECT SUM(amount) FROM system:object;
- Conditions combined with 'SUM()'
-
The
SUM()
function can be combined with aWHERE
statement that specifies conditions.-- Sum the value of all 'amount' properties for objects created today SELECT SUM(amount) FROM system:object WHERE system:creationDate IN today();
- Aliases for 'SUM()'
-
It is possible to set an alias as which the
SUM()
result will be displayed.-- Sum the value of all 'amount' properties , return them with alias 'totalsum' SELECT SUM(amount) AS totalsum FROM system:object;
- Multiple 'SUM()' Requests
-
Within one search query, multiple
SUM()
requests can be processed.-- Sum the value of all 'amount' and all 'item' properties SELECT SUM(amount) AS totalsum, SUM(items) totalitems FROM system:object;
- Applying 'SUM()' to Aggregations
-
As the
SUM()
function is a specific type of aggregation, it can be applied to other aggregations viaGROUP BY
as well.-- Sum the value of all 'amount' properties, grouped by 'supplier' SELECT supplier, SUM(amount) AS totalsum FROM system:object GROUP BY supplier;
- Sorting by 'SUM()' Results
-
To sort by a
SUM()
result, it is required to specify an alias.-- Sum the value of all 'amount' properties, order them descending SELECT SUM(amount) AS totalsum FROM system:object ORDER BY totalsum DESC;
- Constants passed to 'SUM()'
-
If a constant is passed to the
SUM()
function, it is used as scalar factor to be multiplied by the number of search results.-- Sum the value with constant 10, result should be 10x the count of hits SELECT SUM(10) AS totalsum FROM system:object;
2.3.8. Provided Date Functions in 'WHERE' Clauses
The query language provides some frequently used time and time span functions for WHERE
clauses.
-
today()
- a date field contains today’s date -
yesterday()
- a date field contains yesterday’s date -
thisweek()
- a date field contains this week’s date, a week starts on Monday and ends on Sunday -
lastweek()
- a date field contains last week’s date, a week starts on Monday and ends on Sunday -
thismonth()
- a date field contains this month’s date -
lastmonth()
- a date field contains last month’s date -
thisyear()
- a date field contains this year’s date -
lastyear()
- a date field contains last year’s date -
now()
- the current date -
dateadd(interval, number, date)
- adds a date interval to a date and returns the date.-
valid
interval
values:year
,yyyy
,yy
= Year;quarter
,qq
,q
= Quarter;month
,mm
,m
= month;dayofyear
= Day of the year;day
,dy
,y
= Day;week
,ww
,wk
= Week;weekday
,dw
,w
= Weekday;hour
,hh
= hour;minute
,mi
,n
= Minute;second
,ss
,s
= Second;millisecond
,ms
= Millisecond -
number
can be a positiv or negative integer value -
date
is a valid ISO8601 date value of the formatyyyy-MM-dd’T’HH:mm:ssZZ
(e.g.,1970-01-01T00:00:00+0000
) or a function which delivers a date value of this format.
-
SELECT ... FROM ... WHERE system:creationDate IN today();
SELECT ... FROM ... WHERE rmDestructionDate > today();
SELECT contentStreamId, fileName, repositoryId FROM system:object WHERE system:creationDate IN lastmonth();
SELECT * FROM document WHERE system:lastModificationDate IN today() AND system:creationDate IN lastyear() ORDER BY system:creationDate DESC;
SELECT COUNT(*) c, system:creationDate FROM system:object WHERE system:creationDate IN thisyear() GROUP BY system:creationDate ORDER BY c DESC;
SELECT * FROM system:object WHERE system:rmDestructionDate < now();
SELECT * FROM system:object WHERE system:creationDate < dateadd('day',35,'2018-09-20T08:37:26.280Z');
SELECT * FROM document WHERE system:lastModificationDate > dateadd('year',-1,now());
2.3.9. Queries on 'contentstream' Fields
Additional to property fields of a DMS object, all contentstream fields can be queried in SELECT
statements as described above.
SELECT contentStreamId, fileName, repositoryId FROM system:object;
SELECT * FROM document WHERE mimeType'message/rfc822' ORDER BY title DESC;
SELECT COUNT(*) c, fileName FROM system:object GROUP BY fileName ORDER BY c DESC;
2.3.10. Queries on Queriable Tables
As of version 2020 Winter, table cells can be accessed using the format in the following example:
-- syntax of table cell access
SELECT * FROM system:object WHERE queriable_table[row].column = value;
-- examples
SELECT * FROM system:object WHERE queriable_table[row].columnx = value;
SELECT queriable_table.nickname, queriable_table.name FROM system:object WHERE queriable_table[row].columnx LIKE 'steven';
SELECT * FROM system:object WHERE (queriable_table[5].age <= 55 AND queriable_table[6].age >= 22) OR queriable_table[6].age > 6;
SELECT * FROM system:object WHERE queriable_table[2].name IN ('Erwin', 'Max');
SELECT * FROM system:object WHERE queriable_table[3].name CONTAINS('Arno');
SELECT * FROM system:object WHERE queriable_table[4].city IS NULL;
SELECT * FROM system:object WHERE queriable_table[4].city IS NOT NULL;
SELECT * FROM system:object WHERE queriable_table[5].date > lastyear();
Between the SELECT
and FROM
keywords, one or more table columns can be referenced with the syntax tablename.columnname
as shown in the second example query above. The query will then return only the selected columns, in the example the columns nickname
and name
of the table queriable_table
. Otherwise, like in the other examples above where the * symbol is placed between the SELECT
and FROM
keywords, the entire table will be returned.
The conditions are specified in the same way like in single query calls. Date functions can be used, too.
ORDER BY
and GROUP BY
are not supported on tables.
To reference any column or any row in the condition, the *
symbol can be used as wildcard, as shown in the following examples:
-- columnx should have the given value in any row
SELECT * FROM system:object WHERE queriable_table[*].columnx = value;
-- any column should have the given value in rowx
SELECT * FROM system:object WHERE queriable_table[rowx].* = value;
-- any table cell should have the given value
SELECT * FROM system:object WHERE queriable_table[*].* = value;
For combined queries within one column of a table, there is a special syntax as shown in the code block below. Examples are provided as well.
-- syntax of table cell access
SELECT * FROM system:object WHERE queriable_table[row].(column_condition_1 AND/OR ... AND/OR column_condition_x);
SELECT * FROM system:object WHERE queriable_table[*].(column_condition_1 AND/OR ... AND/OR column_condition_x);
-- examples
SELECT * FROM system:object WHERE queriable_table[*].(name IN ('Erwin', 'Max') AND age >= 22);
SELECT * FROM system:object WHERE queriable_table[5].((name CONTAINS('Arno') AND age >= 22) OR city IS NULL);
SELECT * FROM system:object WHERE queriable_table[*].((name CONTAINS('Arno') AND age >= 22) OR (city IS NULL and date <= lastyear())) AND system:creationdate IN thisyear();
Within the brackets, any complex condition statement created from the set of conditions on properties described in the sections above can be queried, where each single condition will be applied on the specified row. If you use the wildcard *
as row number, each table row will be tested on the complex condition. For a query match, a row has to be found for which the whole condition set is true.
As shown in the last two lines of the code block above, Combined queries on a row can also be used in combination with further conditions.
2.3.11. Queries on Tags
As of version 2020 Summer, tags can be assigned to objects. The tag properties are searchable by means of queries. Since the tag properties are stored in table format, the queries are defined like queries on tables. Each tag corresponds to one row of the table property system:tags that is assigned to every object. The row is indicated by the value of the corresponding tag’s name. The four available columns are the same for all tags: name, state, creationDate and traceId. The following code block shows examples:
SELECT * FROM system:object WHERE system:tags[*].creationDate=TODAY();
SELECT * FROM system:object WHERE system:tags[*].name='ren:ocr';
SELECT * FROM system:object WHERE system:tags[ren:ocr].state=2;
SELECT * FROM system:object WHERE system:tags[*].(state=2 AND creationDate=TODAY());
SELECT * FROM system:object WHERE system:tags IS NULL;
SELECT * FROM system:object WHERE system:tags[ren:ocr1] IS NULL;
Of course, the queries can be combined with any other valid query as can be seen in the following examples:
-- search for objects have a tag created today and with the state 2
SELECT * FROM system:object WHERE system:tags[*].(state=2 AND creationDate=TODAY());
-- search for objects having the tag 'analysis' with the state 1 that were created yesterday
SELECT * FROM system:object WHERE system:tags[analysis].state=1 AND where system:creationDate=YESTERDAY();
2.3.12. Queries on Structured Data
As of version 2021 Summer, structured data properties can be used to assign an arbitrary JSON structure to objects. The structured data properties are stored similarly to table properties and are thus searchable by means of similar queries. The addressing of individual keys within the JSON structure is inspired by the concept of JSONPath.
Conditions on Structured Data
The following code block shows examples where objects of type order are searched that match the corresponding WHERE condition. The example property customerdetails
is a structured data property referenced in the object type definition for order. If objects are found, the values for the structured data property customerdetail
will be returned in JSON format for each of them.
-- Search for objects where 'customerdetails' contains the first-order key 'id' with value '2982'.
SELECT customerdetails FROM order WHERE customerdetails.id = 2982
-- Search for objects where 'customerdetails' contains the first-order key 'words' beeing a list with an existing value for index 10.
SELECT customerdetails FROM order WHERE customerdetails.words[10] IS NOT NULL
-- Search for objects where 'customerdetails' contains the first-order key 'words' beeing a list that contains the entry 'milk' at an arbitrary index.
SELECT customerdetails FROM order WHERE customerdetails.words[*] = 'milk'
-- Search for objects where 'customerdetails' contains the first-order key 'sentences' beeing a list that contains the term 'milk' in the second element.
SELECT customerdetails FROM order WHERE customerdetails.sentences[1] CONTAINS('milk')
-- Search for objects where 'customerdetails' contains the first-order key 'food' containing the second-order datetime key 'lastcooked' that has to be a value earlier than last year.
SELECT customerdetails FROM order WHERE customerdetails.food.lastcooked < LASTYEAR()
-- Search for objects where 'customerdetails' contains 'jelly' in the value for the key 'ingredient' that can be at any hierarchical level within the JSON.
SELECT customerdetails FROM order WHERE customerdetails..ingredient CONTAINS('jelly')
-- Search for objects where 'customerdetails' contains 'jelly' in the value for the key 'ingredient' that can be at any hierarchical level within the JSON,
-- but needs to have a direct or indirect parent node 'food'.
SELECT customerdetails FROM order WHERE customerdetails..food..ingredient CONTAINS('jelly')
Restriction Possibilities for Responses
To return only a sub-structure of the JSON value for a structured data property, specify the corresponding key as SELECT
statement:
SELECT customerdetails.uid FROM order
To return multiple sub-structures, separate them by comma:
SELECT customerdetails.uid,customerdetails.word FROM order
If you specify an index within a list, the values for the list elements with lower indices will be replaced by null in the return statement:
-- The query starting with ...
SELECT customerdetails.words[2] FROM order
-- ... will result in the return statement:
{
"properties": {
"appTable:customerdetails": {
"value": {
"words": [
null,
null,
"water"
]
}
}
}
}
To return sub-structures located at any hierarchical level within the JSON value, use .. as shown in the examples below.
-- Search for objects of type order and display only key-value mappings for keys 'uid'.
SELECT customerdetails..uid FROM order
-- Example response:
{
"properties": {
"appTable:customerdetails": {
"value": {
"uid": "711e1858-eb24-4183-8743-0292c7b9b93b",
"food": {
"uid": "7aa4a2f2-3dc0-420c-a0d7-edc6af3619de"
}
}
}
}
}
-- Search for objects of type order and display only key-value mappings for keys 'uid' that have a direkt or indirect parent node 'food'.
SELECT customerdetails..food..uid FROM order
-- Example response:
{
"properties": {
"appTable:customerdetails": {
"value": {
"food": {
"uid": "7aa4a2f2-3dc0-420c-a0d7-edc6af3619de"
}
}
}
}
}
2.3.13. Queries on Audit Entries
Audit entries can be queried by querying the object type system:audit
.
If you search by traceId , please note that the values are normalized if necessary as described here.
|
-- Select all audit entries
SELECT * FROM system:audit;
-- Select all audit entries for a specific traceId
SELECT * from system:audit WHERE traceid = '0000000000543221'
-- Select all audit entries created yesterday
SELECT * from system:audit WHERE creationDate IN YESTERDAY()
Audit entries are stored within a relational database. Thus, to query audit entries full-text queries and the return of the total amount of matching items totalNumItems within the result cannot be supported:
-
no queries with
CONTAINS()
-
no queries using scoring
SCORE()
-
no
totalNumItems
within the result set
All other features will be provided as described above.
2.3.14. Query JSON Format
A search can be called using the POST /api/dms/objects/search
endpoint by giving the following JSON structure:
{
"query" : {
"statement" : "SELECT * from sysemail WHERE email = @emailAddress AND sysfrom IN @from AND CONTAINS(@text)",
"skipCount" : 0, // optional for Paging
"maxItems" : 50, // optional for Paging
"useCache" : true, // optional
"handleDeletedDocuments" : "DELETED_DOCUMENTS_EXCLUDE", // optional DELETED_DOCUMENTS_INCLUDE | DELETED_DOCUMENTS_ONLY | DELETED_DOCUMENTS_EXCLUDE default: DELETED_DOCUMENTS_EXCLUDE
"parameters": { // optional, only if @ parameter occurs in statement
"emailAddress": "'info@optimal-systems.de'",
"text": "'Meeting'",
"from": "('hallo@huhu.de','info@huhu.de')"
}
}
}
-
The field
statement
contains the SQL query. -
skipCount
(default: 0) defines the number of skipped objects from which themaxItems
(default: 50) number of found objects will be delivered. This defines the paging of the search call. -
The field
useCache
(default:true
) defines if this request should be cached in search engine’s Shard request cache. -
Within a default search, all objects marked as deleted will be excluded (
DELETED_DOCUMENTS_EXCLUDE
). By using the optional fieldhandleDeletedDocuments
, this behaviour can be changed in including this objects (DELETED_DOCUMENTS_INCLUDE
) or delivering only deleted objects (DELETED_DOCUMENTS_ONLY
).
Using Parameters
Within an SQL statement, some predefined parameters can be referenced. By @userId
the ID of the actual user (taken from the user session) and by @userRoles
the roles of the actual user (also taken from the user session) can be referenced for replacement at runtime. As of 2023 Summer, @abac.<key>
is available as well.
{
"query" : {
"statement" : "SELECT * from system:object WHERE system:createdBy = @userId AND system:roles IN @userRoles"
}
}
The JSON field parameters can be used to define parameter (reserved names: userRoles
, userId
, abac
) values which can be referenced by @<parameter>
within a preformed SQL statement for replacement at runtime. The reserved parameter names userRoles
, userId
cannot be used for own definition of a parameter. A given definition under this names affects an exception.
{
"query" : {
"statement" : "SELECT * from system:object WHERE email = @emailAddress AND email:from IN @from AND CONTAINS(@text)",
"parameters": { // optional, only if @ Parameter occurs in statement
"emailAddress": "'info@optimal-systems.de'",
"text": "'Meeting'",
"from": "('hallo@huhu.de','info@huhu.de')"
}
}
}
2.4. Document Lifecycle
2.4.1. Synchronous or Asynchronous
In document lifecycle management, multi-stage and asynchronous processes are not uncommon — quite the contrary. The first process steps are carried out with the highest priority. More complex and currently not absolutely essential process steps are carried out asynchronously with a lower priority. This saves time, and carrying out operations in parallel lets you distribute resources more evenly.
Parameter 'waitForSearchConsistency' for Endpoints with Effect on the Search Index
As of version 2022 Autumn, some processes that lead to an update of the index of the search engine can be called with the query parameter waitForSearchConsistency
.
Value of 'waitForSearchConsistency' | Processing | Description | Advantage | Disadvantage |
---|---|---|---|---|
|
synchronous |
The success response of the corresponding endpoint is returned after the successful update of the search index. |
The changes are available even for search requests that are sent immediately after the synchronous processing. |
The waiting time before the response is rather long. |
|
asynchronous |
The success response of the corresponding endpoint does not wait for the update of the search index. |
The waiting time for the response is far shorter. |
Search requests sent immediately after the change request may be processed before the search index is updated. |
The update and import endpoints listed below accept an optional query parameter waitForSearchConsistency
.
Endpoints | Default for 'waitForSearchConsistency' |
---|---|
Import: |
|
Metadata update:
|
|
Content update:
|
|
Restore:
|
|
Deletion:
|
|
Tagging:
|
|
Text rendition:
|
|
2.4.2. Tagging
To resume a process chain, additional information about the current state of the process is necessary. In order to not mix an object’s metadata with its state data, there is the possibility to tag objects. Pure tagging operations do not trigger the creation of new object versions.
Objects can be searched by tags and selected for the next process step. All tagging activities are recorded in the audit trail.
Characteristics of Tags
Difference between metadata and tags:
-
Tags do NOT belong to the metadata and thus do not need to be defined in the schema.
-
Tags are stored together with the object as value for the
system:tags
property similar to metadata. -
Pure tag operations do NOT lead to the creation of a new object version.
-
Tags can only be attached to the current version of an object, whereas previous versions cannot have tags.
-
For version-specific information, metadata provide the suitable options. They have to be defined in the schema.
State information:
-
Tags describe the state of an object in a process chain. The state information is specified via an integer value.
Tracing information:
-
Tags are provided with a process identification that allows to retrace tag operations and tune the update or deletion permissions for the tag.
Assignment:
-
Tags can be added to any object during object creation, during metadata updates or completely independent via a tagging endpoint.
-
As of 2024 Spring, tags can be automatically assigned during specific operations on DMS objects via lifecycle hooks.
-
Multiple tags can be added to one object.
-
The number of tags assigned to one object is limited to 50.
Querying on tags:
-
The properties of tags are included in the searchable data.
-
Tags are queried similar to table properties.
Behavior during POST metadata updates:
-
If the
system:tags
property is specified in the request body,-
all included tags are assigned to the new object version with the given name and state. The same value as
system:lastModificationDate
andsystem:traceId
will be set automatically for creationDate and traceId respectively for all of them. -
each tag that is not included is deleted. The new object version will not have that tag.
-
-
If the property
system:tags
is NOT specified in the request body or is set to null, all tags will be deleted. The new object version will not have any tag.
Behavior during PATCH metadata updates:
-
If the
system:tags
property is specified in the request body,-
all included tags are assigned to the new object version.
-
each tag that is not included is deleted. The new object version will not have that tag.
-
-
If the
system:tags
property is NOT specified in the request body, all tags are transferred to the new object version. Their state, creationDate and traceId remain unchanged. -
If the
system:tags
property is set to null, all tags will be deleted. The new object version will not have any tag.
Behavior during POST updates of the binary content file:
-
If the tag name ends with the suffix
:resistant
, the tag is transferred to the new object version. Its state remains unchanged. -
If the tag name does NOT end with the suffix
:resistant
, the tag is deleted. It will not be assigned to the new object version.
Behavior during POST multipart update of metadata and content (as of 2024 Spring):
-
If the
system:tags
property is specified in the request body,-
each tag that is not included is deleted. The new object version will not have that tag.
-
all included tags are assigned to the new object version with the given
name
andstate
. The same value assystem:lastModificationDate
andsystem:traceId
will be set automatically forcreationDate
andtraceId
respectively for all of them.ExceptionEach non-resistant tag that is specified in the request body with an exact copy of a previously existing tag is deleted. It is assumed that the tag is not deliberately set, but simply copied from the current object. -
Especially, if the whole property
system:tags
specified in the request body equals thesystem:tags
of the current object, the behaviour is like the update of the binary content file: resistant tags survive, non-resistant tags are deleted.
-
-
If the property
system:tags
is NOT specified in the request body or is set tonull
, all tags will be deleted. The new object version will not have any tag.
Behavior during POST restoring actions of an old version (as of 2022 Spring):
-
If the tag name ends with the suffix
:resistant
, the tag is transferred to the new object version. Its state remains unchanged. -
If the tag name does NOT end with the suffix
:resistant
, the tag is deleted. It will not be assigned to the new object version.
Any tag operation is documented in the object audit trail.
Tag Properties
Tags are defined by the following properties:
Property | Type | Description | In a request |
---|---|---|---|
|
String |
Name of the tag for identification. It has to be unique for the corresponding object. The tag names are validated during a tag creation or update process. To pass the validation, they have to match the regular expression [a-z](:?[a-z]) and must not be longer than 32 characters (as of 2022 Spring, no longer than 128 characters). As of version 2021 Summer, the suffix :resistant triggers a specific behavior of the tag. If a tag name matches the expression [a-z](:?[a-z]):resistant, the tag will behave like a resistant tag as described below. |
required |
|
Integer |
Represents the status of the corresponding object in a process chain. |
required |
|
String |
Date and time of the last modification of the tag. It is set automatically by the system. |
optional, only available in search queries |
|
Hexadecimal lowercase string with maximum length 16 |
Process identification of any tag operation. If not specified in the request, a random String value will be set after the tag operation. In a tag update or delete request, the request parameter traceIdMustMatch can be set to true. The operation will be done only if the traceId of the call matches the current traceId of the requested tag. After such update processes, the traceId of the updated tag will be the same as before. Per default, |
optional, specified by means of the HTTP header |
In a request, the corresponding properties are included directly in the URL for the call of the endpoint. In contrast, if tags are displayed in a response body, their properties are listed as a part of a JSON structure in the value of the system:tags
property.
Tagging Endpoints
The following endpoints for pure tag operations do not trigger a new version of the corresponding object, but only a new entry in the audit trail:
-
Retrieve object tags by ID – GET
/api/dms/objects/{objectId}/tags
-
Add object tag by ID – POST
/api/dms/objects/{objectId}/tags/{name}/state/{state}
-
Update object tag by ID – POST
/api/dms/objects/{objectId}/tags/{name}/state/{state}?overwrite=true
-
Delete object tag by ID – DELETE
/api/dms/objects/{objectId}/tags/{name}
-
Add/update object tag by search query – POST
/api/dms/objects/tags/{name}/state/{state}?query=<SQL>
Automated Tagging
As of version 2024 spring, tags can be automatically assigned or updated via lifecycle hooks.
Resistant Tags
As of version 2021 Autumn, it is possible to assign resistant tags that are automatically transferred to the new version of an object created during an update of the binary content file.
The resistant tags will be removed from the old object version and assigned to the new object version. As usual, the previous object version will not have any tags afterwards. However, the new version will have all the resistant tags assigned to it that were originally assigned to the previous version. Conventional non-resistant tags will not be reassigned to the new object version.
Resistant tags are identified by the suffix :resistant
at the end of the tag name.
The tag name including the suffix must not exceed the length limit of 128 characters. |
2.4.3. Typecasting
By assigning or removing secondary object types (SOTs) to DMS objects, it is possible to change their set of available properties during lifecycle. This can be used to realize typecasting.
To assign a secondary object type, the target DMS object’s type (system:objectTypeId
) must match one of the following prerequisites:
- (A) Floating reference on the SOT
-
If the DMS object has any user-defined object type, this type has to contain a reference on the SOT in its schema definition. This reference has to be floating (
"static=false"
).Example reference<secondaryObjectTypeId static="false">myexamplesot</secondaryObjectTypeId>
- (B) Pre-defined
system:document
-
As of 2023 Spring, the predefined object type
system:document
automatically has a floating reference on all SOTs that are available in the applied tenant schema. Thus, all those SOTs can be assigned to DMS objects of typesystem:document
.
The rules for the contentStreamAllowed attribute for the individual SOTs have to be considered before they are assigned to an object.
|
Floating secondary object types can be assigned during the import
-
via
POST /api/dms/objects
or assigned/removed/exchanged at runtime for already existing DMS objects with an update
-
via
POST /api/dms/objects/{objectId}
or -
via
PATCH /api/dms/objects/{objectId}
.
The following keywords can be used in the system:secondaryObjecttypeIds
metadata property.
Keyword | Type | Description | Example | ||
---|---|---|---|---|---|
|
comma-separated string list |
Available during import or update. Assigns one or multiple secondary object types to a DMS object.
|
|
||
|
string |
Available during update. Assigns a single secondary object type to an object. |
|
||
|
string |
Available during update. Removes a single secondary object type from an object.
|
|
If assigned to a DMS object, the SOT is available in the FROM clause in search queries, e.g.:
select * from appSot:INV
You cannot tell from the metadata of a document any longer if a property is referenced directly or indirectly in the schema. All properties are plain in the properties list.
2.4.4. Document Retention
Retention
yuuvis® Momentum provides the possibility to prohibit object deletion requests as well as deletion or change requests on binary content files via an expiration date property called system:rmExpirationDate
. The property is predefined in all systems and is part of the also predefined secondary object type (SOT) system:rmDestructionRetention
. This SOT can be referenced in any document object type definition in any schema (global, app specific or tenant specific). Thus, an expiration date can be set for each object of such a document object type. If a document object has the system:rmExpirationDate
property and if the value of this property lies in the future, it is under retention until the expiration date is reached. There is no maximum retention time. You can specify any date in the future as expiration date to ensure storage time for the sake of your archiving needs.
Since the retention is stored within the objects' metadata, the individual values can be retrieved like other object properties, e.g., via the GET /api/dms/objects/{objectId}
endpoint. It is not possible to define retention periods for objects without the system:rmDestructionRetention
.
The retention defined in the SOT protects binary content files from beeing modified/deleted via yuuvis® Momentum API. However, objects under retention can still be modified/deleted by administrators having direct access to the used storage. To prohibit such administrative operations, some archives offer an archive-internal retention as well. In those archives, the retention specified in the individual objects' metadata is set as an individual archive-internal retention. |
The metadata of objects under retention are NOT protected from changes. They remain editable. If you want to prohibit metadata updates in project-specific use cases, you can configure a suitable webhook, that is triggered before the process you want to prohibit. |
SOT 'system:rmDestructionRetention'
To specify a retention for an individual object, the following properties are predefined in yuuvis® Momentum.
Property | datetime | Description |
---|---|---|
|
datetime |
Required to set a retention. Specifies the date until which the document object will be unter retention. The value must not lie in the past at the time of specification. If the value is null, the values for system:rmStartOfRetention and system:rmDestructionDate must be null as well. If not specified, the default retention of the used repository will be set if defined in the corresponding archive profile. The default retention does NOT replace a retention specified via API, even if the default retention would result in a later expiration date. >> application-storage.yml |
|
datetime |
Optional. Not considered or validated by yuuvis® Momentum core system. Can be used to specify the start date of the retention period for documentation purposes. |
|
datetime |
Optional. Has to equal or exceed the value for Can be used to specify a date to trigger an automated deletion via a custom service. The yuuvis® Momentum core system does not yet offer an endpoint for this purpose. |
The following code block shows the predefined properties that are related to retention. It is not possible to edit or overwrite those definitions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
<propertyDateTimeDefinition>
<id>system:rmExpirationDate</id>
<description>contains the date until the document's content is preserved</description>
<propertyType>datetime</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyDateTimeDefinition>
<propertyDateTimeDefinition>
<id>system:rmStartOfRetention</id>
<description>contains the date from which the retention time was calculated (for documentation purposes only)</description>
<propertyType>datetime</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyDateTimeDefinition>
<propertyDateTimeDefinition>
<id>system:rmDestructionDate</id>
<description>holds the date when the destruction process should be triggered</description>
<propertyType>datetime</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyDateTimeDefinition>
...
All three of those properties are referenced in the system:rmDestructionRetention
SOT. The following code block shows its predefined structure. It is not possible to edit or overwrite this definition.
1
2
3
4
5
6
7
8
9
10
11
...
<typeSecondaryDefinition>
<id>system:rmDestructionRetention</id>
<localNamespace>urn:optimal-systems.de:dmscloud:system</localNamespace>
<description>can be used to apply retentions on objects</description>
<baseId>system:secondary</baseId>
<propertyReference>system:rmExpirationDate</propertyReference>
<propertyReference>system:rmStartOfRetention</propertyReference>
<propertyReference>system:rmDestructionDate</propertyReference>
</typeSecondaryDefinition>
...
To use retentions, your applied schema must contain a document object type that references the predefined system:rmDestructionRetention
SOT. For document objects of this type, you can specify retention properties via yuuvis® Momentum API. The following code block shows an example object type definition.
1
2
3
4
5
6
7
8
9
10
11
...
<typeDocumentDefinition>
<id>document</id>
<description>a document with retention</description>
<baseId>system:document</baseId>
<propertyReference>name</propertyReference>
<propertyReference>date</propertyReference>
<contentStreamAllowed>required</contentStreamAllowed>
<secondaryObjectTypeId>system:rmDestructionRetention</secondaryObjectTypeId>
</typeDocumentDefinition>
...
By means of yuuvis® Momentum core API, there are two ways to set an object under retention:
the object can directly be imported with an expiration date or
an expiration date can be added to a previously existing object using a metadata update.
An example data set as retrievable via GET /api/dms/objects/{objectId}
is shown in the following code block.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"objects": [{
"properties": {
"system:objectTypeId": {
"value": "document"
},
"name": {
"value": "exampledocument"
},
"system:rmStartOfRetention": {
"value": "2018-07-20T11:52:00.000Z"
},
"system:rmExpirationDate": {
"value": "2028-12-28T11:52:00.000Z"
},
"system:rmDestructionDate": {
"value": "2028-12-28T11:52:00.000Z"
}
},
... // the content streams section is missing here
}]
}
Effects of Retentions
If an expiration date has been set for a document object, it is not possible to change or delete its binary content file or delete the object before its expiration date. The other two properties have no particular uses provided by the system. Also, if an object is under retention, it is still possible to update its metadata; however, the expiration date cannot be removed or replaced by an earlier date.
An object under retention cannot be deleted or changed even by users that have a write or delete permissions; retentions take precedence over write
or delete
permissions.
Automated Retention Management
It is possible to extend the functionality of yuuvis® Momentum by configuring webhooks and adding custom microservices. Thus, you can build your own specialized solution to realize automated retention management.
One possible use case would be to calculate the required retention values based on the individual object’s metadata and set them, e.g.,
-
during the object creation,
-
during a specific update of the object’s metadata, or
-
triggered by a specific metadata update of the parent folder object (if you use
system:parentId
).
For the deletion of document objects with expired retention, you can introduce automated custom solutions as well. E.g., with a custom microservice in your system that automatically searches for objects with expired retention and
-
deletes them,
-
updates their state in the lifecycle via tagging, or
-
starts a workflow process asking assigned users to delete them (if BPM-ENGINE Service is used).
2.4.5. Content Renditions
Renditions are alternative representations of the content assigned to DMS objects. As such, they are only retrievable with a read permission for the concrete object instances.
Please note that a rendition is not an exact representation of the original file. Deviations to the original file may arise and are NOT considered as bugs in our software.
Typical use cases for the individual rendition types are:
kind of rendition |
Example use case |
---|---|
|
Full-text search |
|
content preview |
|
thumbnails for content visualization within hit lists in client applications |
Calculation and Storage
The yuuvis® Momentum core system offers automated rendition calculation for various supported formats of binary content files.
The responsible services are enabled in the default configuration but the rendition repository has to be configured manually. |
kind of rendition |
text |
pdf |
slide |
---|---|---|---|
Service for calculation |
|
|
|
Automated calculation |
during import with content and content update processes |
on (first) request |
on (first) request |
Manual input |
during import or via the update endpoint for existing objects, or via the |
- |
- |
Storage location |
search index |
rendition repository |
rendition repository |
Availability for DMS object versions |
only for the current version |
for any (not deleted) version |
for any (not deleted) version |
As the text
rendition is used for full-text search, it is stored in the search index. If you want to extend the core system’s functionality in terms of supported formats, it is possible to set or update the text rendition via API gateway endpoints. Thus, it is possible to, e.g., integrate an OCR implementation to automatically calculate a full-text for binary content files of image file types.
The length of extracted full-text is limited by the configurable parameter extraction.maxTextLengthInKB
in a YAML configuration file for the repository
service. Thus, overloads and downtimes of the repository
due to huge content files with much text can be avoided. If you increase the value, ensure that your search engine (Elasticsearch) can handle your desired size of string fields.
The text
renditions are not stored as content streams but as plain text in the search index where only data for the current version of DMS objects are stored. Thus, text renditions are only available for the current version of DMS objects.
A dbs-reindex command via commander service will undo all manual text rendition inputs.
|
The pdf
and slide
renditions are calculated from the binary content file by the rendition service on request. To reduce the workload and processing time for repeated retrieval of the same rendition, a default rendition repository can be configured. It is a separate repository to allow for a different storage configuration as it might be required for the binary content files themselves. Whenever a pdf or slide rendition is requested for an object, it is retrieved from the default rendition repository. If available, the stored rendition will be returned. If not available, the requested rendition is generated from the binary content file that is assigned to the object, stored in the default rendition repository and finally returned.
The rendition repository uses the content’s digest as rendition identification to avoid duplicate filing. The digest is calculated by the repository
service during each content import or update process and referenced in the content stream properties section of the corresponding DMS object. If the same content file is assigned to multiple DMS objects, the digest is the same, and only one rendition for each kind (pdf
or slide
) is stored within a tenant.
It is not possible to set retention for a rendition.
Supported Formats
The following table provides an overview of various binary content file types and the types of rendition that can be provided (+) by yuuvis® Momentum.
Binary content file type | Extension | text rendition |
pdf rendition |
slide rendition |
---|---|---|---|---|
MS Office Word 97-2016 |
doc, docx |
+ |
+ |
+ |
MS Office PowerPoint 97-2016 |
ppt, pptx |
+ |
+ |
+ |
MS Office Excel 97-2016 |
xls, xlsx |
+ |
+ |
+ |
OpenDocument Text |
odt |
+ |
+ |
+ |
OpenDocument Presentation |
odp |
+ |
+ |
+ |
OpenDocument Spreadsheet |
ods |
+ |
+ |
+ |
Rich Text Format |
rtf |
+ |
- |
- |
Visio Drawing File |
vsd, vsdx |
- |
+ (limited range of functions) |
+ |
Plain Text |
txt |
+ |
- |
- |
Comma Separated Values |
csv |
+ |
- |
- |
HyperText Markup Language (HTML) |
html |
+ |
- |
- |
XML |
xml |
+ |
- |
- |
JavaScript Object Notation |
json |
+ |
- |
- |
MS Outlook |
msg |
+ |
- |
+ |
Electronic Mail Format |
eml |
- |
- |
+ |
Encapsulated Portable Document Format |
epdf |
+ |
- |
- |
Portable Document Format As of 2024 Spring, also 256-bit-encrypted PDF. |
+ |
- |
+ |
|
Tagged Image File Format |
tiff / tif |
- |
+ |
+ |
Portable Bitmap Image |
pbm |
- |
+ |
+ |
Bitmap Image File |
bmp |
- |
+ |
+ |
Graphical Interchange Format File |
gif |
- |
+ |
+ |
JPEG Image Exchangeable image file format (JPEG) |
jpg, jng, jpeg |
- |
+ |
+ |
Portable Network Graphic |
png |
- |
+ |
+ |
Weppy Image Format (Lossy Compression) |
webp |
- |
+ |
+ |
Supported Fonts
The creation of renditions supports only those fonts that are available on the corresponding operation system. If a not-supported font occurs in a binary content file for which a rendition creation is requested, it will be substituted by a supported font.
As yuuvis® Momentum is operated in a Kubernetes system based on Linux, the DejaVu Serif font is always available and is thus used as fallback for the rendition creation if a binary content file contains a not-supported font that cannot be substituted.
The Kubernetes-based yuuvis® Momentum installation contains a variety of different fonts that are available for the creation of renditions. The supported fonts are listed here:
Click here to show supported fonts…
- NotoSansThai-ExtraCondensedLight.ttf: Noto Sans Thai,Noto Sans Thai ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifKhmer-CondensedLight.ttf: Noto Serif Khmer,Noto Serif Khmer Cond Light:style=Condensed Light,Regular
- NotoSerifDisplay-SemiCondensedMedium.ttf: Noto Serif Display,Noto Serif Disp SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansLaoUI-CondensedSemiBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond SemBd:style=Condensed SemiBold,Regular
- DejaVuSerif-Bold.ttf: DejaVu Serif:style=Bold
- NotoSerifGeorgian-SemiCondensedMedium.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn Md:style=SemiCondensed Medium,Regular
- NotoSansArabic-CondensedMedium.ttf: Noto Sans Arabic,Noto Sans Arabic Cond Med:style=Condensed Medium,Regular
- NotoSansCham-Black.ttf: Noto Sans Cham,Noto Sans Cham Blk:style=Black,Regular
- NotoSerifKhmer-ExtraCondensedExtraLight.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansTamilUI-CondensedBlack.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond Blk:style=Condensed Black,Regular
- NotoSansArmenian-SemiCondensedExtraLight.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- URWBookman-LightItalic.otf: URW Bookman:style=Light Italic
- NotoSerifHebrew-CondensedBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond:style=Condensed Bold,Bold
- NotoSerifKhmer-ExtraLight.ttf: Noto Serif Khmer,Noto Serif Khmer ExtLt:style=ExtraLight,Regular
- NotoSerifDisplay-CondensedExtraLight.ttf: Noto Serif Display,Noto Serif Disp Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSans-CondensedLight.ttf: Noto Sans,Noto Sans Cond Light:style=Condensed Light,Regular
- NotoSansLaoUI-ExtraCondensedSemiBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSans-Medium.ttf: Noto Sans,Noto Sans Med:style=Medium,Regular
- NotoSansArabic-Condensed.ttf: Noto Sans Arabic,Noto Sans Arabic Cond:style=Condensed,Regular
- NotoSansCarian-Regular.ttf: Noto Sans Carian:style=Regular
- NotoSerifMyanmar-Thin.ttf: Noto Serif Myanmar,Noto Serif Myanmar Thin:style=Thin,Regular
- NotoSerif-SemiCondensedSemiBold.ttf: Noto Serif,Noto Serif SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansHebrew-Bold.ttf: Noto Sans Hebrew:style=Bold
- NotoSerifArmenian-CondensedExtraLight.ttf: Noto Serif Armenian,Noto Serif Armenian Cn XLt:style=Condensed ExtraLight,Regular
- NotoSansDevanagariUI-Black.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Bk:style=Black,Regular
- URWBookman-Light.otf: URW Bookman:style=Light
- NotoSansDisplay-ExtraCondensedBoldItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond:style=ExtraCondensed Bold Italic,Bold Italic
- NotoSansHebrew-Medium.ttf: Noto Sans Hebrew,Noto Sans Hebrew Med:style=Medium,Regular
- NotoSerifKhmer-Black.ttf: Noto Serif Khmer,Noto Serif Khmer Blk:style=Black,Regular
- NotoSansCherokee-Black.ttf: Noto Sans Cherokee,Noto Sans Cherokee Blk:style=Black,Regular
- DejaVuSansMono.ttf: DejaVu Sans Mono:style=Book
- NotoSerifGeorgian-Condensed.ttf: Noto Serif Georgian,Noto Serif Georgian Cn:style=Condensed,Regular
- NotoSansThai-ExtraCondensedMedium.ttf: Noto Sans Thai,Noto Sans Thai ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSerifTelugu-Regular.ttf: Noto Serif Telugu:style=Regular
- NotoSansLao-SemiCondensedExtraBold.ttf: Noto Sans Lao,Noto Sans Lao SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansOgham-Regular.ttf: Noto Sans Ogham:style=Regular
- NotoSerifMyanmar-CondensedBlack.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond Blk:style=Condensed Black,Regular
- NotoSerifSinhala-ExtraLight.ttf: Noto Serif Sinhala,Noto Serif Sinhala ExtLt:style=ExtraLight,Regular
- NotoSerifHebrew-ExtraCondensedBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifArmenian-ExtraCondensedExtraLight.ttf: Noto Serif Armenian,Noto Serif Armenian XCn XLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifEthiopic-Black.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Bk:style=Black,Regular
- NotoSans-SemiCondensedSemiBoldItalic.ttf: Noto Sans,Noto Sans SemCond SemBd:style=SemiCondensed SemiBold Italic,Italic
- NotoSansInscriptionalPahlavi-Regular.ttf: Noto Sans Inscriptional Pahlavi,Noto Sans InsPahlavi:style=Regular
- NotoSerifMalayalam-Regular.ttf: Noto Serif Malayalam:style=Regular
- NotoSansTamil-SemiCondensedBlack.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansSinhalaUI-ExtraCondensedThin.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifTamil-SemiCondensedExtraLight.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansArabicUI-CondensedExtraLight.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn XLt:style=Condensed ExtraLight,Regular
- NotoSansGeorgian-ExtraBold.ttf: Noto Sans Georgian,Noto Sans Georgian ExtBd:style=ExtraBold,Regular
- NotoSans-Black.ttf: Noto Sans,Noto Sans Blk:style=Black,Regular
- NotoSans-ExtraCondensedExtraBoldItalic.ttf: Noto Sans,Noto Sans ExtCond ExtBd:style=ExtraCondensed ExtraBold Italic,Italic
- NotoSansHebrew-ExtraCondensedThin.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansSymbols-Light.ttf: Noto Sans Symbols,Noto Sans Symbols Light:style=Light,Regular
- NotoSerifLao-ExtraBold.ttf: Noto Serif Lao,Noto Serif Lao ExtBd:style=ExtraBold,Regular
- NotoSansEthiopic-CondensedThin.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond Thin:style=Condensed Thin,Regular
- NotoSerifEthiopic-Medium.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Md:style=Medium,Regular
- NotoSerifMyanmar-CondensedThin.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond Thin:style=Condensed Thin,Regular
- NotoSansDevanagari-Medium.ttf: Noto Sans Devanagari,Noto Sans Devanagari Md:style=Medium,Regular
- NotoSerifMalayalam-Bold.ttf: Noto Serif Malayalam:style=Bold
- NotoSerifKhmer-Condensed.ttf: Noto Serif Khmer,Noto Serif Khmer Cond:style=Condensed,Regular
- NotoSansTamil-SemiCondensedExtraLight.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansDisplay-ExtraCondensedBlackItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond Blk:style=ExtraCondensed Black Italic,Italic
- NotoSerifHebrew-ExtraCondensedBlack.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansMono-SemiCondensedBlack.ttf: Noto Sans Mono,Noto Sans Mono SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansDisplay-CondensedThinItalic.ttf: Noto Sans Display,Noto Sans Disp Cond Thin:style=Condensed Thin Italic,Italic
- NotoSansCJKkr-Black.otf: Noto Sans CJK KR,Noto Sans CJK KR Black:style=Black,Regular
- NotoSansDevanagariUI-CondensedSemiBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn SmBd:style=Condensed SemiBold,Regular
- NotoSansKhmerUI-SemiCondensedLight.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond Light:style=SemiCondensed Light,Regular
- NotoSansKhmer-Thin.ttf: Noto Sans Khmer,Noto Sans Khmer Thin:style=Thin,Regular
- NotoSansArabic-CondensedThin.ttf: Noto Sans Arabic,Noto Sans Arabic Cond Thin:style=Condensed Thin,Regular
- NotoSansTamil-CondensedThin.ttf: Noto Sans Tamil,Noto Sans Tamil Cond Thin:style=Condensed Thin,Regular
- NotoSansArabicUI-CondensedSemiBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn SmBd:style=Condensed SemiBold,Regular
- NotoSerifHebrew-SemiCondensedExtraLight.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifEthiopic-CondensedLight.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn Lt:style=Condensed Light,Regular
- NotoSerifLao-Bold.ttf: Noto Serif Lao:style=Bold
- NotoSansKhmer-Black.ttf: Noto Sans Khmer,Noto Sans Khmer Blk:style=Black,Regular
- NotoSerifKhmer-CondensedBold.ttf: Noto Serif Khmer,Noto Serif Khmer Cond:style=Condensed Bold,Bold
- NotoSansThai-Thin.ttf: Noto Sans Thai,Noto Sans Thai Thin:style=Thin,Regular
- NotoSerifThai-Light.ttf: Noto Serif Thai,Noto Serif Thai Light:style=Light,Regular
- NimbusMonoPS-Italic.otf: Nimbus Mono PS:style=Italic
- NotoSans-SemiCondensedSemiBold.ttf: Noto Sans,Noto Sans SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansHebrew-SemiCondensedSemiBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansMono-Regular.ttf: Noto Sans Mono:style=Regular
- NotoSansGeorgian-SemiBold.ttf: Noto Sans Georgian,Noto Sans Georgian SemBd:style=SemiBold,Regular
- NotoSansDevanagari-ExtraBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari XBd:style=ExtraBold,Regular
- NotoSans-SemiCondensed.ttf: Noto Sans,Noto Sans SemCond:style=SemiCondensed,Regular
- NotoSansArabicUI-CondensedThin.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn Th:style=Condensed Thin,Regular
- NotoSerifGeorgian-ExtraBold.ttf: Noto Serif Georgian,Noto Serif Georgian XBd:style=ExtraBold,Regular
- NotoSerifTamil-ExtraCondensedLight.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond Light:style=ExtraCondensed Light,Regular
- P052-Italic.otf: P052:style=Italic
- URWGothic-BookOblique.t1: URW Gothic:style=Book Oblique
- NotoSerifKhmer-SemiBold.ttf: Noto Serif Khmer,Noto Serif Khmer SemBd:style=SemiBold,Regular
- NotoSansDisplay-CondensedItalic.ttf: Noto Sans Display,Noto Sans Disp Cond:style=Condensed Italic,Italic
- NotoSansGeorgian-Medium.ttf: Noto Sans Georgian,Noto Sans Georgian Med:style=Medium,Regular
- NotoSerifMyanmar-SemiCondensed.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond:style=SemiCondensed,Regular
- NotoSansArabicUI-SemiCondensedSemiBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn SmBd:style=SemiCondensed SemiBold,Regular
- NotoSansArabic-SemiCondensedLight.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond Light:style=SemiCondensed Light,Regular
- NotoSerifGeorgian-SemiCondensedThin.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn Th:style=SemiCondensed Thin,Regular
- NotoSansGeorgian-ExtraCondensedLight.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansLao-ExtraCondensedExtraBold.ttf: Noto Sans Lao,Noto Sans Lao ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansArmenian-CondensedBlack.ttf: Noto Sans Armenian,Noto Sans Armenian Cond Blk:style=Condensed Black,Regular
- NotoSerif-SemiCondensed.ttf: Noto Serif,Noto Serif SemCond:style=SemiCondensed,Regular
- NotoSansThaiUI-SemiBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemBd:style=SemiBold,Regular
- NotoSerifMyanmar-ExtraCondensedSemiBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansBengali-Black.ttf: Noto Sans Bengali,Noto Sans Bengali Blk:style=Black,Regular
- NotoSansTaiLe-Regular.ttf: Noto Sans Tai Le:style=Regular
- NotoSansArmenian-SemiCondensed.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond:style=SemiCondensed,Regular
- NotoSansSinhalaUI-ExtraCondensedExtraLight.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansMyanmar-SemiBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemBd:style=SemiBold,Regular
- NotoSansArmenian-Black.ttf: Noto Sans Armenian,Noto Sans Armenian Blk:style=Black,Regular
- NotoSerifHebrew-Bold.ttf: Noto Serif Hebrew:style=Bold
- NotoSansMyanmarUI-Regular.ttf: Noto Sans Myanmar UI:style=Regular
- NotoSansDevanagari-Thin.ttf: Noto Sans Devanagari,Noto Sans Devanagari Th:style=Thin,Regular
- NotoSerifDisplay-BoldItalic.ttf: Noto Serif Display,Noto Serif Disp:style=Bold Italic
- n021024l.pfb: Nimbus Roman No9 L:style=Medium Italic
- NotoSansThai-CondensedExtraLight.ttf: Noto Sans Thai,Noto Sans Thai Cond ExtLt:style=Condensed ExtraLight,Regular
- DejaVuSans.ttf: DejaVu Sans:style=Book
- NotoSerifDisplay-SemiCondensedExtraBold.ttf: Noto Serif Display,Noto Serif Disp SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NimbusSans-Regular.otf: Nimbus Sans:style=Regular
- NotoSansArmenian-CondensedLight.ttf: Noto Sans Armenian,Noto Sans Armenian Cond Light:style=Condensed Light,Regular
- NotoSansLaoUI-ExtraCondensedMedium.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSerif-ExtraBold.ttf: Noto Serif,Noto Serif ExtBd:style=ExtraBold,Regular
- NotoSans-CondensedBlack.ttf: Noto Sans,Noto Sans Cond Blk:style=Condensed Black,Regular
- NotoSansArmenian-SemiCondensedThin.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSerifCJKkr-Light.otf: Noto Serif CJK KR,Noto Serif CJK KR Light:style=Light,Regular
- NotoSansGeorgian-CondensedExtraLight.ttf: Noto Sans Georgian,Noto Sans Georgian Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansOriya-Regular.ttf: Noto Sans Oriya:style=Regular
- NotoSerifThai-ExtraCondensedExtraBold.ttf: Noto Serif Thai,Noto Serif Thai ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansEthiopic-CondensedBlack.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond Blk:style=Condensed Black,Regular
- NotoSerifArmenian-SemiCondensedBold.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn:style=SemiCondensed Bold,Bold
- NotoSansSinhalaUI-SemiCondensedLight.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond Light:style=SemiCondensed Light,Regular
- NotoSansKhmer-ExtraCondensedLight.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifTamil-Thin.ttf: Noto Serif Tamil,Noto Serif Tamil Thin:style=Thin,Regular
- NotoSansDevanagariUI-CondensedExtraLight.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn XLt:style=Condensed ExtraLight,Regular
- NotoSansTamilUI-SemiCondensed.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond:style=SemiCondensed,Regular
- NotoSansMyanmar-CondensedSemiBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansSymbols-Black.ttf: Noto Sans Symbols,Noto Sans Symbols Blk:style=Black,Regular
- NotoSerifArmenian-Thin.ttf: Noto Serif Armenian,Noto Serif Armenian Th:style=Thin,Regular
- NotoSansGothic-Regular.ttf: Noto Sans Gothic:style=Regular
- NotoSansTamilUI-SemiCondensedSemiBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSerifArmenian-Black.ttf: Noto Serif Armenian,Noto Serif Armenian Bk:style=Black,Regular
- NotoSansTamil-ExtraCondensedExtraBold.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- URWBookman-DemiItalic.t1: URW Bookman:style=Demi Italic
- NotoSansDisplay-SemiCondensedItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond:style=SemiCondensed Italic,Italic
- NotoSansKhmerUI-ExtraCondensedExtraLight.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansLaoUI-CondensedLight.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond Light:style=Condensed Light,Regular
- NotoSansSinhala-Bold.ttf: Noto Sans Sinhala:style=Bold
- NotoSerifKhmer-ExtraCondensedMedium.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond Med:style=ExtraCondensed Medium,Regular
- NimbusSansNarrow-Oblique.otf: Nimbus Sans Narrow:style=Oblique
- NotoSansSinhala-SemiCondensedBlack.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifTamil-ExtraCondensedExtraLight.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansArabic-ExtraCondensedThin.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifThai-CondensedSemiBold.ttf: Noto Serif Thai,Noto Serif Thai Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansSinhala-CondensedBlack.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond Blk:style=Condensed Black,Regular
- NotoSerif-SemiBoldItalic.ttf: Noto Serif,Noto Serif SemBd:style=SemiBold Italic,Italic
- NotoSansSinhalaUI-Black.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Blk:style=Black,Regular
- NotoSerifCJKtc-Light.otf: Noto Serif CJK TC,Noto Serif CJK TC Light:style=Light,Regular
- NotoSerifEthiopic-ExtraCondensedExtraLight.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn XLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansTamil-ExtraCondensedSemiBold.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifThai-ExtraCondensedLight.ttf: Noto Serif Thai,Noto Serif Thai ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifDisplay-ExtraCondensedBlack.ttf: Noto Serif Display,Noto Serif Disp ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansThaiUI-CondensedThin.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond Thin:style=Condensed Thin,Regular
- NotoSansBengali-ExtraBold.ttf: Noto Sans Bengali,Noto Sans Bengali ExtBd:style=ExtraBold,Regular
- NimbusSans-Regular.t1: Nimbus Sans:style=Regular
- NotoSansMyanmar-Bold.ttf: Noto Sans Myanmar:style=Bold
- NotoSansEthiopic-ExtraCondensedBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansEthiopic-Light.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Light:style=Light,Regular
- NotoSansDevanagariUI-ExtraCondensedLight.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn Lt:style=ExtraCondensed Light,Regular
- NotoSansBengaliUI-ExtraBold.ttf: Noto Sans Bengali UI,Noto Sans Bengali ExtBd:style=ExtraBold,Regular
- NotoSerifThai-Bold.ttf: Noto Serif Thai:style=Bold
- NotoSerifGeorgian-SemiCondensedBlack.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn Bk:style=SemiCondensed Black,Regular
- NotoSansSinhala-SemiBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemBd:style=SemiBold,Regular
- NotoSansLao-ExtraCondensedSemiBold.ttf: Noto Sans Lao,Noto Sans Lao ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- C059-Roman.otf: C059:style=Roman
- NotoSansArmenian-CondensedSemiBold.ttf: Noto Sans Armenian,Noto Sans Armenian Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansTamilUI-ExtraLight.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtLt:style=ExtraLight,Regular
- NotoSansCherokee-Thin.ttf: Noto Sans Cherokee,Noto Sans Cherokee Thin:style=Thin,Regular
- NotoSansDisplay-SemiBold.ttf: Noto Sans Display,Noto Sans Disp SemBd:style=SemiBold,Regular
- NotoSansDisplay-ExtraLightItalic.ttf: Noto Sans Display,Noto Sans Disp ExtLt:style=ExtraLight Italic,Italic
- NotoSansLinearB-Regular.ttf: Noto Sans Linear B:style=Regular
- NotoSansSinhalaUI-ExtraCondensedLight.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifEthiopic-Regular.ttf: Noto Serif Ethiopic:style=Regular
- NotoSansArabic-CondensedBlack.ttf: Noto Sans Arabic,Noto Sans Arabic Cond Blk:style=Condensed Black,Regular
- NotoSerifThai-ExtraCondensedThin.ttf: Noto Serif Thai,Noto Serif Thai ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifHebrew-Condensed.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond:style=Condensed,Regular
- NotoSansArabic-SemiCondensed.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond:style=SemiCondensed,Regular
- NotoSansMyanmar-ExtraCondensedSemiBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifLao-CondensedExtraBold.ttf: Noto Serif Lao,Noto Serif Lao Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansDevanagari-SemiCondensedBlack.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn Bk:style=SemiCondensed Black,Regular
- NotoSansKhmer-CondensedLight.ttf: Noto Sans Khmer,Noto Sans Khmer Cond Light:style=Condensed Light,Regular
- NotoSerifDisplay-SemiCondensedThin.ttf: Noto Serif Display,Noto Serif Disp SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansCJKjp-Thin.otf: Noto Sans CJK JP,Noto Sans CJK JP Thin:style=Thin,Regular
- NotoSansCJKkr-Light.otf: Noto Sans CJK KR,Noto Sans CJK KR Light:style=Light,Regular
- NotoSerifGeorgian-ExtraCondensed.ttf: Noto Serif Georgian,Noto Serif Georgian XCn:style=ExtraCondensed,Regular
- n021004l.pfb: Nimbus Roman No9 L:style=Medium
- NotoSerifHebrew-SemiCondensedExtraBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansSinhala-SemiCondensedExtraBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansKhmer-CondensedExtraLight.ttf: Noto Sans Khmer,Noto Sans Khmer Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansHebrew-ExtraBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtBd:style=ExtraBold,Regular
- NotoSansMyanmar-Condensed.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond:style=Condensed,Regular
- NotoSerifDisplay-ExtraCondensedItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond:style=ExtraCondensed Italic,Italic
- NotoSerifArmenian-Medium.ttf: Noto Serif Armenian,Noto Serif Armenian Md:style=Medium,Regular
- NimbusMonoPS-BoldItalic.otf: Nimbus Mono PS:style=Bold Italic
- NotoSansHebrew-ExtraCondensedLight.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifEthiopic-SemiBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmBd:style=SemiBold,Regular
- NotoSerifTamil-SemiCondensedThin.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSerifArmenian-ExtraCondensed.ttf: Noto Serif Armenian,Noto Serif Armenian XCn:style=ExtraCondensed,Regular
- NotoSansLaoUI-Light.ttf: Noto Sans Lao UI,Noto Sans Lao UI Light:style=Light,Regular
- NotoSerif-MediumItalic.ttf: Noto Serif,Noto Serif Med:style=Medium Italic,Italic
- NotoSansMyanmar-ExtraCondensedThin.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansSinhalaUI-CondensedThin.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond Thin:style=Condensed Thin,Regular
- NotoSerif-SemiCondensedExtraLightItalic.ttf: Noto Serif,Noto Serif SemCond ExtLt:style=SemiCondensed ExtraLight Italic,Italic
- NotoSerifHebrew-CondensedSemiBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansSinhala-ExtraCondensedBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond:style=ExtraCondensed Bold,Bold
- URWGothic-DemiOblique.t1: URW Gothic:style=Demi Oblique
- NotoSerifDisplay-SemiCondensedBlackItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond Blk:style=SemiCondensed Black Italic,Italic
- NotoSerifSinhala-SemiBold.ttf: Noto Serif Sinhala,Noto Serif Sinhala SemBd:style=SemiBold,Regular
- NotoSerifEthiopic-ExtraCondensed.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn:style=ExtraCondensed,Regular
- NotoSansEthiopic-SemiCondensedMedium.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansMyanmarUI-ExtraCondensedLight.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn Lt:style=ExtraCondensed Light,Regular
- NotoSerifThai-Black.ttf: Noto Serif Thai,Noto Serif Thai Blk:style=Black,Regular
- NotoSerifGeorgian-CondensedSemiBold.ttf: Noto Serif Georgian,Noto Serif Georgian Cn SmBd:style=Condensed SemiBold,Regular
- NotoSansDisplay-ExtraBold.ttf: Noto Sans Display,Noto Sans Disp ExtBd:style=ExtraBold,Regular
- NotoSerifDisplay-SemiCondensedMediumItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond Med:style=SemiCondensed Medium Italic,Italic
- NotoSerifThai-CondensedMedium.ttf: Noto Serif Thai,Noto Serif Thai Cond Med:style=Condensed Medium,Regular
- p052023l.pfb: URW Palladio L:style=Italic
- n022003l.pfb: Nimbus Mono L:style=Regular
- NotoSerifSinhala-Bold.ttf: Noto Serif Sinhala:style=Bold
- NotoSansLaoUI-Condensed.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond:style=Condensed,Regular
- NotoSerifTelugu-Bold.ttf: Noto Serif Telugu:style=Bold
- NotoSansArabicUI-SemiCondensedThin.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn Th:style=SemiCondensed Thin,Regular
- NotoSansGurmukhi-Bold.ttf: Noto Sans Gurmukhi:style=Bold
- NotoSansLao-CondensedThin.ttf: Noto Sans Lao,Noto Sans Lao Cond Thin:style=Condensed Thin,Regular
- NotoSansMono-SemiCondensedThin.ttf: Noto Sans Mono,Noto Sans Mono SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansDisplay-ExtraBoldItalic.ttf: Noto Sans Display,Noto Sans Disp ExtBd:style=ExtraBold Italic,Italic
- NotoSansHebrew-Thin.ttf: Noto Sans Hebrew,Noto Sans Hebrew Thin:style=Thin,Regular
- NotoSansKhmer-Light.ttf: Noto Sans Khmer,Noto Sans Khmer Light:style=Light,Regular
- NotoSansTamil-ExtraCondensedExtraLight.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifSinhala-Black.ttf: Noto Serif Sinhala,Noto Serif Sinhala Blk:style=Black,Regular
- NotoSansLao-Thin.ttf: Noto Sans Lao,Noto Sans Lao Thin:style=Thin,Regular
- NotoSans-CondensedBlackItalic.ttf: Noto Sans,Noto Sans Cond Blk:style=Condensed Black Italic,Italic
- NotoSerifLao-SemiCondensedSemiBold.ttf: Noto Serif Lao,Noto Serif Lao SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSans-ExtraCondensed.ttf: Noto Sans,Noto Sans ExtCond:style=ExtraCondensed,Regular
- NotoSansDisplay-CondensedBold.ttf: Noto Sans Display,Noto Sans Disp Cond:style=Condensed Bold,Bold
- NotoSansLao-ExtraCondensedLight.ttf: Noto Sans Lao,Noto Sans Lao ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifEthiopic-ExtraCondensedBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn:style=ExtraCondensed Bold,Bold
- NotoSansArabic-CondensedSemiBold.ttf: Noto Sans Arabic,Noto Sans Arabic Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansThaiUI-Thin.ttf: Noto Sans Thai UI,Noto Sans Thai UI Thin:style=Thin,Regular
- NotoSansLao-SemiCondensedBold.ttf: Noto Sans Lao,Noto Sans Lao SemCond:style=SemiCondensed Bold,Bold
- NotoSerifMyanmar-Regular.ttf: Noto Serif Myanmar:style=Regular
- NotoSansMyanmarUI-ExtraCondensedMedium.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn Md:style=ExtraCondensed Medium,Regular
- NotoSansDevanagari-SemiCondensedSemiBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn SmBd:style=SemiCondensed SemiBold,Regular
- NotoSansThaiUI-SemiCondensedBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond:style=SemiCondensed Bold,Bold
- NotoSerifGeorgian-ExtraCondensedLight.ttf: Noto Serif Georgian,Noto Serif Georgian XCn Lt:style=ExtraCondensed Light,Regular
- NotoSansShavian-Regular.ttf: Noto Sans Shavian:style=Regular
- NotoSansDevanagariUI-SemiCondensedSemiBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn SmBd:style=SemiCondensed SemiBold,Regular
- NotoSansArabic-ExtraCondensedBlack.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansGeorgian-CondensedMedium.ttf: Noto Sans Georgian,Noto Sans Georgian Cond Med:style=Condensed Medium,Regular
- NotoSerifHebrew-SemiCondensedSemiBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansArabic-CondensedLight.ttf: Noto Sans Arabic,Noto Sans Arabic Cond Light:style=Condensed Light,Regular
- NotoSansLaoUI-SemiCondensedMedium.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansOlChiki-Regular.ttf: Noto Sans Ol Chiki:style=Regular
- NotoSerif-ExtraCondensedSemiBold.ttf: Noto Serif,Noto Serif ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifArmenian-CondensedBlack.ttf: Noto Serif Armenian,Noto Serif Armenian Cn Bk:style=Condensed Black,Regular
- NotoSansDevanagari-Light.ttf: Noto Sans Devanagari,Noto Sans Devanagari Lt:style=Light,Regular
- NotoSansTamilUI-CondensedMedium.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond Med:style=Condensed Medium,Regular
- NotoSerifDisplay-ExtraCondensedSemiBold.ttf: Noto Serif Display,Noto Serif Disp ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansArabicUI-ExtraLight.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XLt:style=ExtraLight,Regular
- NotoSansMyanmarUI-SemiCondensedBlack.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn Bk:style=SemiCondensed Black,Regular
- NotoSansSinhala-Black.ttf: Noto Sans Sinhala,Noto Sans Sinhala Blk:style=Black,Regular
- NotoSerifEthiopic-SemiCondensedBlack.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn Bk:style=SemiCondensed Black,Regular
- NotoSansThai-SemiCondensedBold.ttf: Noto Sans Thai,Noto Sans Thai SemCond:style=SemiCondensed Bold,Bold
- NotoSansKhmer-SemiCondensedLight.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond Light:style=SemiCondensed Light,Regular
- NotoSansArmenian-ExtraBold.ttf: Noto Sans Armenian,Noto Sans Armenian ExtBd:style=ExtraBold,Regular
- NotoSansDevanagariUI-Medium.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Md:style=Medium,Regular
- NotoSerifHebrew-SemiCondensedBlack.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansMonoCJKtc-Regular.otf: Noto Sans Mono CJK TC,Noto Sans Mono CJK TC Regular:style=Regular
- NotoSansNewTaiLue-Regular.ttf: Noto Sans New Tai Lue:style=Regular
- z003034l.pfb: URW Chancery L:style=Medium Italic
- NotoSansSinhala-ExtraCondensedExtraLight.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerif-ExtraCondensedLight.ttf: Noto Serif,Noto Serif ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifCJKtc-Medium.otf: Noto Serif CJK TC,Noto Serif CJK TC Medium:style=Medium,Regular
- NotoSerifGeorgian-SemiCondensed.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn:style=SemiCondensed,Regular
- NotoSansGeorgian-ExtraCondensedMedium.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansArmenian-Bold.ttf: Noto Sans Armenian:style=Bold
- NotoSerifDisplay-CondensedMedium.ttf: Noto Serif Display,Noto Serif Disp Cond Med:style=Condensed Medium,Regular
- NotoSerifTamil-SemiCondensedBold.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond:style=SemiCondensed Bold,Bold
- NotoSans-ExtraCondensedMediumItalic.ttf: Noto Sans,Noto Sans ExtCond Med:style=ExtraCondensed Medium Italic,Italic
- NotoSansTagalog-Regular.ttf: Noto Sans Tagalog:style=Regular
- NotoSansHanunoo-Regular.ttf: Noto Sans Hanunoo:style=Regular
- URWBookman-LightItalic.t1: URW Bookman:style=Light Italic
- NotoSerifTamil-Light.ttf: Noto Serif Tamil,Noto Serif Tamil Light:style=Light,Regular
- NotoSerifKhmer-SemiCondensedSemiBold.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NimbusSansNarrow-BoldOblique.otf: Nimbus Sans Narrow:style=Bold Oblique
- NotoSansKhmer-CondensedExtraBold.ttf: Noto Sans Khmer,Noto Sans Khmer Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansGeorgian-CondensedBold.ttf: Noto Sans Georgian,Noto Sans Georgian Cond:style=Condensed Bold,Bold
- NotoSansLao-Condensed.ttf: Noto Sans Lao,Noto Sans Lao Cond:style=Condensed,Regular
- NotoSansMono-ExtraCondensedBlack.ttf: Noto Sans Mono,Noto Sans Mono ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansHebrew-SemiCondensed.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond:style=SemiCondensed,Regular
- NotoSerifMyanmar-ExtraCondensed.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond:style=ExtraCondensed,Regular
- NotoSansLao-CondensedExtraLight.ttf: Noto Sans Lao,Noto Sans Lao Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansTamilUI-Condensed.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond:style=Condensed,Regular
- NotoSansMonoCJKtc-Bold.otf: Noto Sans Mono CJK TC,Noto Sans Mono CJK TC Bold:style=Bold,Regular
- NotoSansMyanmarUI-SemiCondensedThin.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn Th:style=SemiCondensed Thin,Regular
- NotoSerif-SemiCondensedBold.ttf: Noto Serif,Noto Serif SemCond:style=SemiCondensed Bold,Bold
- NotoSansDisplay-ExtraCondensedMediumItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond Med:style=ExtraCondensed Medium Italic,Italic
- NotoSansBengaliUI-Regular.ttf: Noto Sans Bengali UI:style=Regular
- NotoColorEmoji.ttf: Noto Color Emoji:style=Regular
- NotoSansCham-ExtraBold.ttf: Noto Sans Cham,Noto Sans Cham ExtBd:style=ExtraBold,Regular
- NotoSansEthiopic-ExtraCondensedLight.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansCham-Light.ttf: Noto Sans Cham,Noto Sans Cham Light:style=Light,Regular
- NotoSerifMyanmar-SemiCondensedBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond:style=SemiCondensed Bold,Bold
- NotoSansGeorgian-SemiCondensedLight.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond Light:style=SemiCondensed Light,Regular
- NotoSerifHebrew-Thin.ttf: Noto Serif Hebrew,Noto Serif Hebrew Thin:style=Thin,Regular
- NotoSerifHebrew-Black.ttf: Noto Serif Hebrew,Noto Serif Hebrew Blk:style=Black,Regular
- NotoSerifGeorgian-ExtraCondensedSemiBold.ttf: Noto Serif Georgian,Noto Serif Georgian XCn SmBd:style=ExtraCondensed SemiBold,Regular
- NotoSansLaoUI-ExtraBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtBd:style=ExtraBold,Regular
- NotoSerifDisplay-ExtraCondensedExtraBold.ttf: Noto Serif Display,Noto Serif Disp ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerifGeorgian-Regular.ttf: Noto Serif Georgian:style=Regular
- NotoSerifDisplay-CondensedItalic.ttf: Noto Serif Display,Noto Serif Disp Cond:style=Condensed Italic,Italic
- NotoSansTamil-Thin.ttf: Noto Sans Tamil,Noto Sans Tamil Thin:style=Thin,Regular
- NotoSans-CondensedExtraBold.ttf: Noto Sans,Noto Sans Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansTelugu-Regular.ttf: Noto Sans Telugu:style=Regular
- NotoSansLaoUI-Regular.ttf: Noto Sans Lao UI:style=Regular
- NotoSansGeorgian-Bold.ttf: Noto Sans Georgian:style=Bold
- NotoSansArmenian-ExtraCondensedMedium.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansLaoUI-CondensedBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond:style=Condensed Bold,Bold
- NotoSerifDisplay-MediumItalic.ttf: Noto Serif Display,Noto Serif Disp Med:style=Medium Italic,Italic
- NotoSansArabicUI-CondensedBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn:style=Condensed Bold,Bold
- NotoSansBamum-Regular.ttf: Noto Sans Bamum:style=Regular
- NotoSerifCJKtc-Regular.otf: Noto Serif CJK TC:style=Regular
- NotoSerif-ExtraCondensedItalic.ttf: Noto Serif,Noto Serif ExtCond:style=ExtraCondensed Italic,Italic
- NotoSerifThai-CondensedExtraLight.ttf: Noto Serif Thai,Noto Serif Thai Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSerifThai-CondensedLight.ttf: Noto Serif Thai,Noto Serif Thai Cond Light:style=Condensed Light,Regular
- NotoSansGeorgian-ExtraCondensed.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond:style=ExtraCondensed,Regular
- NotoSansCJKkr-Thin.otf: Noto Sans CJK KR,Noto Sans CJK KR Thin:style=Thin,Regular
- NotoSansSinhalaUI-SemiBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemBd:style=SemiBold,Regular
- NotoSerif-SemiCondensedBlack.ttf: Noto Serif,Noto Serif SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansBengali-Medium.ttf: Noto Sans Bengali,Noto Sans Bengali Med:style=Medium,Regular
- NotoSansTamilUI-ExtraCondensedExtraLight.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansCJKkr-Medium.otf: Noto Sans CJK KR,Noto Sans CJK KR Medium:style=Medium,Regular
- NotoSansLao-Light.ttf: Noto Sans Lao,Noto Sans Lao Light:style=Light,Regular
- NotoSansHebrew-ExtraCondensedBlack.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSerifGeorgian-Light.ttf: Noto Serif Georgian,Noto Serif Georgian Lt:style=Light,Regular
- NotoSansLao-CondensedBlack.ttf: Noto Sans Lao,Noto Sans Lao Cond Blk:style=Condensed Black,Regular
- NotoSansMyanmar-SemiCondensedLight.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond Light:style=SemiCondensed Light,Regular
- NotoSerifHebrew-Regular.ttf: Noto Serif Hebrew:style=Regular
- NotoSansThai-SemiBold.ttf: Noto Sans Thai,Noto Sans Thai SemBd:style=SemiBold,Regular
- NotoSerif-ExtraCondensedBold.ttf: Noto Serif,Noto Serif ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansEthiopic-CondensedBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond:style=Condensed Bold,Bold
- NotoSerifGeorgian-Thin.ttf: Noto Serif Georgian,Noto Serif Georgian Th:style=Thin,Regular
- NotoSerifHebrew-ExtraCondensedSemiBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansThai-SemiCondensedThin.ttf: Noto Sans Thai,Noto Sans Thai SemCond Thin:style=SemiCondensed Thin,Regular
- c059013l.pfb: Century Schoolbook L:style=Roman
- NotoSans-SemiCondensedBold.ttf: Noto Sans,Noto Sans SemCond:style=SemiCondensed Bold,Bold
- NotoSansEthiopic-ExtraCondensedExtraLight.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansGeorgian-Black.ttf: Noto Sans Georgian,Noto Sans Georgian Blk:style=Black,Regular
- NimbusSansNarrow-BoldOblique.t1: Nimbus Sans Narrow:style=Bold Oblique
- NotoSerif-SemiCondensedLight.ttf: Noto Serif,Noto Serif SemCond Light:style=SemiCondensed Light,Regular
- NotoSansDisplay-CondensedLightItalic.ttf: Noto Sans Display,Noto Sans Disp Cond Light:style=Condensed Light Italic,Italic
- NotoSerifMyanmar-SemiCondensedExtraLight.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifMyanmar-CondensedLight.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond Light:style=Condensed Light,Regular
- NotoSansKhmer-SemiCondensedMedium.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond Med:style=SemiCondensed Medium,Regular
- NotoNaskhArabicUI-Regular.ttf: Noto Naskh Arabic UI:style=Regular
- NotoSansArmenian-ExtraCondensedExtraLight.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifKhmer-ExtraCondensedSemiBold.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NimbusSans-Bold.otf: Nimbus Sans:style=Bold
- NotoSansArmenian-SemiCondensedLight.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond Light:style=SemiCondensed Light,Regular
- NotoSansTamil-CondensedSemiBold.ttf: Noto Sans Tamil,Noto Sans Tamil Cond SemBd:style=Condensed SemiBold,Regular
- NotoSerifLao-SemiCondensedLight.ttf: Noto Serif Lao,Noto Serif Lao SemCond Light:style=SemiCondensed Light,Regular
- NotoSansSinhala-ExtraCondensed.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond:style=ExtraCondensed,Regular
- NotoSerifCJKsc-Medium.otf: Noto Serif CJK SC,Noto Serif CJK SC Medium:style=Medium,Regular
- NotoSansMono-ExtraCondensedMedium.ttf: Noto Sans Mono,Noto Sans Mono ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansThaiUI-ExtraCondensedBlack.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond Blk:style=ExtraCondensed Black,Regular
- NimbusMonoPS-Italic.t1: Nimbus Mono PS:style=Italic
- NotoSansDevanagari-Bold.ttf: Noto Sans Devanagari:style=Bold
- NotoSerif-SemiCondensedExtraBold.ttf: Noto Serif,Noto Serif SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansDisplay-SemiCondensedBold.ttf: Noto Sans Display,Noto Sans Disp SemCond:style=SemiCondensed Bold,Bold
- NotoSansCJKjp-DemiLight.otf: Noto Sans CJK JP,Noto Sans CJK JP DemiLight:style=DemiLight,Regular
- NotoSansEthiopic-SemiCondensed.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond:style=SemiCondensed,Regular
- NotoSansKhmer-CondensedBlack.ttf: Noto Sans Khmer,Noto Sans Khmer Cond Blk:style=Condensed Black,Regular
- NotoSansSinhala-SemiCondensed.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond:style=SemiCondensed,Regular
- NotoSerifMyanmar-SemiCondensedThin.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSerifTamil-Black.ttf: Noto Serif Tamil,Noto Serif Tamil Blk:style=Black,Regular
- NotoSerifDisplay-ExtraCondensedThinItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond Thin:style=ExtraCondensed Thin Italic,Italic
- NotoSerifDisplay-Condensed.ttf: Noto Serif Display,Noto Serif Disp Cond:style=Condensed,Regular
- NotoSansMyanmar-Medium.ttf: Noto Sans Myanmar,Noto Sans Myanmar Med:style=Medium,Regular
- NotoSansLao-CondensedMedium.ttf: Noto Sans Lao,Noto Sans Lao Cond Med:style=Condensed Medium,Regular
- NotoSansMono-SemiCondensedMedium.ttf: Noto Sans Mono,Noto Sans Mono SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansCJKsc-Thin.otf: Noto Sans CJK SC,Noto Sans CJK SC Thin:style=Thin,Regular
- NotoSansDisplay-Italic.ttf: Noto Sans Display,Noto Sans Disp:style=Italic
- NotoSansThaana-Regular.ttf: Noto Sans Thaana:style=Regular
- NotoSerifThai-SemiCondensed.ttf: Noto Serif Thai,Noto Serif Thai SemCond:style=SemiCondensed,Regular
- NimbusRoman-BoldItalic.t1: Nimbus Roman:style=Bold Italic
- NotoSansArabicUI-SemiCondensed.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn:style=SemiCondensed,Regular
- NotoSansSinhala-CondensedMedium.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond Med:style=Condensed Medium,Regular
- NotoSerifDisplay-CondensedLightItalic.ttf: Noto Serif Display,Noto Serif Disp Cond Light:style=Condensed Light Italic,Italic
- NotoSerifDisplay-CondensedBoldItalic.ttf: Noto Serif Display,Noto Serif Disp Cond:style=Condensed Bold Italic,Bold Italic
- NotoSansCherokee-ExtraLight.ttf: Noto Sans Cherokee,Noto Sans Cherokee ExtLt:style=ExtraLight,Regular
- NotoSansTelugu-Bold.ttf: Noto Sans Telugu:style=Bold
- NotoSansHebrew-SemiCondensedBlack.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansBengali-ExtraLight.ttf: Noto Sans Bengali,Noto Sans Bengali ExtLt:style=ExtraLight,Regular
- NotoSerifDisplay-CondensedExtraBoldItalic.ttf: Noto Serif Display,Noto Serif Disp Cond ExtBd:style=Condensed ExtraBold Italic,Italic
- NotoSansTaiViet-Regular.ttf: Noto Sans Tai Viet:style=Regular
- NotoSansThai-Regular.ttf: Noto Sans Thai:style=Regular
- NotoSansCJKsc-Bold.otf: Noto Sans CJK SC,Noto Sans CJK SC Bold:style=Bold,Regular
- NotoSerifLao-ExtraCondensedLight.ttf: Noto Serif Lao,Noto Serif Lao ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansArmenian-ExtraCondensedExtraBold.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerifTamil-ExtraCondensedSemiBold.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifEthiopic-ExtraCondensedBlack.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn Bk:style=ExtraCondensed Black,Regular
- NotoSansTamil-CondensedMedium.ttf: Noto Sans Tamil,Noto Sans Tamil Cond Med:style=Condensed Medium,Regular
- NotoSansBuhid-Regular.ttf: Noto Sans Buhid:style=Regular
- NotoSansTamilUI-Light.ttf: Noto Sans Tamil UI,Noto Sans Tamil Light:style=Light,Regular
- NotoSerifKhmer-Thin.ttf: Noto Serif Khmer,Noto Serif Khmer Thin:style=Thin,Regular
- NotoSansGeorgian-Thin.ttf: Noto Sans Georgian,Noto Sans Georgian Thin:style=Thin,Regular
- NotoSansCherokee-ExtraBold.ttf: Noto Sans Cherokee,Noto Sans Cherokee ExtBd:style=ExtraBold,Regular
- NotoSansKhmerUI-SemiCondensed.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond:style=SemiCondensed,Regular
- NotoSerifArmenian-SemiCondensedExtraBold.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn XBd:style=SemiCondensed ExtraBold,Regular
- Z003-MediumItalic.otf: Z003:style=Medium Italic
- NotoSansSymbols-Bold.ttf: Noto Sans Symbols:style=Bold
- NimbusSans-BoldItalic.otf: Nimbus Sans:style=Bold Italic
- NotoSansGeorgian-CondensedSemiBold.ttf: Noto Sans Georgian,Noto Sans Georgian Cond SemBd:style=Condensed SemiBold,Regular
- URWGothic-Book.otf: URW Gothic:style=Book
- NotoSansEthiopic-SemiCondensedLight.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond Light:style=SemiCondensed Light,Regular
- NotoSansMono-SemiCondensedLight.ttf: Noto Sans Mono,Noto Sans Mono SemCond Light:style=SemiCondensed Light,Regular
- NotoSansTamilUI-SemiBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemBd:style=SemiBold,Regular
- NotoSerifThai-Condensed.ttf: Noto Serif Thai,Noto Serif Thai Cond:style=Condensed,Regular
- NotoSerif-CondensedItalic.ttf: Noto Serif,Noto Serif Cond:style=Condensed Italic,Italic
- NotoSansDisplay-Black.ttf: Noto Sans Display,Noto Sans Disp Blk:style=Black,Regular
- NotoSansSinhala-CondensedExtraBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansSyriacEastern-Regular.ttf: Noto Sans Syriac Eastern:style=Regular
- NotoSansArabicUI-SemiCondensedLight.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn Lt:style=SemiCondensed Light,Regular
- NotoSerifLao-Black.ttf: Noto Serif Lao,Noto Serif Lao Blk:style=Black,Regular
- NotoSans-CondensedBold.ttf: Noto Sans,Noto Sans Cond:style=Condensed Bold,Bold
- NotoSansDisplay-CondensedMedium.ttf: Noto Sans Display,Noto Sans Disp Cond Med:style=Condensed Medium,Regular
- NotoSansGujaratiUI-Bold.ttf: Noto Sans Gujarati UI:style=Bold
- NotoSerif-SemiCondensedThin.ttf: Noto Serif,Noto Serif SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansThaiUI-Medium.ttf: Noto Sans Thai UI,Noto Sans Thai UI Med:style=Medium,Regular
- NotoSerifEthiopic-CondensedExtraLight.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn XLt:style=Condensed ExtraLight,Regular
- NotoSerif-ExtraCondensedMedium.ttf: Noto Serif,Noto Serif ExtCond Med:style=ExtraCondensed Medium,Regular
- d050000l.pfb: Dingbats:style=Regular
- NotoSerifCJKsc-Bold.otf: Noto Serif CJK SC:style=Bold
- NotoKufiArabic-Regular.ttf: Noto Kufi Arabic:style=Regular
- NotoSansGeorgian-ExtraCondensedExtraLight.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansMono-CondensedMedium.ttf: Noto Sans Mono,Noto Sans Mono Cond Med:style=Condensed Medium,Regular
- NotoSerifDisplay-LightItalic.ttf: Noto Serif Display,Noto Serif Disp Light:style=Light Italic,Italic
- NotoSansKhmer-ExtraCondensed.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond:style=ExtraCondensed,Regular
- NotoSansDisplay-ExtraCondensedMedium.ttf: Noto Sans Display,Noto Sans Disp ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansSinhala-ExtraLight.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtLt:style=ExtraLight,Regular
- NotoSansSundanese-Regular.ttf: Noto Sans Sundanese:style=Regular
- NotoSansGeorgian-SemiCondensedThin.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansCJKjp-Medium.otf: Noto Sans CJK JP,Noto Sans CJK JP Medium:style=Medium,Regular
- NotoSansEthiopic-SemiBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemBd:style=SemiBold,Regular
- NotoSansCham-ExtraLight.ttf: Noto Sans Cham,Noto Sans Cham ExtLt:style=ExtraLight,Regular
- NotoSansLepcha-Regular.ttf: Noto Sans Lepcha:style=Regular
- NotoSansEthiopic-Black.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Blk:style=Black,Regular
- NotoSansThaiUI-SemiCondensed.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond:style=SemiCondensed,Regular
- NotoSans-CondensedBoldItalic.ttf: Noto Sans,Noto Sans Cond:style=Condensed Bold Italic,Bold Italic
- NotoSansDisplay-SemiCondensedLightItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond Light:style=SemiCondensed Light Italic,Italic
- NotoSansRunic-Regular.ttf: Noto Sans Runic:style=Regular
- NotoSerifTamil-ExtraCondensedBlack.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansKhmerUI-CondensedBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond:style=Condensed Bold,Bold
- NotoSerifKhmer-ExtraCondensedBlack.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansTamil-CondensedExtraBold.ttf: Noto Sans Tamil,Noto Sans Tamil Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSerifTamil-Condensed.ttf: Noto Serif Tamil,Noto Serif Tamil Cond:style=Condensed,Regular
- NotoSansThai-Black.ttf: Noto Sans Thai,Noto Sans Thai Blk:style=Black,Regular
- NotoSansKhmer-Condensed.ttf: Noto Sans Khmer,Noto Sans Khmer Cond:style=Condensed,Regular
- NotoSansCanadianAboriginal-Regular.ttf: Noto Sans Canadian Aboriginal:style=Regular
- NotoSansSymbols-Medium.ttf: Noto Sans Symbols,Noto Sans Symbols Med:style=Medium,Regular
- NotoSerifDisplay-ExtraCondensedBoldItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond:style=ExtraCondensed Bold Italic,Bold Italic
- n021023l.pfb: Nimbus Roman No9 L:style=Regular Italic
- NotoSansTamilUI-SemiCondensedThin.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSerifLao-ExtraCondensed.ttf: Noto Serif Lao,Noto Serif Lao ExtCond:style=ExtraCondensed,Regular
- NotoSansTamilUI-Thin.ttf: Noto Sans Tamil UI,Noto Sans Tamil Thin:style=Thin,Regular
- NotoSansLaoUI-SemiBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemBd:style=SemiBold,Regular
- NotoSerif-ExtraCondensedLightItalic.ttf: Noto Serif,Noto Serif ExtCond Light:style=ExtraCondensed Light Italic,Italic
- NotoSansArabic-CondensedExtraBold.ttf: Noto Sans Arabic,Noto Sans Arabic Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansBengali-Thin.ttf: Noto Sans Bengali,Noto Sans Bengali Thin:style=Thin,Regular
- NotoSansLaoUI-SemiCondensed.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond:style=SemiCondensed,Regular
- NotoSansThaiUI-ExtraCondensedSemiBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerif-ExtraCondensed.ttf: Noto Serif,Noto Serif ExtCond:style=ExtraCondensed,Regular
- NotoSansSinhalaUI-ExtraBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtBd:style=ExtraBold,Regular
- NotoSerifArmenian-SemiCondensed.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn:style=SemiCondensed,Regular
- NotoSansDisplay-ExtraCondensedExtraBoldItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond ExtBd:style=ExtraCondensed ExtraBold Italic,Italic
- NotoSansDevanagari-SemiCondensedBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn:style=SemiCondensed Bold,Bold
- NotoSansGeorgian-ExtraLight.ttf: Noto Sans Georgian,Noto Sans Georgian ExtLt:style=ExtraLight,Regular
- NotoSansMono-CondensedExtraLight.ttf: Noto Sans Mono,Noto Sans Mono Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansArabicUI-Light.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Lt:style=Light,Regular
- NotoSansArabicUI-ExtraCondensedBlack.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn Bk:style=ExtraCondensed Black,Regular
- NotoSansArabicUI-SemiCondensedMedium.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn Md:style=SemiCondensed Medium,Regular
- NotoSerifArmenian-SemiCondensedSemiBold.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn SmBd:style=SemiCondensed SemiBold,Regular
- NotoSansTamil-CondensedBold.ttf: Noto Sans Tamil,Noto Sans Tamil Cond:style=Condensed Bold,Bold
- NotoSansTamilUI-CondensedSemiBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansMyanmarUI-CondensedLight.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn Lt:style=Condensed Light,Regular
- NotoSerifMyanmar-SemiCondensedBlack.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifThai-SemiCondensedBlack.ttf: Noto Serif Thai,Noto Serif Thai SemCond Blk:style=SemiCondensed Black,Regular
- D050000L.otf: D050000L:style=Regular
- NotoSansArabicUI-Condensed.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn:style=Condensed,Regular
- NotoSansTamilUI-ExtraCondensed.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond:style=ExtraCondensed,Regular
- NotoSerifGeorgian-SemiCondensedLight.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn Lt:style=SemiCondensed Light,Regular
- NotoSansSinhalaUI-ExtraCondensedSemiBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansMyanmar-SemiCondensedExtraLight.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansMyanmarUI-ExtraCondensedBlack.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn Bk:style=ExtraCondensed Black,Regular
- NotoSansDisplay-ExtraCondensedExtraLight.ttf: Noto Sans Display,Noto Sans Disp ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansHebrew-ExtraLight.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtLt:style=ExtraLight,Regular
- NotoSansCJKtc-Regular.otf: Noto Sans CJK TC,Noto Sans CJK TC Regular:style=Regular
- NotoSansTamil-Bold.ttf: Noto Sans Tamil:style=Bold
- NotoSansTamil-Medium.ttf: Noto Sans Tamil,Noto Sans Tamil Med:style=Medium,Regular
- NotoSerifCJKtc-Black.otf: Noto Serif CJK TC,Noto Serif CJK TC Black:style=Black,Regular
- NotoSansDevanagari-ExtraCondensedLight.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn Lt:style=ExtraCondensed Light,Regular
- NotoSansLaoUI-SemiCondensedBlack.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansHebrew-CondensedLight.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond Light:style=Condensed Light,Regular
- NotoSansAnatolianHieroglyphs-Regular.ttf: Noto Sans Anatolian Hieroglyphs,Noto Sans AnatoHiero:style=Regular
- NotoSansLaoUI-ExtraCondensed.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond:style=ExtraCondensed,Regular
- NotoSansLaoUI-Medium.ttf: Noto Sans Lao UI,Noto Sans Lao UI Med:style=Medium,Regular
- NotoSans-ExtraBoldItalic.ttf: Noto Sans,Noto Sans ExtBd:style=ExtraBold Italic,Italic
- NotoSans-Italic.ttf: Noto Sans:style=Italic
- NotoSansSaurashtra-Regular.ttf: Noto Sans Saurashtra:style=Regular
- NotoSansThai-SemiCondensed.ttf: Noto Sans Thai,Noto Sans Thai SemCond:style=SemiCondensed,Regular
- NotoSansDevanagari-CondensedLight.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn Lt:style=Condensed Light,Regular
- NotoSansGeorgian-CondensedBlack.ttf: Noto Sans Georgian,Noto Sans Georgian Cond Blk:style=Condensed Black,Regular
- NotoSansMyanmarUI-Light.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Lt:style=Light,Regular
- NotoSansThaiUI-CondensedLight.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond Light:style=Condensed Light,Regular
- NotoSerifThai-ExtraCondensedExtraLight.ttf: Noto Serif Thai,Noto Serif Thai ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifMyanmar-ExtraCondensedBlack.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansArabic-SemiCondensedThin.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansDisplay-Condensed.ttf: Noto Sans Display,Noto Sans Disp Cond:style=Condensed,Regular
- NotoSerifSinhala-Thin.ttf: Noto Serif Sinhala,Noto Serif Sinhala Thin:style=Thin,Regular
- NotoSansDevanagari-Condensed.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn:style=Condensed,Regular
- NotoSansTamil-CondensedExtraLight.ttf: Noto Sans Tamil,Noto Sans Tamil Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansMyanmar-SemiCondensedMedium.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond Med:style=SemiCondensed Medium,Regular
- n019063l.pfb: Nimbus Sans L:style=Regular Condensed Italic
- NotoSerifDisplay-Regular.ttf: Noto Serif Display,Noto Serif Disp:style=Regular
- NotoSansLao-ExtraCondensedMedium.ttf: Noto Sans Lao,Noto Sans Lao ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansEgyptianHieroglyphs-Regular.ttf: Noto Sans Egyptian Hieroglyphs,Noto Sans EgyptHiero:style=Regular
- NotoSansTamil-ExtraCondensed.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond:style=ExtraCondensed,Regular
- NotoSerifHebrew-ExtraCondensedLight.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSans-SemiCondensedExtraLightItalic.ttf: Noto Sans,Noto Sans SemCond ExtLt:style=SemiCondensed ExtraLight Italic,Italic
- C059-BdIta.otf: C059:style=Bold Italic
- NotoSansSylotiNagri-Regular.ttf: Noto Sans Syloti Nagri:style=Regular
- NotoSansTamil-ExtraCondensedBlack.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSerifThai-SemiCondensedMedium.ttf: Noto Serif Thai,Noto Serif Thai SemCond Med:style=SemiCondensed Medium,Regular
- NotoSerif-CondensedLightItalic.ttf: Noto Serif,Noto Serif Cond Light:style=Condensed Light Italic,Italic
- DejaVuSans-Bold.ttf: DejaVu Sans:style=Bold
- NotoSansThai-Medium.ttf: Noto Sans Thai,Noto Sans Thai Med:style=Medium,Regular
- NotoSansDevanagariUI-ExtraCondensedBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn:style=ExtraCondensed Bold,Bold
- NotoSansThaiUI-SemiCondensedExtraLight.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansTamil-Condensed.ttf: Noto Sans Tamil,Noto Sans Tamil Cond:style=Condensed,Regular
- NotoSans-ExtraCondensedLightItalic.ttf: Noto Sans,Noto Sans ExtCond Light:style=ExtraCondensed Light Italic,Italic
- NotoSansLao-Regular.ttf: Noto Sans Lao:style=Regular
- NotoSerifArmenian-Condensed.ttf: Noto Serif Armenian,Noto Serif Armenian Cn:style=Condensed,Regular
- NotoSerifDisplay-Italic.ttf: Noto Serif Display,Noto Serif Disp:style=Italic
- NotoSansSinhala-SemiCondensedMedium.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond Med:style=SemiCondensed Medium,Regular
- NotoSans-CondensedExtraBoldItalic.ttf: Noto Sans,Noto Sans Cond ExtBd:style=Condensed ExtraBold Italic,Italic
- NotoSerifTamil-CondensedMedium.ttf: Noto Serif Tamil,Noto Serif Tamil Cond Med:style=Condensed Medium,Regular
- NotoSansThaiUI-Condensed.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond:style=Condensed,Regular
- NotoSansMono-CondensedThin.ttf: Noto Sans Mono,Noto Sans Mono Cond Thin:style=Condensed Thin,Regular
- NotoSans-CondensedExtraLight.ttf: Noto Sans,Noto Sans Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansDevanagari-ExtraCondensedThin.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn Th:style=ExtraCondensed Thin,Regular
- NotoSerifGujarati-Regular.ttf: Noto Serif Gujarati:style=Regular
- NotoSerifMyanmar-ExtraCondensedLight.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansArabicUI-CondensedBlack.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn Bk:style=Condensed Black,Regular
- NotoSansKhmer-ExtraCondensedExtraBold.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerifGeorgian-CondensedBlack.ttf: Noto Serif Georgian,Noto Serif Georgian Cn Bk:style=Condensed Black,Regular
- NotoSansSinhala-ExtraCondensedExtraBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerifEthiopic-SemiCondensedExtraBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn XBd:style=SemiCondensed ExtraBold,Regular
- NotoSansMyanmar-SemiCondensedExtraBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansCherokee-Medium.ttf: Noto Sans Cherokee,Noto Sans Cherokee Med:style=Medium,Regular
- NotoSerifDevanagari-Bold.ttf: Noto Serif Devanagari:style=Bold
- NotoSansGeorgian-ExtraCondensedBold.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansMeeteiMayek-Regular.ttf: Noto Sans Meetei Mayek:style=Regular
- NotoSansThaana-Bold.ttf: Noto Sans Thaana:style=Bold
- NotoSansKannada-Bold.ttf: Noto Sans Kannada:style=Bold
- NotoSerifKhmer-CondensedExtraBold.ttf: Noto Serif Khmer,Noto Serif Khmer Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansDevanagari-SemiBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmBd:style=SemiBold,Regular
- NotoSansKhmerUI-SemiBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemBd:style=SemiBold,Regular
- NotoSansSinhalaUI-SemiCondensedMedium.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansDevanagariUI-SemiCondensedLight.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn Lt:style=SemiCondensed Light,Regular
- NotoSansDevanagariUI-ExtraBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XBd:style=ExtraBold,Regular
- NotoSerifThai-SemiCondensedExtraBold.ttf: Noto Serif Thai,Noto Serif Thai SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansDisplay-Light.ttf: Noto Sans Display,Noto Sans Disp Light:style=Light,Regular
- NotoSansEthiopic-Condensed.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond:style=Condensed,Regular
- NotoSerifMyanmar-SemiCondensedExtraBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansMyanmar-ExtraCondensed.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond:style=ExtraCondensed,Regular
- NotoSansArabicUI-SemiBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmBd:style=SemiBold,Regular
- NotoSerif-ThinItalic.ttf: Noto Serif,Noto Serif Thin:style=Thin Italic,Italic
- NotoSansArabicUI-ExtraCondensedThin.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn Th:style=ExtraCondensed Thin,Regular
- NotoSansKhmer-SemiCondensedExtraLight.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- a010013l.pfb: URW Gothic L:style=Book
- NotoSansDevanagari-CondensedThin.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn Th:style=Condensed Thin,Regular
- NotoSerifThai-SemiCondensedExtraLight.ttf: Noto Serif Thai,Noto Serif Thai SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansKhmerUI-CondensedThin.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond Thin:style=Condensed Thin,Regular
- NotoSansArabicUI-ExtraCondensed.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn:style=ExtraCondensed,Regular
- NotoSerif-CondensedThin.ttf: Noto Serif,Noto Serif Cond Thin:style=Condensed Thin,Regular
- NotoSerifDisplay-BlackItalic.ttf: Noto Serif Display,Noto Serif Disp Blk:style=Black Italic,Italic
- NotoSansImperialAramaic-Regular.ttf: Noto Sans Imperial Aramaic,Noto Sans ImpAramaic:style=Regular
- NotoSansSinhalaUI-ExtraCondensedBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifLao-CondensedMedium.ttf: Noto Serif Lao,Noto Serif Lao Cond Med:style=Condensed Medium,Regular
- NotoSansArabic-Thin.ttf: Noto Sans Arabic,Noto Sans Arabic Thin:style=Thin,Regular
- NotoSansHebrew-CondensedMedium.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond Med:style=Condensed Medium,Regular
- NotoSansEthiopic-Medium.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Med:style=Medium,Regular
- NotoSerifLao-SemiCondensedExtraLight.ttf: Noto Serif Lao,Noto Serif Lao SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSans-CondensedItalic.ttf: Noto Sans,Noto Sans Cond:style=Condensed Italic,Italic
- NotoSansCJKjp-Light.otf: Noto Sans CJK JP,Noto Sans CJK JP Light:style=Light,Regular
- NimbusRoman-Regular.otf: Nimbus Roman:style=Regular
- NotoSansDevanagariUI-ExtraCondensedMedium.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn Md:style=ExtraCondensed Medium,Regular
- NotoSansThaiUI-ExtraCondensedExtraLight.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifLao-ExtraCondensedBold.ttf: Noto Serif Lao,Noto Serif Lao ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifTamil-ExtraBold.ttf: Noto Serif Tamil,Noto Serif Tamil ExtBd:style=ExtraBold,Regular
- NotoSerifThai-ExtraCondensedSemiBold.ttf: Noto Serif Thai,Noto Serif Thai ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansLao-ExtraBold.ttf: Noto Sans Lao,Noto Sans Lao ExtBd:style=ExtraBold,Regular
- NotoSerifMyanmar-SemiCondensedSemiBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansDisplay-ThinItalic.ttf: Noto Sans Display,Noto Sans Disp Thin:style=Thin Italic,Italic
- NotoSansKhmerUI-ExtraCondensedBlack.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansEthiopic-Regular.ttf: Noto Sans Ethiopic:style=Regular
- NotoSansOsage-Regular.ttf: Noto Sans Osage:style=Regular
- NotoSans-ExtraCondensedSemiBold.ttf: Noto Sans,Noto Sans ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerif-ExtraCondensedMediumItalic.ttf: Noto Serif,Noto Serif ExtCond Med:style=ExtraCondensed Medium Italic,Italic
- NotoSerifKhmer-SemiCondensedThin.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansArmenian-Thin.ttf: Noto Sans Armenian,Noto Sans Armenian Thin:style=Thin,Regular
- C059-Italic.otf: C059:style=Italic
- NotoSerifMyanmar-ExtraCondensedExtraLight.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifKhmer-CondensedThin.ttf: Noto Serif Khmer,Noto Serif Khmer Cond Thin:style=Condensed Thin,Regular
- NotoNastaliqUrdu-Regular.ttf: Noto Nastaliq Urdu:style=Regular
- NotoSansMyanmar-SemiCondensedBlack.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifDisplay-ExtraCondensedBlackItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond Blk:style=ExtraCondensed Black Italic,Italic
- NotoSerifThai-ExtraBold.ttf: Noto Serif Thai,Noto Serif Thai ExtBd:style=ExtraBold,Regular
- NotoSerifEthiopic-CondensedMedium.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn Md:style=Condensed Medium,Regular
- NotoSerifMyanmar-ExtraCondensedThin.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansLao-ExtraCondensedBold.ttf: Noto Sans Lao,Noto Sans Lao ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansLisu-Regular.ttf: Noto Sans Lisu:style=Regular
- NotoSansThai-CondensedSemiBold.ttf: Noto Sans Thai,Noto Sans Thai Cond SemBd:style=Condensed SemiBold,Regular
- NotoSerifTamil-SemiCondensedMedium.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond Med:style=SemiCondensed Medium,Regular
- NotoSerifLao-SemiCondensedBlack.ttf: Noto Serif Lao,Noto Serif Lao SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansSinhalaUI-CondensedExtraLight.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSans-SemiCondensedMedium.ttf: Noto Sans,Noto Sans SemCond Med:style=SemiCondensed Medium,Regular
- NimbusMonoPS-Bold.otf: Nimbus Mono PS:style=Bold
- NimbusRoman-Bold.otf: Nimbus Roman:style=Bold
- NotoSansKhmerUI-CondensedExtraBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSerifCJKsc-ExtraLight.otf: Noto Serif CJK SC,Noto Serif CJK SC ExtraLight:style=ExtraLight,Regular
- NotoSansMalayalamUI-Regular.ttf: Noto Sans Malayalam UI:style=Regular
- NotoSerifKhmer-SemiCondensedLight.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond Light:style=SemiCondensed Light,Regular
- NotoSansDisplay-ExtraCondensedExtraBold.ttf: Noto Sans Display,Noto Sans Disp ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansEthiopic-CondensedMedium.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond Med:style=Condensed Medium,Regular
- NotoSerifDisplay-ExtraCondensedLightItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond Light:style=ExtraCondensed Light Italic,Italic
- NotoSansArabicUI-CondensedExtraBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn XBd:style=Condensed ExtraBold,Regular
- NimbusSansNarrow-Bold.t1: Nimbus Sans Narrow:style=Bold
- NotoSansArabicUI-SemiCondensedExtraLight.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn XLt:style=SemiCondensed ExtraLight,Regular
- NotoSansLaoUI-CondensedMedium.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond Med:style=Condensed Medium,Regular
- NotoSans-SemiCondensedThin.ttf: Noto Sans,Noto Sans SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSerifHebrew-SemiCondensedBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond:style=SemiCondensed Bold,Bold
- NotoSansTamilUI-ExtraCondensedBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifHebrew-ExtraCondensedExtraBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NimbusRoman-BoldItalic.otf: Nimbus Roman:style=Bold Italic
- NotoSansKhmerUI-CondensedLight.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond Light:style=Condensed Light,Regular
- NotoSansSinhalaUI-CondensedBlack.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond Blk:style=Condensed Black,Regular
- NotoSansGurmukhiUI-Regular.ttf: Noto Sans Gurmukhi UI:style=Regular
- NotoSansTamil-SemiCondensedBold.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond:style=SemiCondensed Bold,Bold
- NotoSansDevanagari-SemiCondensed.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn:style=SemiCondensed,Regular
- NotoSans-SemiCondensedItalic.ttf: Noto Sans,Noto Sans SemCond:style=SemiCondensed Italic,Italic
- NotoSansTamil-ExtraBold.ttf: Noto Sans Tamil,Noto Sans Tamil ExtBd:style=ExtraBold,Regular
- NotoSerifKannada-Bold.ttf: Noto Serif Kannada:style=Bold
- NotoSansMyanmarUI-SemiCondensedExtraBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn XBd:style=SemiCondensed ExtraBold,Regular
- NotoSerifKhmer-SemiCondensedMedium.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansGeorgian-ExtraCondensedThin.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansGujarati-Bold.ttf: Noto Sans Gujarati:style=Bold
- NotoSerif-Black.ttf: Noto Serif,Noto Serif Blk:style=Black,Regular
- NotoSansSymbols-ExtraLight.ttf: Noto Sans Symbols,Noto Sans Symbols ExtLt:style=ExtraLight,Regular
- NotoSerifHebrew-ExtraBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtBd:style=ExtraBold,Regular
- NotoSerifSinhala-Regular.ttf: Noto Serif Sinhala:style=Regular
- NotoSerifGeorgian-SemiBold.ttf: Noto Serif Georgian,Noto Serif Georgian SmBd:style=SemiBold,Regular
- NotoSansTamil-CondensedLight.ttf: Noto Sans Tamil,Noto Sans Tamil Cond Light:style=Condensed Light,Regular
- NotoSerifDisplay-SemiCondensedExtraBoldItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond ExtBd:style=SemiCondensed ExtraBold Italic,Italic
- NotoSansDevanagari-Black.ttf: Noto Sans Devanagari,Noto Sans Devanagari Bk:style=Black,Regular
- NotoSansThaiUI-CondensedExtraBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSerifEthiopic-ExtraCondensedThin.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn Th:style=ExtraCondensed Thin,Regular
- n019064l.pfb: Nimbus Sans L:style=Bold Condensed Italic
- NotoSerifEthiopic-CondensedSemiBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn SmBd:style=Condensed SemiBold,Regular
- NotoSansDevanagariUI-ExtraCondensed.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn:style=ExtraCondensed,Regular
- NotoSerif-BlackItalic.ttf: Noto Serif,Noto Serif Blk:style=Black Italic,Italic
- NotoSerifMyanmar-CondensedExtraLight.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSerifMyanmar-SemiCondensedMedium.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond Med:style=SemiCondensed Medium,Regular
- NotoSans-ExtraCondensedBlack.ttf: Noto Sans,Noto Sans ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansMalayalamUI-Bold.ttf: Noto Sans Malayalam UI:style=Bold
- NotoSansEthiopic-SemiCondensedBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond:style=SemiCondensed Bold,Bold
- NotoSans-CondensedSemiBold.ttf: Noto Sans,Noto Sans Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansThai-SemiCondensedExtraBold.ttf: Noto Sans Thai,Noto Sans Thai SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSerifEthiopic-SemiCondensedMedium.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn Md:style=SemiCondensed Medium,Regular
- NotoSansSinhala-Light.ttf: Noto Sans Sinhala,Noto Sans Sinhala Light:style=Light,Regular
- NotoSansGujarati-Regular.ttf: Noto Sans Gujarati:style=Regular
- NotoSerif-ExtraCondensedExtraLightItalic.ttf: Noto Serif,Noto Serif ExtCond ExtLt:style=ExtraCondensed ExtraLight Italic,Italic
- NotoSansGeorgian-SemiCondensed.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond:style=SemiCondensed,Regular
- NotoSerifEthiopic-SemiCondensedExtraLight.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn XLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifGeorgian-CondensedExtraLight.ttf: Noto Serif Georgian,Noto Serif Georgian Cn XLt:style=Condensed ExtraLight,Regular
- NotoSerifLao-SemiCondensedMedium.ttf: Noto Serif Lao,Noto Serif Lao SemCond Med:style=SemiCondensed Medium,Regular
- DroidSansFallbackFull.ttf: Droid Sans Fallback:style=Regular
- NotoSansLaoUI-ExtraCondensedThin.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansMyanmar-SemiCondensedSemiBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansTamilUI-CondensedExtraBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSerifLao-SemiCondensedThin.ttf: Noto Serif Lao,Noto Serif Lao SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansOldSouthArabian-Regular.ttf: Noto Sans Old South Arabian,Noto Sans OldSouArab:style=Regular
- p052004l.pfb: URW Palladio L:style=Bold
- NotoSansMyanmarUI-CondensedThin.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn Th:style=Condensed Thin,Regular
- NotoSansLao-SemiCondensedSemiBold.ttf: Noto Sans Lao,Noto Sans Lao SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansLaoUI-SemiCondensedThin.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSerifGeorgian-ExtraCondensedExtraLight.ttf: Noto Serif Georgian,Noto Serif Georgian XCn XLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansArabic-SemiCondensedBlack.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansTamilUI-ExtraCondensedMedium.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansEthiopic-SemiCondensedThin.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSans-CondensedMediumItalic.ttf: Noto Sans,Noto Sans Cond Med:style=Condensed Medium Italic,Italic
- NotoSansHebrew-SemiBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemBd:style=SemiBold,Regular
- NotoSansTamilUI-ExtraBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtBd:style=ExtraBold,Regular
- NotoSerifKhmer-ExtraCondensedExtraBold.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerifDisplay-SemiCondensedBlack.ttf: Noto Serif Display,Noto Serif Disp SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifTamil-Regular.ttf: Noto Serif Tamil:style=Regular
- NotoSansCJKkr-DemiLight.otf: Noto Sans CJK KR,Noto Sans CJK KR DemiLight:style=DemiLight,Regular
- NotoSerifDisplay-ExtraCondensedExtraLight.ttf: Noto Serif Display,Noto Serif Disp ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansArabic-Regular.ttf: Noto Sans Arabic:style=Regular
- NotoSansNKo-Regular.ttf: Noto Sans NKo,Noto Sans N'Ko:style=Regular
- NotoSansKhmerUI-ExtraLight.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtLt:style=ExtraLight,Regular
- NotoSansMyanmar-CondensedLight.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond Light:style=Condensed Light,Regular
- NotoSansDisplay-SemiCondensedExtraLight.ttf: Noto Sans Display,Noto Sans Disp SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansSinhalaUI-Bold.ttf: Noto Sans Sinhala UI:style=Bold
- NotoSans-CondensedMedium.ttf: Noto Sans,Noto Sans Cond Med:style=Condensed Medium,Regular
- NotoSansDisplay-CondensedSemiBold.ttf: Noto Sans Display,Noto Sans Disp Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansLao-ExtraCondensedExtraLight.ttf: Noto Sans Lao,Noto Sans Lao ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifKhmer-Light.ttf: Noto Serif Khmer,Noto Serif Khmer Light:style=Light,Regular
- NotoSansSinhalaUI-SemiCondensed.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond:style=SemiCondensed,Regular
- NotoSerif-CondensedBold.ttf: Noto Serif,Noto Serif Cond:style=Condensed Bold,Bold
- NotoSansDevanagariUI-ExtraCondensedExtraBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn XBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansEthiopic-Bold.ttf: Noto Sans Ethiopic:style=Bold
- NotoSansGeorgian-SemiCondensedSemiBold.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSerif-ExtraLightItalic.ttf: Noto Serif,Noto Serif ExtLt:style=ExtraLight Italic,Italic
- C059-Roman.t1: C059:style=Roman
- NotoSerifMyanmar-CondensedExtraBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansDevanagariUI-CondensedBlack.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn Bk:style=Condensed Black,Regular
- NotoSansKhmerUI-SemiCondensedSemiBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansKannadaUI-Regular.ttf: Noto Sans Kannada UI:style=Regular
- NotoSansSinhala-ExtraCondensedSemiBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansOsmanya-Regular.ttf: Noto Sans Osmanya:style=Regular
- NotoSerifGeorgian-ExtraCondensedThin.ttf: Noto Serif Georgian,Noto Serif Georgian XCn Th:style=ExtraCondensed Thin,Regular
- NotoSansKhmerUI-SemiCondensedThin.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansArabicUI-Thin.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Th:style=Thin,Regular
- NotoSerifArmenian-ExtraCondensedBlack.ttf: Noto Serif Armenian,Noto Serif Armenian XCn Bk:style=ExtraCondensed Black,Regular
- NotoSerifMyanmar-CondensedMedium.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond Med:style=Condensed Medium,Regular
- NotoSansDevanagariUI-SemiCondensedThin.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn Th:style=SemiCondensed Thin,Regular
- NotoSansMyanmar-CondensedExtraBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansTamil-SemiCondensedExtraBold.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansLao-CondensedBold.ttf: Noto Sans Lao,Noto Sans Lao Cond:style=Condensed Bold,Bold
- NotoSerifGeorgian-CondensedExtraBold.ttf: Noto Serif Georgian,Noto Serif Georgian Cn XBd:style=Condensed ExtraBold,Regular
- NotoSansSinhalaUI-Medium.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Med:style=Medium,Regular
- NotoSansMono-CondensedBold.ttf: Noto Sans Mono,Noto Sans Mono Cond:style=Condensed Bold,Bold
- NotoSansArabicUI-SemiCondensedExtraBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn XBd:style=SemiCondensed ExtraBold,Regular
- NotoSans-MediumItalic.ttf: Noto Sans,Noto Sans Med:style=Medium Italic,Italic
- NotoSansArabic-SemiBold.ttf: Noto Sans Arabic,Noto Sans Arabic SemBd:style=SemiBold,Regular
- NotoSansAdlamUnjoined-Regular.ttf: Noto Sans Adlam Unjoined:style=Regular
- NotoSansArmenian-SemiCondensedSemiBold.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansSymbols-ExtraBold.ttf: Noto Sans Symbols,Noto Sans Symbols ExtBd:style=ExtraBold,Regular
- NotoSansThai-ExtraCondensedBold.ttf: Noto Sans Thai,Noto Sans Thai ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansTamilUI-CondensedLight.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond Light:style=Condensed Light,Regular
- NotoSansLycian-Regular.ttf: Noto Sans Lycian:style=Regular
- NotoSansDisplay-CondensedLight.ttf: Noto Sans Display,Noto Sans Disp Cond Light:style=Condensed Light,Regular
- NotoSansGeorgian-SemiCondensedBold.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond:style=SemiCondensed Bold,Bold
- NotoSerifCJKjp-ExtraLight.otf: Noto Serif CJK JP,Noto Serif CJK JP ExtraLight:style=ExtraLight,Regular
- NimbusRoman-Italic.t1: Nimbus Roman:style=Italic
- NotoSerifDisplay-ExtraCondensedSemiBoldItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond SemBd:style=ExtraCondensed SemiBold Italic,Italic
- NotoSansThai-SemiCondensedSemiBold.ttf: Noto Sans Thai,Noto Sans Thai SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansMono-ExtraCondensedThin.ttf: Noto Sans Mono,Noto Sans Mono ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifThai-ExtraCondensedBlack.ttf: Noto Serif Thai,Noto Serif Thai ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansMyanmarUI-CondensedExtraLight.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn XLt:style=Condensed ExtraLight,Regular
- NotoSansSinhala-Condensed.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond:style=Condensed,Regular
- NotoSansGeorgian-SemiCondensedBlack.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond Blk:style=SemiCondensed Black,Regular
- NimbusSans-Italic.otf: Nimbus Sans:style=Italic
- NotoSansArmenian-SemiCondensedBold.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond:style=SemiCondensed Bold,Bold
- NotoSerifDisplay-Medium.ttf: Noto Serif Display,Noto Serif Disp Med:style=Medium,Regular
- NotoSerifHebrew-ExtraCondensedMedium.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansLao-SemiCondensedExtraLight.ttf: Noto Sans Lao,Noto Sans Lao SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansArabicUI-ExtraBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XBd:style=ExtraBold,Regular
- NotoSansCJKtc-Light.otf: Noto Sans CJK TC,Noto Sans CJK TC Light:style=Light,Regular
- NotoSerifKhmer-SemiCondensedExtraBold.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansCherokee-SemiBold.ttf: Noto Sans Cherokee,Noto Sans Cherokee SemBd:style=SemiBold,Regular
- NotoSansDisplay-MediumItalic.ttf: Noto Sans Display,Noto Sans Disp Med:style=Medium Italic,Italic
- NotoSerifLao-SemiBold.ttf: Noto Serif Lao,Noto Serif Lao SemBd:style=SemiBold,Regular
- n022023l.pfb: Nimbus Mono L:style=Regular Oblique
- NotoSansCham-Medium.ttf: Noto Sans Cham,Noto Sans Cham Med:style=Medium,Regular
- NotoSansDevanagariUI-ExtraCondensedSemiBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn SmBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifDisplay-CondensedLight.ttf: Noto Serif Display,Noto Serif Disp Cond Light:style=Condensed Light,Regular
- NotoSansEthiopic-ExtraCondensedSemiBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansMono-Light.ttf: Noto Sans Mono,Noto Sans Mono Light:style=Light,Regular
- NotoSerifLao-CondensedExtraLight.ttf: Noto Serif Lao,Noto Serif Lao Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansTamilUI-Black.ttf: Noto Sans Tamil UI,Noto Sans Tamil Blk:style=Black,Regular
- NotoSansArabicUI-Regular.ttf: Noto Sans Arabic UI:style=Regular
- NotoSerifCJKtc-Bold.otf: Noto Serif CJK TC:style=Bold
- NotoSansBengali-Light.ttf: Noto Sans Bengali,Noto Sans Bengali Light:style=Light,Regular
- NotoSansEthiopic-CondensedLight.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond Light:style=Condensed Light,Regular
- NotoSans-Regular.ttf: Noto Sans:style=Regular
- NotoSansThaiUI-ExtraCondensedLight.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansSinhala-Regular.ttf: Noto Sans Sinhala:style=Regular
- NotoSansMono-Black.ttf: Noto Sans Mono,Noto Sans Mono Blk:style=Black,Regular
- NotoSansDevanagariUI-CondensedThin.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn Th:style=Condensed Thin,Regular
- NotoSerifLao-ExtraLight.ttf: Noto Serif Lao,Noto Serif Lao ExtLt:style=ExtraLight,Regular
- NotoSansSinhalaUI-CondensedLight.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond Light:style=Condensed Light,Regular
- NotoSansSinhala-SemiCondensedLight.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond Light:style=SemiCondensed Light,Regular
- NotoSerifGeorgian-Black.ttf: Noto Serif Georgian,Noto Serif Georgian Bk:style=Black,Regular
- NotoSansLao-ExtraLight.ttf: Noto Sans Lao,Noto Sans Lao ExtLt:style=ExtraLight,Regular
- NotoSansTamil-ExtraCondensedMedium.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansDisplay-SemiCondensedMedium.ttf: Noto Sans Display,Noto Sans Disp SemCond Med:style=SemiCondensed Medium,Regular
- NotoSerifEthiopic-Light.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Lt:style=Light,Regular
- NotoSerifGujarati-Bold.ttf: Noto Serif Gujarati:style=Bold
- NotoSansDevanagariUI-Light.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Lt:style=Light,Regular
- NotoSansDevanagariUI-Condensed.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn:style=Condensed,Regular
- NotoSerifHebrew-SemiCondensed.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond:style=SemiCondensed,Regular
- NotoSansLaoUI-CondensedExtraBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSerif-SemiCondensedItalic.ttf: Noto Serif,Noto Serif SemCond:style=SemiCondensed Italic,Italic
- NotoSansTamilUI-SemiCondensedMedium.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansArabic-Medium.ttf: Noto Sans Arabic,Noto Sans Arabic Med:style=Medium,Regular
- NotoSansHebrew-SemiCondensedBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond:style=SemiCondensed Bold,Bold
- NotoSansMono-ExtraCondensedExtraBold.ttf: Noto Sans Mono,Noto Sans Mono ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansThai-ExtraLight.ttf: Noto Sans Thai,Noto Sans Thai ExtLt:style=ExtraLight,Regular
- NotoSerif-CondensedThinItalic.ttf: Noto Serif,Noto Serif Cond Thin:style=Condensed Thin Italic,Italic
- URWBookman-Demi.t1: URW Bookman:style=Demi
- NotoSansSyriacEstrangela-Regular.ttf: Noto Sans Syriac Estrangela:style=Regular
- NotoSansKhmer-Medium.ttf: Noto Sans Khmer,Noto Sans Khmer Med:style=Medium,Regular
- NotoSansLaoUI-Thin.ttf: Noto Sans Lao UI,Noto Sans Lao UI Thin:style=Thin,Regular
- NotoSerif-SemiCondensedExtraBoldItalic.ttf: Noto Serif,Noto Serif SemCond ExtBd:style=SemiCondensed ExtraBold Italic,Italic
- NotoSerifHebrew-CondensedMedium.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond Med:style=Condensed Medium,Regular
- NotoSansSinhalaUI-SemiCondensedThin.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansTamil-CondensedBlack.ttf: Noto Sans Tamil,Noto Sans Tamil Cond Blk:style=Condensed Black,Regular
- NotoSerifHebrew-CondensedBlack.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond Blk:style=Condensed Black,Regular
- NotoSansUgaritic-Regular.ttf: Noto Sans Ugaritic:style=Regular
- NotoSansMyanmar-ExtraCondensedExtraLight.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansSymbols2-Regular.ttf: Noto Sans Symbols2:style=Regular
- NotoSansKhmer-ExtraCondensedExtraLight.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansHebrew-CondensedThin.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond Thin:style=Condensed Thin,Regular
- NotoSansGeorgian-Condensed.ttf: Noto Sans Georgian,Noto Sans Georgian Cond:style=Condensed,Regular
- NotoSerifCJKkr-SemiBold.otf: Noto Serif CJK KR,Noto Serif CJK KR SemiBold:style=SemiBold,Regular
- NotoSerifDisplay-ExtraCondensedLight.ttf: Noto Serif Display,Noto Serif Disp ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansOriyaUI-Bold.ttf: Noto Sans Oriya UI:style=Bold
- a010015l.pfb: URW Gothic L:style=Demi
- NotoSansMyanmarUI-SemiCondensedExtraLight.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn XLt:style=SemiCondensed ExtraLight,Regular
- NotoSansArmenian-CondensedExtraBold.ttf: Noto Sans Armenian,Noto Sans Armenian Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansLaoUI-SemiCondensedLight.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond Light:style=SemiCondensed Light,Regular
- NotoSansBengali-Regular.ttf: Noto Sans Bengali:style=Regular
- NotoSansSinhalaUI-Thin.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Thin:style=Thin,Regular
- NotoSerifMyanmar-ExtraCondensedExtraBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerifDisplay-ExtraCondensedMedium.ttf: Noto Serif Display,Noto Serif Disp ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansLao-Black.ttf: Noto Sans Lao,Noto Sans Lao Blk:style=Black,Regular
- NotoSans-ExtraCondensedBlackItalic.ttf: Noto Sans,Noto Sans ExtCond Blk:style=ExtraCondensed Black Italic,Italic
- NotoSansThai-ExtraCondensedExtraBold.ttf: Noto Sans Thai,Noto Sans Thai ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansKhmer-SemiCondensed.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond:style=SemiCondensed,Regular
- NotoSansDevanagari-CondensedMedium.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn Md:style=Condensed Medium,Regular
- NotoSansGeorgian-ExtraCondensedExtraBold.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansSinhala-SemiCondensedThin.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSerifLao-CondensedThin.ttf: Noto Serif Lao,Noto Serif Lao Cond Thin:style=Condensed Thin,Regular
- NotoSansTamilUI-ExtraCondensedExtraBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerif-ExtraCondensedBoldItalic.ttf: Noto Serif,Noto Serif ExtCond:style=ExtraCondensed Bold Italic,Bold Italic
- NotoSansArmenian-CondensedMedium.ttf: Noto Sans Armenian,Noto Sans Armenian Cond Med:style=Condensed Medium,Regular
- NotoSansMyanmarUI-ExtraCondensedThin.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn Th:style=ExtraCondensed Thin,Regular
- NotoSansMyanmarUI-CondensedMedium.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn Md:style=Condensed Medium,Regular
- NotoSerifDisplay-SemiCondensedBold.ttf: Noto Serif Display,Noto Serif Disp SemCond:style=SemiCondensed Bold,Bold
- NotoSerifThai-ExtraCondensedBold.ttf: Noto Serif Thai,Noto Serif Thai ExtCond:style=ExtraCondensed Bold,Bold
- NotoSans-SemiCondensedExtraBold.ttf: Noto Sans,Noto Sans SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- URWGothic-Book.t1: URW Gothic:style=Book
- NotoSerifCJKkr-Bold.otf: Noto Serif CJK KR:style=Bold
- NotoSansDisplay-ExtraCondensed.ttf: Noto Sans Display,Noto Sans Disp ExtCond:style=ExtraCondensed,Regular
- NotoSansDevanagariUI-CondensedExtraBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn XBd:style=Condensed ExtraBold,Regular
- NotoSansArabicUI-Medium.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Md:style=Medium,Regular
- DejaVuSansMono-Bold.ttf: DejaVu Sans Mono:style=Bold
- NimbusRoman-Regular.t1: Nimbus Roman:style=Regular
- NotoSansMyanmar-ExtraCondensedExtraBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NimbusMonoPS-Regular.otf: Nimbus Mono PS:style=Regular
- NotoSerifKhmer-Regular.ttf: Noto Serif Khmer:style=Regular
- NotoSans-ExtraCondensedBold.ttf: Noto Sans,Noto Sans ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansEthiopic-SemiCondensedExtraBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NimbusSansNarrow-Regular.otf: Nimbus Sans Narrow:style=Regular
- NotoSansDisplay-ExtraCondensedSemiBoldItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond SemBd:style=ExtraCondensed SemiBold Italic,Italic
- NotoSansArabic-ExtraLight.ttf: Noto Sans Arabic,Noto Sans Arabic ExtLt:style=ExtraLight,Regular
- NotoSerifDisplay-ExtraLight.ttf: Noto Serif Display,Noto Serif Disp ExtLt:style=ExtraLight,Regular
- NotoSerifDevanagari-Regular.ttf: Noto Serif Devanagari:style=Regular
- NotoSerifThai-CondensedBlack.ttf: Noto Serif Thai,Noto Serif Thai Cond Blk:style=Condensed Black,Regular
- NotoSansKharoshthi-Regular.ttf: Noto Sans Kharoshthi:style=Regular
- NotoSansKhmer-CondensedSemiBold.ttf: Noto Sans Khmer,Noto Sans Khmer Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansArabic-ExtraCondensed.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond:style=ExtraCondensed,Regular
- n019043l.pfb: Nimbus Sans L:style=Regular Condensed
- NotoSerif-SemiCondensedBoldItalic.ttf: Noto Serif,Noto Serif SemCond:style=SemiCondensed Bold Italic,Bold Italic
- NotoSansDevanagari-CondensedExtraLight.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn XLt:style=Condensed ExtraLight,Regular
- NotoSerifArmenian-Regular.ttf: Noto Serif Armenian:style=Regular
- NotoSerifDisplay-ExtraCondensedMediumItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond Med:style=ExtraCondensed Medium Italic,Italic
- NotoSansMono-ExtraLight.ttf: Noto Sans Mono,Noto Sans Mono ExtLt:style=ExtraLight,Regular
- NotoSansKhmer-ExtraCondensedThin.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifSinhala-Medium.ttf: Noto Serif Sinhala,Noto Serif Sinhala Med:style=Medium,Regular
- NotoSansSinhalaUI-CondensedExtraBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansDeseret-Regular.ttf: Noto Sans Deseret:style=Regular
- NotoSerifHebrew-CondensedExtraBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansThaiUI-SemiCondensedBlack.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansEthiopic-ExtraBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtBd:style=ExtraBold,Regular
- NotoSans-ExtraCondensedExtraLight.ttf: Noto Sans,Noto Sans ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansDisplay-CondensedExtraBoldItalic.ttf: Noto Sans Display,Noto Sans Disp Cond ExtBd:style=Condensed ExtraBold Italic,Italic
- NotoSansDisplay-SemiBoldItalic.ttf: Noto Sans Display,Noto Sans Disp SemBd:style=SemiBold Italic,Italic
- NotoSerifLao-CondensedBold.ttf: Noto Serif Lao,Noto Serif Lao Cond:style=Condensed Bold,Bold
- NotoSansDisplay-SemiCondensedThin.ttf: Noto Sans Display,Noto Sans Disp SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSans-ExtraCondensedThin.ttf: Noto Sans,Noto Sans ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerif-ExtraCondensedBlack.ttf: Noto Serif,Noto Serif ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSerifDisplay-Black.ttf: Noto Serif Display,Noto Serif Disp Blk:style=Black,Regular
- NotoSansMyanmarUI-CondensedExtraBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn XBd:style=Condensed ExtraBold,Regular
- NotoSerifGeorgian-CondensedThin.ttf: Noto Serif Georgian,Noto Serif Georgian Cn Th:style=Condensed Thin,Regular
- NotoSansMyanmar-ExtraCondensedBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifKhmer-CondensedBlack.ttf: Noto Serif Khmer,Noto Serif Khmer Cond Blk:style=Condensed Black,Regular
- NotoSansDisplay-ExtraLight.ttf: Noto Sans Display,Noto Sans Disp ExtLt:style=ExtraLight,Regular
- NotoSansMyanmarUI-SemiCondensed.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn:style=SemiCondensed,Regular
- NotoSans-ExtraCondensedMedium.ttf: Noto Sans,Noto Sans ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSerifKhmer-Bold.ttf: Noto Serif Khmer:style=Bold
- NotoSansMyanmar-Thin.ttf: Noto Sans Myanmar,Noto Sans Myanmar Thin:style=Thin,Regular
- NotoSansBengaliUI-Thin.ttf: Noto Sans Bengali UI,Noto Sans Bengali Thin:style=Thin,Regular
- NotoSansDevanagari-SemiCondensedLight.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn Lt:style=SemiCondensed Light,Regular
- NotoSerifTamil-ExtraCondensed.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond:style=ExtraCondensed,Regular
- URWBookman-Demi.otf: URW Bookman:style=Demi
- NotoSansDevanagari-CondensedBlack.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn Bk:style=Condensed Black,Regular
- NimbusMonoPS-Regular.t1: Nimbus Mono PS:style=Regular
- NotoSerifHebrew-ExtraCondensedThin.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond Thin:style=ExtraCondensed Thin,Regular
- NimbusSans-BoldItalic.t1: Nimbus Sans:style=Bold Italic
- NimbusSans-Bold.t1: Nimbus Sans:style=Bold
- NotoSansDevanagariUI-Regular.ttf: Noto Sans Devanagari UI:style=Regular
- NotoSerifDisplay-ThinItalic.ttf: Noto Serif Display,Noto Serif Disp Thin:style=Thin Italic,Italic
- NotoSansOldItalic-Regular.ttf: Noto Sans Old Italic:style=Regular
- n019044l.pfb: Nimbus Sans L:style=Bold Condensed
- NotoSerifDisplay-SemiBoldItalic.ttf: Noto Serif Display,Noto Serif Disp SemBd:style=SemiBold Italic,Italic
- NotoSerifDisplay-ExtraLightItalic.ttf: Noto Serif Display,Noto Serif Disp ExtLt:style=ExtraLight Italic,Italic
- NotoSerifKhmer-CondensedExtraLight.ttf: Noto Serif Khmer,Noto Serif Khmer Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansAvestan-Regular.ttf: Noto Sans Avestan:style=Regular
- NotoSansCJKjp-Black.otf: Noto Sans CJK JP,Noto Sans CJK JP Black:style=Black,Regular
- NotoSansDevanagari-ExtraCondensed.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn:style=ExtraCondensed,Regular
- NotoSansMyanmarUI-Condensed.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn:style=Condensed,Regular
- NotoSerifGeorgian-SemiCondensedExtraLight.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn XLt:style=SemiCondensed ExtraLight,Regular
- NotoSerif-Condensed.ttf: Noto Serif,Noto Serif Cond:style=Condensed,Regular
- NotoSansMalayalam-Bold.ttf: Noto Sans Malayalam:style=Bold
- NotoSansArabic-CondensedBold.ttf: Noto Sans Arabic,Noto Sans Arabic Cond:style=Condensed Bold,Bold
- NotoSerifThai-CondensedBold.ttf: Noto Serif Thai,Noto Serif Thai Cond:style=Condensed Bold,Bold
- NimbusMonoPS-BoldItalic.t1: Nimbus Mono PS:style=Bold Italic
- NotoSansTamil-ExtraLight.ttf: Noto Sans Tamil,Noto Sans Tamil ExtLt:style=ExtraLight,Regular
- NotoSerifLao-ExtraCondensedSemiBold.ttf: Noto Serif Lao,Noto Serif Lao ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansKhmer-CondensedMedium.ttf: Noto Sans Khmer,Noto Sans Khmer Cond Med:style=Condensed Medium,Regular
- NotoSansThaiUI-CondensedBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond:style=Condensed Bold,Bold
- NotoSansThai-ExtraCondensed.ttf: Noto Sans Thai,Noto Sans Thai ExtCond:style=ExtraCondensed,Regular
- NotoSansThaiUI-ExtraCondensedThin.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifArmenian-SemiBold.ttf: Noto Serif Armenian,Noto Serif Armenian SmBd:style=SemiBold,Regular
- NotoSansArabic-ExtraCondensedExtraLight.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansThai-ExtraBold.ttf: Noto Sans Thai,Noto Sans Thai ExtBd:style=ExtraBold,Regular
- NotoMono-Regular.ttf: Noto Mono:style=Regular
- NotoSansDisplay-Medium.ttf: Noto Sans Display,Noto Sans Disp Med:style=Medium,Regular
- NotoSerifLao-Medium.ttf: Noto Serif Lao,Noto Serif Lao Med:style=Medium,Regular
- NotoSansKhmer-SemiCondensedBlack.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansDisplay-BoldItalic.ttf: Noto Sans Display,Noto Sans Disp:style=Bold Italic
- NotoSansDisplay-SemiCondensedBlack.ttf: Noto Sans Display,Noto Sans Disp SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifLao-Regular.ttf: Noto Serif Lao:style=Regular
- NotoSansDisplay-ExtraCondensedThinItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond Thin:style=ExtraCondensed Thin Italic,Italic
- NotoSansMyanmarUI-CondensedSemiBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn SmBd:style=Condensed SemiBold,Regular
- NotoSerifHebrew-Light.ttf: Noto Serif Hebrew,Noto Serif Hebrew Light:style=Light,Regular
- NotoSerif-CondensedMediumItalic.ttf: Noto Serif,Noto Serif Cond Med:style=Condensed Medium Italic,Italic
- NotoSansDevanagari-Regular.ttf: Noto Sans Devanagari:style=Regular
- NotoSerifTamil-ExtraCondensedThin.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifThai-ExtraCondensedMedium.ttf: Noto Serif Thai,Noto Serif Thai ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSans-ExtraCondensedSemiBoldItalic.ttf: Noto Sans,Noto Sans ExtCond SemBd:style=ExtraCondensed SemiBold Italic,Italic
- NotoSansGurmukhi-Regular.ttf: Noto Sans Gurmukhi:style=Regular
- NotoSansMonoCJKkr-Regular.otf: Noto Sans Mono CJK KR,Noto Sans Mono CJK KR Regular:style=Regular
- NotoSerifTamil-ExtraLight.ttf: Noto Serif Tamil,Noto Serif Tamil ExtLt:style=ExtraLight,Regular
- NotoSansCJKtc-Black.otf: Noto Sans CJK TC,Noto Sans CJK TC Black:style=Black,Regular
- NotoSansDisplay-ExtraCondensedItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond:style=ExtraCondensed Italic,Italic
- NotoSansArabic-ExtraCondensedLight.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond Light:style=ExtraCondensed Light,Regular
- StandardSymbolsPS.t1: Standard Symbols PS:style=Regular
- NotoSerifArmenian-SemiCondensedThin.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn Th:style=SemiCondensed Thin,Regular
- NotoSerifDisplay-CondensedBlackItalic.ttf: Noto Serif Display,Noto Serif Disp Cond Blk:style=Condensed Black Italic,Italic
- NotoSansArmenian-Condensed.ttf: Noto Sans Armenian,Noto Sans Armenian Cond:style=Condensed,Regular
- NotoSansHebrew-CondensedSemiBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond SemBd:style=Condensed SemiBold,Regular
- NotoSerifGeorgian-ExtraCondensedBlack.ttf: Noto Serif Georgian,Noto Serif Georgian XCn Bk:style=ExtraCondensed Black,Regular
- NotoSansMyanmarUI-ExtraCondensedExtraLight.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn XLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansSinhalaUI-CondensedBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond:style=Condensed Bold,Bold
- NotoSansThai-Bold.ttf: Noto Sans Thai:style=Bold
- NotoSans-Bold.ttf: Noto Sans:style=Bold
- URWGothic-Demi.otf: URW Gothic:style=Demi
- NotoSansEthiopic-CondensedSemiBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansGujaratiUI-Regular.ttf: Noto Sans Gujarati UI:style=Regular
- NotoSansKhmer-ExtraCondensedSemiBold.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- a010033l.pfb: URW Gothic L:style=Book Oblique
- NotoSansDisplay-CondensedBoldItalic.ttf: Noto Sans Display,Noto Sans Disp Cond:style=Condensed Bold Italic,Bold Italic
- NotoSansDisplay-CondensedSemiBoldItalic.ttf: Noto Sans Display,Noto Sans Disp Cond SemBd:style=Condensed SemiBold Italic,Italic
- NotoSansMono-ExtraCondensedExtraLight.ttf: Noto Sans Mono,Noto Sans Mono ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifArmenian-ExtraCondensedBold.ttf: Noto Serif Armenian,Noto Serif Armenian XCn:style=ExtraCondensed Bold,Bold
- NotoSerifDisplay-SemiCondensedItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond:style=SemiCondensed Italic,Italic
- NotoSansCuneiform-Regular.ttf: Noto Sans Cuneiform:style=Regular
- NotoSansMyanmarUI-ExtraBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XBd:style=ExtraBold,Regular
- NotoSansDisplay-SemiCondensedExtraBold.ttf: Noto Sans Display,Noto Sans Disp SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSerif-CondensedBoldItalic.ttf: Noto Serif,Noto Serif Cond:style=Condensed Bold Italic,Bold Italic
- NotoSerifTamil-SemiCondensedSemiBold.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSerif-SemiCondensedBlackItalic.ttf: Noto Serif,Noto Serif SemCond Blk:style=SemiCondensed Black Italic,Italic
- NotoSansSinhala-CondensedBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond:style=Condensed Bold,Bold
- NotoSansKhmerUI-Regular.ttf: Noto Sans Khmer UI:style=Regular
- NotoSansTamilUI-SemiCondensedLight.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond Light:style=SemiCondensed Light,Regular
- NotoSansMyanmar-CondensedBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond:style=Condensed Bold,Bold
- NotoSansTamil-Light.ttf: Noto Sans Tamil,Noto Sans Tamil Light:style=Light,Regular
- NotoSerifEthiopic-CondensedBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn:style=Condensed Bold,Bold
- NotoSansHebrew-ExtraCondensedExtraBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansKhmerUI-Bold.ttf: Noto Sans Khmer UI:style=Bold
- NotoSerifArmenian-Light.ttf: Noto Serif Armenian,Noto Serif Armenian Lt:style=Light,Regular
- NotoSerifGeorgian-Bold.ttf: Noto Serif Georgian:style=Bold
- NotoSansTamilUI-Medium.ttf: Noto Sans Tamil UI,Noto Sans Tamil Med:style=Medium,Regular
- NotoSerifTamil-SemiBold.ttf: Noto Serif Tamil,Noto Serif Tamil SemBd:style=SemiBold,Regular
- NotoSansSinhala-ExtraCondensedThin.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansMyanmarUI-SemiCondensedMedium.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn Md:style=SemiCondensed Medium,Regular
- NotoSansThaiUI-CondensedBlack.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond Blk:style=Condensed Black,Regular
- NotoSerifDisplay-ExtraCondensedExtraBoldItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond ExtBd:style=ExtraCondensed ExtraBold Italic,Italic
- NotoSansMono-SemiCondensedExtraBold.ttf: Noto Sans Mono,Noto Sans Mono SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansThaiUI-SemiCondensedThin.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSans-SemiCondensedLight.ttf: Noto Sans,Noto Sans SemCond Light:style=SemiCondensed Light,Regular
- NotoSansMono-Regular.ttf: Noto Sans Mono:style=Regular
- NotoSerif-CondensedSemiBold.ttf: Noto Serif,Noto Serif Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansKhmer-ExtraCondensedBold.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansMyanmar-Black.ttf: Noto Sans Myanmar,Noto Sans Myanmar Blk:style=Black,Regular
- NotoSansTamilUI-SemiCondensedBlack.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifArmenian-SemiCondensedMedium.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn Md:style=SemiCondensed Medium,Regular
- NotoSans-Light.ttf: Noto Sans,Noto Sans Light:style=Light,Regular
- n021003l.pfb: Nimbus Roman No9 L:style=Regular
- NotoSansMono-SemiCondensed.ttf: Noto Sans Mono,Noto Sans Mono SemCond:style=SemiCondensed,Regular
- NotoSansThaiUI-SemiCondensedSemiBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSerifDisplay-CondensedSemiBold.ttf: Noto Serif Display,Noto Serif Disp Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansMyanmarUI-Black.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Bk:style=Black,Regular
- NotoSerifThai-SemiCondensedBold.ttf: Noto Serif Thai,Noto Serif Thai SemCond:style=SemiCondensed Bold,Bold
- NotoSerif-SemiCondensedSemiBoldItalic.ttf: Noto Serif,Noto Serif SemCond SemBd:style=SemiCondensed SemiBold Italic,Italic
- s050000l.pfb: Standard Symbols L:style=Regular
- NotoSansArmenian-CondensedExtraLight.ttf: Noto Sans Armenian,Noto Sans Armenian Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSerifLao-SemiCondensed.ttf: Noto Serif Lao,Noto Serif Lao SemCond:style=SemiCondensed,Regular
- NotoSansTamil-SemiCondensedThin.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansMyanmarUI-Bold.ttf: Noto Sans Myanmar UI:style=Bold
- NotoSerifArmenian-CondensedExtraBold.ttf: Noto Serif Armenian,Noto Serif Armenian Cn XBd:style=Condensed ExtraBold,Regular
- NotoSansEthiopic-CondensedExtraBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansHebrew-ExtraCondensedSemiBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansMyanmar-Regular.ttf: Noto Sans Myanmar:style=Regular
- NotoSansArabicUI-SemiCondensedBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn:style=SemiCondensed Bold,Bold
- NotoSansBengaliUI-Bold.ttf: Noto Sans Bengali UI:style=Bold
- NotoSans-ExtraLight.ttf: Noto Sans,Noto Sans ExtLt:style=ExtraLight,Regular
- NotoSerifEthiopic-ExtraCondensedExtraBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn XBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansMonoCJKsc-Regular.otf: Noto Sans Mono CJK SC,Noto Sans Mono CJK SC Regular:style=Regular
- NotoSansDevanagariUI-CondensedMedium.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn Md:style=Condensed Medium,Regular
- NotoSerifCJKjp-Medium.otf: Noto Serif CJK JP,Noto Serif CJK JP Medium:style=Medium,Regular
- NotoSerifBengali-Regular.ttf: Noto Serif Bengali:style=Regular
- NotoSerifDisplay-CondensedSemiBoldItalic.ttf: Noto Serif Display,Noto Serif Disp Cond SemBd:style=Condensed SemiBold Italic,Italic
- NotoSansTaiTham-Regular.ttf: Noto Sans Tai Tham:style=Regular
- NotoSansKhmer-ExtraLight.ttf: Noto Sans Khmer,Noto Sans Khmer ExtLt:style=ExtraLight,Regular
- NotoSansBengali-Bold.ttf: Noto Sans Bengali:style=Bold
- NotoSansKannadaUI-Bold.ttf: Noto Sans Kannada UI:style=Bold
- NotoSerifThai-SemiCondensedLight.ttf: Noto Serif Thai,Noto Serif Thai SemCond Light:style=SemiCondensed Light,Regular
- NotoSansTamilUI-ExtraCondensedBlack.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansArabicUI-ExtraCondensedExtraBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn XBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansThaiUI-Regular.ttf: Noto Sans Thai UI:style=Regular
- NotoSans-SemiCondensedLightItalic.ttf: Noto Sans,Noto Sans SemCond Light:style=SemiCondensed Light Italic,Italic
- NotoSansLaoUI-Bold.ttf: Noto Sans Lao UI:style=Bold
- NotoSerif-ExtraBoldItalic.ttf: Noto Serif,Noto Serif ExtBd:style=ExtraBold Italic,Italic
- NotoSerifDisplay-SemiCondensed.ttf: Noto Serif Display,Noto Serif Disp SemCond:style=SemiCondensed,Regular
- NotoSansKhmerUI-SemiCondensedBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond:style=SemiCondensed Bold,Bold
- NotoSansSinhalaUI-SemiCondensedExtraLight.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSans-CondensedLightItalic.ttf: Noto Sans,Noto Sans Cond Light:style=Condensed Light Italic,Italic
- NimbusSansNarrow-Bold.otf: Nimbus Sans Narrow:style=Bold
- URWBookman-DemiItalic.otf: URW Bookman:style=Demi Italic
- NotoSansDisplay-SemiCondensedExtraLightItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond ExtLt:style=SemiCondensed ExtraLight Italic,Italic
- NotoSerif-Italic.ttf: Noto Serif:style=Italic
- NotoSansArabic-ExtraBold.ttf: Noto Sans Arabic,Noto Sans Arabic ExtBd:style=ExtraBold,Regular
- NotoSerifMyanmar-SemiCondensedLight.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemCond Light:style=SemiCondensed Light,Regular
- NotoSansMyanmarUI-CondensedBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn:style=Condensed Bold,Bold
- NotoSansCJKjp-Bold.otf: Noto Sans CJK JP,Noto Sans CJK JP Bold:style=Bold,Regular
- URWGothic-BookOblique.otf: URW Gothic:style=Book Oblique
- NotoSerifDisplay-ExtraBoldItalic.ttf: Noto Serif Display,Noto Serif Disp ExtBd:style=ExtraBold Italic,Italic
- NotoSerifTamil-SemiCondensed.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond:style=SemiCondensed,Regular
- b018035l.pfb: URW Bookman L:style=Demi Bold Italic
- NotoSansCherokee-Bold.ttf: Noto Sans Cherokee:style=Bold
- NotoSansThaiUI-Light.ttf: Noto Sans Thai UI,Noto Sans Thai UI Light:style=Light,Regular
- NotoSansKhmer-CondensedThin.ttf: Noto Sans Khmer,Noto Sans Khmer Cond Thin:style=Condensed Thin,Regular
- NotoSerifGeorgian-SemiCondensedExtraBold.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn XBd:style=SemiCondensed ExtraBold,Regular
- NotoNaskhArabic-Bold.ttf: Noto Naskh Arabic:style=Bold
- NotoSerifThai-CondensedExtraBold.ttf: Noto Serif Thai,Noto Serif Thai Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansThai-CondensedBold.ttf: Noto Sans Thai,Noto Sans Thai Cond:style=Condensed Bold,Bold
- NotoSerifArmenian-ExtraCondensedThin.ttf: Noto Serif Armenian,Noto Serif Armenian XCn Th:style=ExtraCondensed Thin,Regular
- NotoSansMyanmar-ExtraLight.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtLt:style=ExtraLight,Regular
- NotoSansDevanagari-ExtraCondensedExtraLight.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn XLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansHebrew-Black.ttf: Noto Sans Hebrew,Noto Sans Hebrew Blk:style=Black,Regular
- NotoSansDevanagariUI-SemiCondensedBlack.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn Bk:style=SemiCondensed Black,Regular
- NotoSerifCJKjp-Light.otf: Noto Serif CJK JP,Noto Serif CJK JP Light:style=Light,Regular
- NotoSerifTamil-SemiCondensedExtraBold.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- c059033l.pfb: Century Schoolbook L:style=Italic
- NotoSans-ExtraCondensedItalic.ttf: Noto Sans,Noto Sans ExtCond:style=ExtraCondensed Italic,Italic
- NotoSerifLao-CondensedLight.ttf: Noto Serif Lao,Noto Serif Lao Cond Light:style=Condensed Light,Regular
- NotoSansGeorgian-CondensedLight.ttf: Noto Sans Georgian,Noto Sans Georgian Cond Light:style=Condensed Light,Regular
- NotoSerifGeorgian-Medium.ttf: Noto Serif Georgian,Noto Serif Georgian Md:style=Medium,Regular
- NotoSansLaoUI-SemiCondensedSemiBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSerifCJKkr-Medium.otf: Noto Serif CJK KR,Noto Serif CJK KR Medium:style=Medium,Regular
- NotoSansVai-Regular.ttf: Noto Sans Vai:style=Regular
- NotoSansBengaliUI-Light.ttf: Noto Sans Bengali UI,Noto Sans Bengali Light:style=Light,Regular
- NotoSansOriyaUI-Regular.ttf: Noto Sans Oriya UI:style=Regular
- NotoSansArmenian-Light.ttf: Noto Sans Armenian,Noto Sans Armenian Light:style=Light,Regular
- NotoSansArmenian-SemiBold.ttf: Noto Sans Armenian,Noto Sans Armenian SemBd:style=SemiBold,Regular
- NotoSansMonoCJKjp-Regular.otf: Noto Sans Mono CJK JP,Noto Sans Mono CJK JP Regular:style=Regular
- NotoSansTamilUI-CondensedThin.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond Thin:style=Condensed Thin,Regular
- NotoSansArabic-SemiCondensedMedium.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond Med:style=SemiCondensed Medium,Regular
- NotoSans-ExtraLightItalic.ttf: Noto Sans,Noto Sans ExtLt:style=ExtraLight Italic,Italic
- NotoSansCherokee-Regular.ttf: Noto Sans Cherokee:style=Regular
- NotoSansThaiUI-SemiCondensedLight.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond Light:style=SemiCondensed Light,Regular
- NotoSansInscriptionalParthian-Regular.ttf: Noto Sans Inscriptional Parthian,Noto Sans InsParthi:style=Regular
- NotoSans-CondensedThinItalic.ttf: Noto Sans,Noto Sans Cond Thin:style=Condensed Thin Italic,Italic
- NotoSansBuginese-Regular.ttf: Noto Sans Buginese:style=Regular
- NotoSerifLao-SemiCondensedExtraBold.ttf: Noto Serif Lao,Noto Serif Lao SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansDevanagariUI-SemiCondensedExtraBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn XBd:style=SemiCondensed ExtraBold,Regular
- NotoSansDisplay-Regular.ttf: Noto Sans Display,Noto Sans Disp:style=Regular
- NotoSansMono-SemiBold.ttf: Noto Sans Mono,Noto Sans Mono SemBd:style=SemiBold,Regular
- NotoNaskhArabicUI-Bold.ttf: Noto Naskh Arabic UI:style=Bold
- NotoSansKhmer-ExtraCondensedBlack.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansCJKjp-Regular.otf: Noto Sans CJK JP,Noto Sans CJK JP Regular:style=Regular
- NotoSansRejang-Regular.ttf: Noto Sans Rejang:style=Regular
- NotoSansCJKtc-DemiLight.otf: Noto Sans CJK TC,Noto Sans CJK TC DemiLight:style=DemiLight,Regular
- NotoSansTamil-ExtraCondensedBold.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifThai-ExtraLight.ttf: Noto Serif Thai,Noto Serif Thai ExtLt:style=ExtraLight,Regular
- NotoSansKhmerUI-Medium.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Med:style=Medium,Regular
- NotoSansKhmer-SemiCondensedThin.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansBengaliUI-SemiBold.ttf: Noto Sans Bengali UI,Noto Sans Bengali SemBd:style=SemiBold,Regular
- NotoSerifDisplay-ExtraCondensedThin.ttf: Noto Serif Display,Noto Serif Disp ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifBengali-Bold.ttf: Noto Serif Bengali:style=Bold
- NotoSansHebrew-ExtraCondensedMedium.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansDisplay-LightItalic.ttf: Noto Sans Display,Noto Sans Disp Light:style=Light Italic,Italic
- NotoSerifCJKkr-Regular.otf: Noto Serif CJK KR:style=Regular
- NotoSerifLao-ExtraCondensedExtraLight.ttf: Noto Serif Lao,Noto Serif Lao ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansArabic-Black.ttf: Noto Sans Arabic,Noto Sans Arabic Blk:style=Black,Regular
- NotoSansLaoUI-Black.ttf: Noto Sans Lao UI,Noto Sans Lao UI Blk:style=Black,Regular
- NotoSansSinhalaUI-SemiCondensedBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond:style=SemiCondensed Bold,Bold
- NotoSansHebrew-SemiCondensedExtraBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSerifSinhala-Light.ttf: Noto Serif Sinhala,Noto Serif Sinhala Light:style=Light,Regular
- Z003-MediumItalic.t1: Z003:style=Medium Italic
- NotoSerif-CondensedLight.ttf: Noto Serif,Noto Serif Cond Light:style=Condensed Light,Regular
- NotoSerifMyanmar-Black.ttf: Noto Serif Myanmar,Noto Serif Myanmar Blk:style=Black,Regular
- NotoSansArabic-ExtraCondensedSemiBold.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansThai-SemiCondensedExtraLight.ttf: Noto Sans Thai,Noto Sans Thai SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifHebrew-SemiBold.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemBd:style=SemiBold,Regular
- NotoSansKannada-Regular.ttf: Noto Sans Kannada:style=Regular
- NotoSansThaiUI-ExtraBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtBd:style=ExtraBold,Regular
- NotoSerifKhmer-CondensedMedium.ttf: Noto Serif Khmer,Noto Serif Khmer Cond Med:style=Condensed Medium,Regular
- NotoSansEthiopic-Thin.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Thin:style=Thin,Regular
- NotoSansLaoUI-ExtraCondensedLight.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond Light:style=ExtraCondensed Light,Regular
- P052-BoldItalic.t1: P052:style=Bold Italic
- NotoSerifDisplay-Bold.ttf: Noto Serif Display,Noto Serif Disp:style=Bold
- NotoSerifMyanmar-CondensedBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond:style=Condensed Bold,Bold
- NotoSansThaiUI-ExtraCondensedBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifThai-Regular.ttf: Noto Serif Thai:style=Regular
- C059-Italic.t1: C059:style=Italic
- NotoEmoji-Regular.ttf: Noto Emoji:style=Regular
- NotoSans-SemiCondensedBlack.ttf: Noto Sans,Noto Sans SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansMyanmar-ExtraBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtBd:style=ExtraBold,Regular
- NotoSansThai-ExtraCondensedThin.ttf: Noto Sans Thai,Noto Sans Thai ExtCond Thin:style=ExtraCondensed Thin,Regular
- a010035l.pfb: URW Gothic L:style=Demi Oblique
- NotoSerif-CondensedExtraLight.ttf: Noto Serif,Noto Serif Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansLaoUI-ExtraCondensedBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansSinhala-Thin.ttf: Noto Sans Sinhala,Noto Sans Sinhala Thin:style=Thin,Regular
- NotoSerif-Bold.ttf: Noto Serif:style=Bold
- NotoSans-BlackItalic.ttf: Noto Sans,Noto Sans Blk:style=Black Italic,Italic
- NotoSerifKhmer-ExtraCondensedThin.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansThaiUI-ExtraLight.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtLt:style=ExtraLight,Regular
- NotoSerif-SemiCondensedMedium.ttf: Noto Serif,Noto Serif SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansMono-CondensedLight.ttf: Noto Sans Mono,Noto Sans Mono Cond Light:style=Condensed Light,Regular
- NotoSansMono-Bold.ttf: Noto Sans Mono:style=Bold
- NotoSansSinhalaUI-CondensedMedium.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond Med:style=Condensed Medium,Regular
- NotoSerif-CondensedMedium.ttf: Noto Serif,Noto Serif Cond Med:style=Condensed Medium,Regular
- NotoSansDevanagariUI-ExtraCondensedExtraLight.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn XLt:style=ExtraCondensed ExtraLight,Regular
- P052-Roman.t1: P052:style=Roman
- NotoSansKhmerUI-SemiCondensedExtraLight.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifHebrew-Medium.ttf: Noto Serif Hebrew,Noto Serif Hebrew Med:style=Medium,Regular
- NotoSerifEthiopic-SemiCondensedLight.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn Lt:style=SemiCondensed Light,Regular
- NotoSansGeorgian-SemiCondensedExtraLight.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifArmenian-ExtraBold.ttf: Noto Serif Armenian,Noto Serif Armenian XBd:style=ExtraBold,Regular
- NotoSansArabicUI-CondensedMedium.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn Md:style=Condensed Medium,Regular
- NotoSerifEthiopic-ExtraCondensedMedium.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn Md:style=ExtraCondensed Medium,Regular
- NotoSerifHebrew-CondensedThin.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond Thin:style=Condensed Thin,Regular
- NotoSerifTamil-CondensedExtraBold.ttf: Noto Serif Tamil,Noto Serif Tamil Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansArabic-SemiCondensedExtraBold.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSerif-ExtraCondensedBlackItalic.ttf: Noto Serif,Noto Serif ExtCond Blk:style=ExtraCondensed Black Italic,Italic
- NotoSerifDisplay-ExtraCondensedBold.ttf: Noto Serif Display,Noto Serif Disp ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifArmenian-SemiCondensedBlack.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn Bk:style=SemiCondensed Black,Regular
- NotoSerifCJKjp-SemiBold.otf: Noto Serif CJK JP,Noto Serif CJK JP SemiBold:style=SemiBold,Regular
- NotoSerifThai-CondensedThin.ttf: Noto Serif Thai,Noto Serif Thai Cond Thin:style=Condensed Thin,Regular
- NotoSansKhmerUI-CondensedExtraLight.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansBengaliUI-ExtraLight.ttf: Noto Sans Bengali UI,Noto Sans Bengali ExtLt:style=ExtraLight,Regular
- NotoSansDisplay-ExtraCondensedLightItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond Light:style=ExtraCondensed Light Italic,Italic
- NotoSansMyanmar-SemiCondensedBold.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond:style=SemiCondensed Bold,Bold
- NotoSerifThai-SemiBold.ttf: Noto Serif Thai,Noto Serif Thai SemBd:style=SemiBold,Regular
- NotoSerifEthiopic-Condensed.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn:style=Condensed,Regular
- NotoSansDevanagariUI-CondensedBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn:style=Condensed Bold,Bold
- NotoSansGeorgian-SemiCondensedMedium.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond Med:style=SemiCondensed Medium,Regular
- NotoSerifCJKjp-Regular.otf: Noto Serif CJK JP:style=Regular
- NotoSansThai-CondensedMedium.ttf: Noto Sans Thai,Noto Sans Thai Cond Med:style=Condensed Medium,Regular
- NotoSansArmenian-SemiCondensedBlack.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansDevanagariUI-ExtraCondensedThin.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn Th:style=ExtraCondensed Thin,Regular
- NotoSansDisplay-ExtraCondensedBold.ttf: Noto Sans Display,Noto Sans Disp ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansGeorgian-ExtraCondensedBlack.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansArabic-SemiCondensedSemiBold.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansOldTurkic-Regular.ttf: Noto Sans Old Turkic:style=Regular
- NotoSansEthiopic-SemiCondensedExtraLight.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansMalayalam-Regular.ttf: Noto Sans Malayalam:style=Regular
- NotoSansHebrew-SemiCondensedMedium.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond Med:style=SemiCondensed Medium,Regular
- NotoSans-CondensedSemiBoldItalic.ttf: Noto Sans,Noto Sans Cond SemBd:style=Condensed SemiBold Italic,Italic
- NotoSerifMyanmar-Condensed.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond:style=Condensed,Regular
- NotoSansSinhala-Medium.ttf: Noto Sans Sinhala,Noto Sans Sinhala Med:style=Medium,Regular
- NimbusRoman-Bold.t1: Nimbus Roman:style=Bold
- NimbusSansNarrow-Oblique.t1: Nimbus Sans Narrow:style=Oblique
- NotoSans-ExtraCondensedExtraBold.ttf: Noto Sans,Noto Sans ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerifDisplay-SemiBold.ttf: Noto Serif Display,Noto Serif Disp SemBd:style=SemiBold,Regular
- NotoSerifHebrew-SemiCondensedMedium.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansMongolian-Regular.ttf: Noto Sans Mongolian:style=Regular
- NotoSansMyanmarUI-SemiCondensedBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn:style=SemiCondensed Bold,Bold
- NotoSansBengaliUI-Black.ttf: Noto Sans Bengali UI,Noto Sans Bengali Blk:style=Black,Regular
- NotoSerifHebrew-CondensedLight.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond Light:style=Condensed Light,Regular
- NotoSansMyanmar-SemiCondensedThin.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansDevanagariUI-SemiCondensed.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn:style=SemiCondensed,Regular
- NotoSansThai-CondensedLight.ttf: Noto Sans Thai,Noto Sans Thai Cond Light:style=Condensed Light,Regular
- NotoSansKhmerUI-ExtraCondensedExtraBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansCJKsc-DemiLight.otf: Noto Sans CJK SC,Noto Sans CJK SC DemiLight:style=DemiLight,Regular
- NotoSerifDisplay-SemiCondensedExtraLight.ttf: Noto Serif Display,Noto Serif Disp SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifTamil-ExtraCondensedExtraBold.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansSinhalaUI-Condensed.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond:style=Condensed,Regular
- NotoSansDisplay-BlackItalic.ttf: Noto Sans Display,Noto Sans Disp Blk:style=Black Italic,Italic
- NotoSansLao-Bold.ttf: Noto Sans Lao:style=Bold
- NotoSans-SemiCondensedExtraBoldItalic.ttf: Noto Sans,Noto Sans SemCond ExtBd:style=SemiCondensed ExtraBold Italic,Italic
- NotoSansCherokee-Light.ttf: Noto Sans Cherokee,Noto Sans Cherokee Light:style=Light,Regular
- NotoSerifGeorgian-CondensedMedium.ttf: Noto Serif Georgian,Noto Serif Georgian Cn Md:style=Condensed Medium,Regular
- NotoSansTamil-ExtraCondensedThin.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond Thin:style=ExtraCondensed Thin,Regular
- P052-BoldItalic.otf: P052:style=Bold Italic
- NotoSansSinhala-SemiCondensedSemiBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansHebrew-ExtraCondensed.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond:style=ExtraCondensed,Regular
- NotoSansLaoUI-CondensedBlack.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond Blk:style=Condensed Black,Regular
- NotoSansLaoUI-ExtraCondensedBlack.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansLydian-Regular.ttf: Noto Sans Lydian:style=Regular
- NotoSansKhmer-SemiCondensedSemiBold.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansArabicUI-Bold.ttf: Noto Sans Arabic UI:style=Bold
- NotoSansMono-ExtraCondensedLight.ttf: Noto Sans Mono,Noto Sans Mono ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifGeorgian-CondensedBold.ttf: Noto Serif Georgian,Noto Serif Georgian Cn:style=Condensed Bold,Bold
- NotoSerifGeorgian-ExtraLight.ttf: Noto Serif Georgian,Noto Serif Georgian XLt:style=ExtraLight,Regular
- NotoSansKhmer-Regular.ttf: Noto Sans Khmer:style=Regular
- NotoSansDisplay-SemiCondensedSemiBold.ttf: Noto Sans Display,Noto Sans Disp SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSerifArmenian-ExtraLight.ttf: Noto Serif Armenian,Noto Serif Armenian XLt:style=ExtraLight,Regular
- NotoSerifKannada-Regular.ttf: Noto Serif Kannada:style=Regular
- NotoSansCJKtc-Bold.otf: Noto Sans CJK TC,Noto Sans CJK TC Bold:style=Bold,Regular
- NotoSans-SemiCondensedThinItalic.ttf: Noto Sans,Noto Sans SemCond Thin:style=SemiCondensed Thin Italic,Italic
- NotoSansOldPersian-Regular.ttf: Noto Sans Old Persian:style=Regular
- NotoSansMono-SemiCondensedBold.ttf: Noto Sans Mono,Noto Sans Mono SemCond:style=SemiCondensed Bold,Bold
- NotoSans-ExtraCondensedLight.ttf: Noto Sans,Noto Sans ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansKhmerUI-Light.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Light:style=Light,Regular
- NotoSansSinhalaUI-ExtraCondensed.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond:style=ExtraCondensed,Regular
- NotoSerifCJKsc-Black.otf: Noto Serif CJK SC,Noto Serif CJK SC Black:style=Black,Regular
- NotoSerifEthiopic-SemiCondensedBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn:style=SemiCondensed Bold,Bold
- NotoSansCham-SemiBold.ttf: Noto Sans Cham,Noto Sans Cham SemBd:style=SemiBold,Regular
- NotoSansMono-Bold.ttf: Noto Sans Mono:style=Bold
- NotoSansDisplay-SemiCondensedSemiBoldItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond SemBd:style=SemiCondensed SemiBold Italic,Italic
- NotoSansTamilUI-CondensedExtraLight.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansSymbols-Regular.ttf: Noto Sans Symbols:style=Regular
- NotoSansTagbanwa-Regular.ttf: Noto Sans Tagbanwa:style=Regular
- NotoSansKhmerUI-ExtraCondensedMedium.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansArmenian-Regular.ttf: Noto Sans Armenian:style=Regular
- NotoSansCJKkr-Regular.otf: Noto Sans CJK KR,Noto Sans CJK KR Regular:style=Regular
- NotoSansMyanmar-CondensedMedium.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond Med:style=Condensed Medium,Regular
- NotoSansThaiUI-Black.ttf: Noto Sans Thai UI,Noto Sans Thai UI Blk:style=Black,Regular
- NotoSerifEthiopic-CondensedBlack.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn Bk:style=Condensed Black,Regular
- NotoSansEthiopic-SemiCondensedSemiBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansKhmerUI-Condensed.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond:style=Condensed,Regular
- NotoSansThaiUI-CondensedSemiBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansMyanmarUI-ExtraCondensedBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn:style=ExtraCondensed Bold,Bold
- NotoSerifEthiopic-ExtraBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XBd:style=ExtraBold,Regular
- NotoSerif-SemiCondensedMediumItalic.ttf: Noto Serif,Noto Serif SemCond Med:style=SemiCondensed Medium Italic,Italic
- NotoSansCJKkr-Bold.otf: Noto Sans CJK KR,Noto Sans CJK KR Bold:style=Bold,Regular
- NotoSerifGeorgian-ExtraCondensedExtraBold.ttf: Noto Serif Georgian,Noto Serif Georgian XCn XBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansGeorgian-Regular.ttf: Noto Sans Georgian:style=Regular
- NotoSerifCJKjp-Bold.otf: Noto Serif CJK JP:style=Bold
- NotoSansSymbols-SemiBold.ttf: Noto Sans Symbols,Noto Sans Symbols SemBd:style=SemiBold,Regular
- NotoSerifLao-Light.ttf: Noto Serif Lao,Noto Serif Lao Light:style=Light,Regular
- NotoSerifCJKjp-Black.otf: Noto Serif CJK JP,Noto Serif CJK JP Black:style=Black,Regular
- NotoSansAdlam-Regular.ttf: Noto Sans Adlam:style=Regular
- NotoSansDevanagari-ExtraLight.ttf: Noto Sans Devanagari,Noto Sans Devanagari XLt:style=ExtraLight,Regular
- NotoSerifDisplay-CondensedBlack.ttf: Noto Serif Display,Noto Serif Disp Cond Blk:style=Condensed Black,Regular
- NotoSansTamilUI-CondensedBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil Cond:style=Condensed Bold,Bold
- NotoSansArmenian-ExtraCondensedThin.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifDisplay-CondensedExtraLightItalic.ttf: Noto Serif Display,Noto Serif Disp Cond ExtLt:style=Condensed ExtraLight Italic,Italic
- NotoSansEthiopic-ExtraCondensedBlack.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansCJKsc-Black.otf: Noto Sans CJK SC,Noto Sans CJK SC Black:style=Black,Regular
- NotoSansThaiUI-CondensedExtraLight.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansMono-ExtraCondensedSemiBold.ttf: Noto Sans Mono,Noto Sans Mono ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifEthiopic-Thin.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Th:style=Thin,Regular
- NotoSerifEthiopic-ExtraCondensedSemiBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn SmBd:style=ExtraCondensed SemiBold,Regular
- NotoSansKhmer-CondensedBold.ttf: Noto Sans Khmer,Noto Sans Khmer Cond:style=Condensed Bold,Bold
- NotoSansDisplay-SemiCondensedBlackItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond Blk:style=SemiCondensed Black Italic,Italic
- NotoSansKaithi-Regular.ttf: Noto Sans Kaithi:style=Regular
- NotoSansYi-Regular.ttf: Noto Sans Yi:style=Regular
- NotoSansArmenian-SemiCondensedExtraBold.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSerifKhmer-SemiCondensedExtraLight.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoNaskhArabic-Regular.ttf: Noto Naskh Arabic:style=Regular
- NotoSansArabic-Bold.ttf: Noto Sans Arabic:style=Bold
- NotoSansThai-ExtraCondensedExtraLight.ttf: Noto Sans Thai,Noto Sans Thai ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansDisplay-CondensedMediumItalic.ttf: Noto Sans Display,Noto Sans Disp Cond Med:style=Condensed Medium Italic,Italic
- NotoSansDisplay-SemiCondensedLight.ttf: Noto Sans Display,Noto Sans Disp SemCond Light:style=SemiCondensed Light,Regular
- NotoSansSinhalaUI-CondensedSemiBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansSinhala-ExtraBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtBd:style=ExtraBold,Regular
- NotoSansMono-Condensed.ttf: Noto Sans Mono,Noto Sans Mono Cond:style=Condensed,Regular
- NotoSerifEthiopic-SemiCondensedThin.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn Th:style=SemiCondensed Thin,Regular
- NotoSansThai-CondensedExtraBold.ttf: Noto Sans Thai,Noto Sans Thai Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSerif-CondensedExtraLightItalic.ttf: Noto Serif,Noto Serif Cond ExtLt:style=Condensed ExtraLight Italic,Italic
- NotoSerifDisplay-SemiCondensedLight.ttf: Noto Serif Display,Noto Serif Disp SemCond Light:style=SemiCondensed Light,Regular
- NotoSansArmenian-CondensedBold.ttf: Noto Sans Armenian,Noto Sans Armenian Cond:style=Condensed Bold,Bold
- NotoSansThaiUI-CondensedMedium.ttf: Noto Sans Thai UI,Noto Sans Thai UI Cond Med:style=Condensed Medium,Regular
- NotoSansThai-ExtraCondensedSemiBold.ttf: Noto Sans Thai,Noto Sans Thai ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifCJKsc-Light.otf: Noto Serif CJK SC,Noto Serif CJK SC Light:style=Light,Regular
- D050000L.t1: D050000L:style=Regular
- NotoSansChakma-Regular.ttf: Noto Sans Chakma:style=Regular
- NotoSerifDisplay-SemiCondensedThinItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond Thin:style=SemiCondensed Thin Italic,Italic
- StandardSymbolsPS.otf: Standard Symbols PS:style=Regular
- NotoSansLao-SemiCondensedLight.ttf: Noto Sans Lao,Noto Sans Lao SemCond Light:style=SemiCondensed Light,Regular
- NotoSansSinhalaUI-SemiCondensedSemiBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSerifThai-SemiCondensedThin.ttf: Noto Serif Thai,Noto Serif Thai SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansThaiUI-ExtraCondensedMedium.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSerifMyanmar-ExtraCondensedBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifDisplay-CondensedExtraBold.ttf: Noto Serif Display,Noto Serif Disp Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansSinhala-SemiCondensedBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond:style=SemiCondensed Bold,Bold
- NotoSerifArmenian-SemiCondensedExtraLight.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn XLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifLao-ExtraCondensedExtraBold.ttf: Noto Serif Lao,Noto Serif Lao ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansThaiUI-SemiCondensedExtraBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSerifCJKtc-ExtraLight.otf: Noto Serif CJK TC,Noto Serif CJK TC ExtraLight:style=ExtraLight,Regular
- NotoSansMono-Medium.ttf: Noto Sans Mono,Noto Sans Mono Med:style=Medium,Regular
- NotoSansDisplay-CondensedExtraLightItalic.ttf: Noto Sans Display,Noto Sans Disp Cond ExtLt:style=Condensed ExtraLight Italic,Italic
- NotoSerifSinhala-ExtraBold.ttf: Noto Serif Sinhala,Noto Serif Sinhala ExtBd:style=ExtraBold,Regular
- NotoSerif-ExtraCondensedSemiBoldItalic.ttf: Noto Serif,Noto Serif ExtCond SemBd:style=ExtraCondensed SemiBold Italic,Italic
- NotoSansArabicUI-SemiCondensedBlack.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI SmCn Bk:style=SemiCondensed Black,Regular
- NotoSerifLao-Thin.ttf: Noto Serif Lao,Noto Serif Lao Thin:style=Thin,Regular
- NotoSansSinhala-ExtraCondensedBlack.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSerifLao-ExtraCondensedThin.ttf: Noto Serif Lao,Noto Serif Lao ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerif-CondensedBlack.ttf: Noto Serif,Noto Serif Cond Blk:style=Condensed Black,Regular
- NotoSansEthiopic-ExtraCondensedThin.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansMono-CondensedBlack.ttf: Noto Sans Mono,Noto Sans Mono Cond Blk:style=Condensed Black,Regular
- NotoSansGlagolitic-Regular.ttf: Noto Sans Glagolitic:style=Regular
- NotoSansThai-SemiCondensedBlack.ttf: Noto Sans Thai,Noto Sans Thai SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifLao-ExtraCondensedMedium.ttf: Noto Serif Lao,Noto Serif Lao ExtCond Med:style=ExtraCondensed Medium,Regular
- n019023l.pfb: Nimbus Sans L:style=Regular Italic
- NotoSansArabic-ExtraCondensedExtraBold.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansSinhalaUI-ExtraLight.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtLt:style=ExtraLight,Regular
- NotoSansHebrew-ExtraCondensedExtraLight.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifThai-Medium.ttf: Noto Serif Thai,Noto Serif Thai Med:style=Medium,Regular
- NotoSansLao-CondensedLight.ttf: Noto Sans Lao,Noto Sans Lao Cond Light:style=Condensed Light,Regular
- NotoSansHebrew-SemiCondensedExtraLight.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansMyanmar-SemiCondensed.ttf: Noto Sans Myanmar,Noto Sans Myanmar SemCond:style=SemiCondensed,Regular
- b018012l.pfb: URW Bookman L:style=Light
- NotoSansMandaic-Regular.ttf: Noto Sans Mandaic:style=Regular
- NotoSansDevanagariUI-ExtraCondensedBlack.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XCn Bk:style=ExtraCondensed Black,Regular
- NotoSansMonoCJKsc-Bold.otf: Noto Sans Mono CJK SC,Noto Sans Mono CJK SC Bold:style=Bold,Regular
- NotoSerif-CondensedExtraBoldItalic.ttf: Noto Serif,Noto Serif Cond ExtBd:style=Condensed ExtraBold Italic,Italic
- NotoSansArabic-ExtraCondensedMedium.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSerifCJKsc-Regular.otf: Noto Serif CJK SC:style=Regular
- NotoSansDevanagari-ExtraCondensedBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn:style=ExtraCondensed Bold,Bold
- NotoSansThai-Condensed.ttf: Noto Sans Thai,Noto Sans Thai Cond:style=Condensed,Regular
- NotoSansKhmer-SemiCondensedBold.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond:style=SemiCondensed Bold,Bold
- NotoSerifThai-Thin.ttf: Noto Serif Thai,Noto Serif Thai Thin:style=Thin,Regular
- NotoSansKhmer-SemiBold.ttf: Noto Sans Khmer,Noto Sans Khmer SemBd:style=SemiBold,Regular
- NotoMono-Regular.ttf: Noto Mono:style=Regular
- NotoSansSinhala-CondensedLight.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond Light:style=Condensed Light,Regular
- NotoSerifArmenian-ExtraCondensedMedium.ttf: Noto Serif Armenian,Noto Serif Armenian XCn Md:style=ExtraCondensed Medium,Regular
- NotoKufiArabic-Bold.ttf: Noto Kufi Arabic:style=Bold
- NotoSansArabic-CondensedExtraLight.ttf: Noto Sans Arabic,Noto Sans Arabic Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSerifDisplay-ExtraCondensed.ttf: Noto Serif Display,Noto Serif Disp ExtCond:style=ExtraCondensed,Regular
- NotoSansDisplay-Thin.ttf: Noto Sans Display,Noto Sans Disp Thin:style=Thin,Regular
- URWGothic-Demi.t1: URW Gothic:style=Demi
- NotoSerifTamil-CondensedExtraLight.ttf: Noto Serif Tamil,Noto Serif Tamil Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansArabicUI-ExtraCondensedLight.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn Lt:style=ExtraCondensed Light,Regular
- NimbusSans-Italic.t1: Nimbus Sans:style=Italic
- C059-BdIta.t1: C059:style=Bold Italic
- NotoSansDevanagari-ExtraCondensedBlack.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn Bk:style=ExtraCondensed Black,Regular
- NotoSansThaiUI-SemiCondensedMedium.ttf: Noto Sans Thai UI,Noto Sans Thai UI SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansDevanagari-ExtraCondensedMedium.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn Md:style=ExtraCondensed Medium,Regular
- NotoSerifCJKsc-SemiBold.otf: Noto Serif CJK SC,Noto Serif CJK SC SemiBold:style=SemiBold,Regular
- NotoSansMono-SemiCondensedExtraLight.ttf: Noto Sans Mono,Noto Sans Mono SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifHebrew-ExtraCondensed.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond:style=ExtraCondensed,Regular
- NotoSansHebrew-Condensed.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond:style=Condensed,Regular
- NotoSerifGeorgian-ExtraCondensedBold.ttf: Noto Serif Georgian,Noto Serif Georgian XCn:style=ExtraCondensed Bold,Bold
- NotoSerifThai-ExtraCondensed.ttf: Noto Serif Thai,Noto Serif Thai ExtCond:style=ExtraCondensed,Regular
- NimbusMonoPS-Bold.t1: Nimbus Mono PS:style=Bold
- NotoSansTamil-SemiCondensedMedium.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond Med:style=SemiCondensed Medium,Regular
- c059016l.pfb: Century Schoolbook L:style=Bold
- n022004l.pfb: Nimbus Mono L:style=Bold
- NotoSansCJKtc-Thin.otf: Noto Sans CJK TC,Noto Sans CJK TC Thin:style=Thin,Regular
- NotoSansLao-CondensedExtraBold.ttf: Noto Sans Lao,Noto Sans Lao Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSans-ExtraCondensedThinItalic.ttf: Noto Sans,Noto Sans ExtCond Thin:style=ExtraCondensed Thin Italic,Italic
- NotoSansDevanagari-ExtraCondensedExtraBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn XBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansGeorgian-CondensedThin.ttf: Noto Sans Georgian,Noto Sans Georgian Cond Thin:style=Condensed Thin,Regular
- NotoSansHebrew-CondensedExtraBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond ExtBd:style=Condensed ExtraBold,Regular
- n019024l.pfb: Nimbus Sans L:style=Bold Italic
- NotoSansArmenian-SemiCondensedMedium.ttf: Noto Sans Armenian,Noto Sans Armenian SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansTamil-Black.ttf: Noto Sans Tamil,Noto Sans Tamil Blk:style=Black,Regular
- NotoSerifTamil-CondensedSemiBold.ttf: Noto Serif Tamil,Noto Serif Tamil Cond SemBd:style=Condensed SemiBold,Regular
- NotoSerif-SemiBold.ttf: Noto Serif,Noto Serif SemBd:style=SemiBold,Regular
- NotoSansJavanese-Regular.ttf: Noto Sans Javanese:style=Regular
- NotoSerif-ExtraLight.ttf: Noto Serif,Noto Serif ExtLt:style=ExtraLight,Regular
- NotoSerifGeorgian-CondensedLight.ttf: Noto Serif Georgian,Noto Serif Georgian Cn Lt:style=Condensed Light,Regular
- NotoSansCham-Bold.ttf: Noto Sans Cham:style=Bold
- NotoSansKhmerUI-SemiCondensedBlack.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansArmenian-CondensedThin.ttf: Noto Sans Armenian,Noto Sans Armenian Cond Thin:style=Condensed Thin,Regular
- NotoSansDisplay-ExtraCondensedExtraLightItalic.ttf: Noto Sans Display,Noto Sans Disp ExtCond ExtLt:style=ExtraCondensed ExtraLight Italic,Italic
- NotoSansDevanagariUI-ExtraLight.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari XLt:style=ExtraLight,Regular
- NotoSansDisplay-SemiCondensedMediumItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond Med:style=SemiCondensed Medium Italic,Italic
- b018032l.pfb: URW Bookman L:style=Light Italic
- NotoSans-SemiBoldItalic.ttf: Noto Sans,Noto Sans SemBd:style=SemiBold Italic,Italic
- NotoSerifDisplay-SemiCondensedBoldItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond:style=SemiCondensed Bold Italic,Bold Italic
- NotoSansBrahmi-Regular.ttf: Noto Sans Brahmi:style=Regular
- NotoSansThai-SemiCondensedLight.ttf: Noto Sans Thai,Noto Sans Thai SemCond Light:style=SemiCondensed Light,Regular
- NotoSerifCJKtc-SemiBold.otf: Noto Serif CJK TC,Noto Serif CJK TC SemiBold:style=SemiBold,Regular
- NotoSansArmenian-ExtraCondensedSemiBold.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansLao-SemiBold.ttf: Noto Sans Lao,Noto Sans Lao SemBd:style=SemiBold,Regular
- NotoSansMono-CondensedSemiBold.ttf: Noto Sans Mono,Noto Sans Mono Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansGeorgian-SemiCondensedExtraBold.ttf: Noto Sans Georgian,Noto Sans Georgian SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansArabicUI-Black.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Bk:style=Black,Regular
- NotoSansMyanmarUI-SemiCondensedSemiBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn SmBd:style=SemiCondensed SemiBold,Regular
- p052003l.pfb: URW Palladio L:style=Roman
- NotoSans-ExtraCondensedBoldItalic.ttf: Noto Sans,Noto Sans ExtCond:style=ExtraCondensed Bold Italic,Bold Italic
- NotoSerifLao-ExtraCondensedBlack.ttf: Noto Serif Lao,Noto Serif Lao ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansOriya-Bold.ttf: Noto Sans Oriya:style=Bold
- NotoSansKhmerUI-Thin.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Thin:style=Thin,Regular
- NotoSansKayahLi-Regular.ttf: Noto Sans Kayah Li:style=Regular
- NotoSansCham-Thin.ttf: Noto Sans Cham,Noto Sans Cham Thin:style=Thin,Regular
- NotoSerifDisplay-Thin.ttf: Noto Serif Display,Noto Serif Disp Thin:style=Thin,Regular
- NotoSansMonoCJKkr-Bold.otf: Noto Sans Mono CJK KR,Noto Sans Mono CJK KR Bold:style=Bold,Regular
- NotoSans-CondensedThin.ttf: Noto Sans,Noto Sans Cond Thin:style=Condensed Thin,Regular
- NotoSansArabic-ExtraCondensedBold.ttf: Noto Sans Arabic,Noto Sans Arabic ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansCoptic-Regular.ttf: Noto Sans Coptic:style=Regular
- NotoSansDisplay-CondensedBlackItalic.ttf: Noto Sans Display,Noto Sans Disp Cond Blk:style=Condensed Black Italic,Italic
- NotoSansArabicUI-ExtraCondensedSemiBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn SmBd:style=ExtraCondensed SemiBold,Regular
- NotoSansSinhalaUI-ExtraCondensedBlack.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSerifEthiopic-SemiCondensedSemiBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn SmBd:style=SemiCondensed SemiBold,Regular
- NotoSerifMyanmar-Medium.ttf: Noto Serif Myanmar,Noto Serif Myanmar Med:style=Medium,Regular
- NotoSerif-CondensedBlackItalic.ttf: Noto Serif,Noto Serif Cond Blk:style=Condensed Black Italic,Italic
- NotoSansKhmerUI-SemiCondensedExtraBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansKhmerUI-SemiCondensedMedium.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI SemCond Med:style=SemiCondensed Medium,Regular
- NotoSansSinhalaUI-Regular.ttf: Noto Sans Sinhala UI:style=Regular
- NotoSansThai-Light.ttf: Noto Sans Thai,Noto Sans Thai Light:style=Light,Regular
- NotoSerifKhmer-SemiCondensedBlack.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond Blk:style=SemiCondensed Black,Regular
- NotoSansThaiUI-ExtraCondensedExtraBold.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansSinhalaUI-SemiCondensedBlack.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifHebrew-ExtraCondensedExtraLight.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifMyanmar-Light.ttf: Noto Serif Myanmar,Noto Serif Myanmar Light:style=Light,Regular
- NotoSansSymbols-Thin.ttf: Noto Sans Symbols,Noto Sans Symbols Thin:style=Thin,Regular
- URWGothic-DemiOblique.otf: URW Gothic:style=Demi Oblique
- NotoSansTamilUI-ExtraCondensedSemiBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifArmenian-CondensedSemiBold.ttf: Noto Serif Armenian,Noto Serif Armenian Cn SmBd:style=Condensed SemiBold,Regular
- NotoSansArabicUI-CondensedLight.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI Cn Lt:style=Condensed Light,Regular
- NotoSansCJKsc-Regular.otf: Noto Sans CJK SC,Noto Sans CJK SC Regular:style=Regular
- NotoSansMyanmar-CondensedBlack.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond Blk:style=Condensed Black,Regular
- NotoSansBatak-Regular.ttf: Noto Sans Batak:style=Regular
- NotoSansSinhala-CondensedSemiBold.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansArmenian-ExtraCondensedBlack.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansLaoUI-SemiCondensedExtraLight.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansArabicUI-ExtraCondensedMedium.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn Md:style=ExtraCondensed Medium,Regular
- NotoSerifDisplay-CondensedBold.ttf: Noto Serif Display,Noto Serif Disp Cond:style=Condensed Bold,Bold
- NotoSansHebrew-CondensedBlack.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond Blk:style=Condensed Black,Regular
- NotoSansMyanmar-CondensedThin.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond Thin:style=Condensed Thin,Regular
- NotoSansKhmerUI-ExtraBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtBd:style=ExtraBold,Regular
- NotoSansMono-ExtraCondensed.ttf: Noto Sans Mono,Noto Sans Mono ExtCond:style=ExtraCondensed,Regular
- NotoSansTamil-SemiBold.ttf: Noto Sans Tamil,Noto Sans Tamil SemBd:style=SemiBold,Regular
- NotoSerifThai-SemiCondensedSemiBold.ttf: Noto Serif Thai,Noto Serif Thai SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSerifTamil-CondensedThin.ttf: Noto Serif Tamil,Noto Serif Tamil Cond Thin:style=Condensed Thin,Regular
- NotoSerifLao-SemiCondensedBold.ttf: Noto Serif Lao,Noto Serif Lao SemCond:style=SemiCondensed Bold,Bold
- NotoSans-LightItalic.ttf: Noto Sans,Noto Sans Light:style=Light Italic,Italic
- NotoSerifDisplay-ExtraCondensedExtraLightItalic.ttf: Noto Serif Display,Noto Serif Disp ExtCond ExtLt:style=ExtraCondensed ExtraLight Italic,Italic
- P052-Bold.t1: P052:style=Bold
- NotoSerifTamil-ExtraCondensedMedium.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansMyanmarUI-ExtraCondensed.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn:style=ExtraCondensed,Regular
- NotoSansGeorgian-CondensedExtraBold.ttf: Noto Sans Georgian,Noto Sans Georgian Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansLao-ExtraCondensedThin.ttf: Noto Sans Lao,Noto Sans Lao ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansCJKsc-Medium.otf: Noto Sans CJK SC,Noto Sans CJK SC Medium:style=Medium,Regular
- NotoSansDisplay-Bold.ttf: Noto Sans Display,Noto Sans Disp:style=Bold
- NotoSansMyanmarUI-ExtraCondensedSemiBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn SmBd:style=ExtraCondensed SemiBold,Regular
- NotoSansDevanagari-SemiCondensedExtraBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn XBd:style=SemiCondensed ExtraBold,Regular
- NotoSansEthiopic-SemiCondensedBlack.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerifArmenian-CondensedLight.ttf: Noto Serif Armenian,Noto Serif Armenian Cn Lt:style=Condensed Light,Regular
- NotoSerifEthiopic-ExtraLight.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XLt:style=ExtraLight,Regular
- NotoSansDisplay-CondensedExtraLight.ttf: Noto Sans Display,Noto Sans Disp Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSerifGeorgian-SemiCondensedBold.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn:style=SemiCondensed Bold,Bold
- NotoSansDevanagariUI-Bold.ttf: Noto Sans Devanagari UI:style=Bold
- NotoSansMyanmarUI-SemiCondensedLight.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmCn Lt:style=SemiCondensed Light,Regular
- NotoSansEthiopic-CondensedExtraLight.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSans-SemiCondensedBoldItalic.ttf: Noto Sans,Noto Sans SemCond:style=SemiCondensed Bold Italic,Bold Italic
- NotoSansArmenian-ExtraCondensedBold.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansSinhalaUI-ExtraCondensedMedium.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSerifMyanmar-SemiBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar SemBd:style=SemiBold,Regular
- NotoSansDevanagariUI-SemiCondensedExtraLight.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn XLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifHebrew-SemiCondensedThin.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSerifTamil-SemiCondensedLight.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond Light:style=SemiCondensed Light,Regular
- NotoSansEthiopic-ExtraCondensed.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond:style=ExtraCondensed,Regular
- NotoSerifEthiopic-SemiCondensed.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic SmCn:style=SemiCondensed,Regular
- NotoSerif-Regular.ttf: Noto Serif:style=Regular
- NotoSansMyanmar-CondensedExtraLight.ttf: Noto Sans Myanmar,Noto Sans Myanmar Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansKhmer-ExtraBold.ttf: Noto Sans Khmer,Noto Sans Khmer ExtBd:style=ExtraBold,Regular
- NotoSansMyanmarUI-Thin.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Th:style=Thin,Regular
- NotoSerifMyanmar-ExtraLight.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtLt:style=ExtraLight,Regular
- NotoSerifDisplay-Light.ttf: Noto Serif Display,Noto Serif Disp Light:style=Light,Regular
- n019004l.pfb: Nimbus Sans L:style=Bold
- NotoSansHebrew-Regular.ttf: Noto Sans Hebrew:style=Regular
- NotoSansGeorgian-Light.ttf: Noto Sans Georgian,Noto Sans Georgian Light:style=Light,Regular
- NotoSansArmenian-ExtraLight.ttf: Noto Sans Armenian,Noto Sans Armenian ExtLt:style=ExtraLight,Regular
- b018015l.pfb: URW Bookman L:style=Demi Bold
- NotoSerif-BoldItalic.ttf: Noto Serif:style=Bold Italic
- NotoSerif-SemiCondensedExtraLight.ttf: Noto Serif,Noto Serif SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifTamil-ExtraCondensedBold.ttf: Noto Serif Tamil,Noto Serif Tamil ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansSinhala-ExtraCondensedMedium.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansTamil-SemiCondensedSemiBold.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansArabic-SemiCondensedExtraLight.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerifTamil-CondensedLight.ttf: Noto Serif Tamil,Noto Serif Tamil Cond Light:style=Condensed Light,Regular
- NotoSansLaoUI-ExtraLight.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtLt:style=ExtraLight,Regular
- NotoSansSinhalaUI-ExtraCondensedExtraBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansLao-ExtraCondensed.ttf: Noto Sans Lao,Noto Sans Lao ExtCond:style=ExtraCondensed,Regular
- NotoSansHebrew-SemiCondensedLight.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond Light:style=SemiCondensed Light,Regular
- NotoSansEthiopic-ExtraCondensedExtraBold.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansKhmer-SemiCondensedExtraBold.ttf: Noto Sans Khmer,Noto Sans Khmer SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansTeluguUI-Bold.ttf: Noto Sans Telugu UI:style=Bold
- NotoSansDevanagariUI-Thin.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Th:style=Thin,Regular
- n022024l.pfb: Nimbus Mono L:style=Bold Oblique
- NotoSerifTamil-CondensedBlack.ttf: Noto Serif Tamil,Noto Serif Tamil Cond Blk:style=Condensed Black,Regular
- NotoSansMono-SemiCondensedSemiBold.ttf: Noto Sans Mono,Noto Sans Mono SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansSinhala-ExtraCondensedLight.ttf: Noto Sans Sinhala,Noto Sans Sinhala ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerif-SemiCondensedThinItalic.ttf: Noto Serif,Noto Serif SemCond Thin:style=SemiCondensed Thin Italic,Italic
- NotoSansDevanagari-CondensedBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn:style=Condensed Bold,Bold
- NotoSerifKhmer-Medium.ttf: Noto Serif Khmer,Noto Serif Khmer Med:style=Medium,Regular
- NotoSansPhagsPa-Regular.ttf: Noto Sans Phags Pa:style=Regular
- P052-Italic.t1: P052:style=Italic
- NotoSansKhmerUI-ExtraCondensedLight.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansDisplay-ExtraCondensedLight.ttf: Noto Sans Display,Noto Sans Disp ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansMyanmar-ExtraCondensedBlack.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSerif-ExtraCondensedThinItalic.ttf: Noto Serif,Noto Serif ExtCond Thin:style=ExtraCondensed Thin Italic,Italic
- NotoSerifMyanmar-ExtraCondensedMedium.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSerifArmenian-ExtraCondensedLight.ttf: Noto Serif Armenian,Noto Serif Armenian XCn Lt:style=ExtraCondensed Light,Regular
- NotoSansLao-SemiCondensedThin.ttf: Noto Sans Lao,Noto Sans Lao SemCond Thin:style=SemiCondensed Thin,Regular
- NotoSansThaiUI-ExtraCondensed.ttf: Noto Sans Thai UI,Noto Sans Thai UI ExtCond:style=ExtraCondensed,Regular
- NotoSansPhoenician-Regular.ttf: Noto Sans Phoenician:style=Regular
- NotoSansSinhala-CondensedThin.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond Thin:style=Condensed Thin,Regular
- NotoSansDisplay-ExtraCondensedSemiBold.ttf: Noto Sans Display,Noto Sans Disp ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansDevanagariUI-SemiCondensedBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn:style=SemiCondensed Bold,Bold
- NotoSerifArmenian-Bold.ttf: Noto Serif Armenian:style=Bold
- NotoSansGeorgian-ExtraCondensedSemiBold.ttf: Noto Sans Georgian,Noto Sans Georgian ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansBengaliUI-Medium.ttf: Noto Sans Bengali UI,Noto Sans Bengali Med:style=Medium,Regular
- NotoSansCJKsc-Light.otf: Noto Sans CJK SC,Noto Sans CJK SC Light:style=Light,Regular
- NotoSansDisplay-ExtraCondensedThin.ttf: Noto Sans Display,Noto Sans Disp ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansTamilUI-Regular.ttf: Noto Sans Tamil UI:style=Regular
- NotoSansTamilUI-SemiCondensedExtraLight.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansDisplay-SemiCondensed.ttf: Noto Sans Display,Noto Sans Disp SemCond:style=SemiCondensed,Regular
- NotoSerifDisplay-SemiCondensedExtraLightItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond ExtLt:style=SemiCondensed ExtraLight Italic,Italic
- NimbusSansNarrow-Regular.t1: Nimbus Sans Narrow:style=Regular
- NotoSansBengali-SemiBold.ttf: Noto Sans Bengali,Noto Sans Bengali SemBd:style=SemiBold,Regular
- NotoSansTamilUI-ExtraCondensedThin.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSerifDisplay-SemiCondensedSemiBold.ttf: Noto Serif Display,Noto Serif Disp SemCond SemBd:style=SemiCondensed SemiBold,Regular
- NotoSansTamil-Regular.ttf: Noto Sans Tamil:style=Regular
- NotoSans-BoldItalic.ttf: Noto Sans:style=Bold Italic
- NotoSansKhmerUI-Black.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Blk:style=Black,Regular
- NotoSerifDisplay-CondensedMediumItalic.ttf: Noto Serif Display,Noto Serif Disp Cond Med:style=Condensed Medium Italic,Italic
- NotoSerifEthiopic-CondensedExtraBold.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn XBd:style=Condensed ExtraBold,Regular
- NotoSans-ExtraBold.ttf: Noto Sans,Noto Sans ExtBd:style=ExtraBold,Regular
- NotoSansThai-ExtraCondensedBlack.ttf: Noto Sans Thai,Noto Sans Thai ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSerifMyanmar-ExtraBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar ExtBd:style=ExtraBold,Regular
- NotoSans-SemiCondensedExtraLight.ttf: Noto Sans,Noto Sans SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSansLaoUI-ExtraCondensedExtraLight.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifKhmer-ExtraCondensed.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond:style=ExtraCondensed,Regular
- NotoSansDevanagari-SemiCondensedThin.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn Th:style=SemiCondensed Thin,Regular
- NotoSerifEthiopic-ExtraCondensedLight.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic XCn Lt:style=ExtraCondensed Light,Regular
- NotoSansEthiopic-ExtraLight.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtLt:style=ExtraLight,Regular
- NotoSansDisplay-SemiCondensedThinItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond Thin:style=SemiCondensed Thin Italic,Italic
- NotoSerifGeorgian-SemiCondensedSemiBold.ttf: Noto Serif Georgian,Noto Serif Georgian SmCn SmBd:style=SemiCondensed SemiBold,Regular
- NotoSansKhmer-Bold.ttf: Noto Sans Khmer:style=Bold
- NotoSansLao-SemiCondensed.ttf: Noto Sans Lao,Noto Sans Lao SemCond:style=SemiCondensed,Regular
- NotoSansMono-CondensedExtraBold.ttf: Noto Sans Mono,Noto Sans Mono Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansMono-ExtraCondensedBold.ttf: Noto Sans Mono,Noto Sans Mono ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansTeluguUI-Regular.ttf: Noto Sans Telugu UI:style=Regular
- NotoSansHebrew-ExtraCondensedBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew ExtCond:style=ExtraCondensed Bold,Bold
- NotoSerifCJKkr-ExtraLight.otf: Noto Serif CJK KR,Noto Serif CJK KR ExtraLight:style=ExtraLight,Regular
- NotoSerifKhmer-SemiCondensedBold.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond:style=SemiCondensed Bold,Bold
- NotoSerifArmenian-CondensedThin.ttf: Noto Serif Armenian,Noto Serif Armenian Cn Th:style=Condensed Thin,Regular
- NotoSerifTamil-CondensedBold.ttf: Noto Serif Tamil,Noto Serif Tamil Cond:style=Condensed Bold,Bold
- NotoSerifArmenian-CondensedMedium.ttf: Noto Serif Armenian,Noto Serif Armenian Cn Md:style=Condensed Medium,Regular
- NotoSansLao-Medium.ttf: Noto Sans Lao,Noto Sans Lao Med:style=Medium,Regular
- NotoSerifHebrew-CondensedExtraLight.ttf: Noto Serif Hebrew,Noto Serif Hebrew Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansLaoUI-SemiCondensedBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond:style=SemiCondensed Bold,Bold
- NotoSansArabic-Light.ttf: Noto Sans Arabic,Noto Sans Arabic Light:style=Light,Regular
- NotoSansKhmerUI-CondensedSemiBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansThai-CondensedBlack.ttf: Noto Sans Thai,Noto Sans Thai Cond Blk:style=Condensed Black,Regular
- NotoSansKhmerUI-CondensedBlack.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond Blk:style=Condensed Black,Regular
- NotoSansKhmerUI-ExtraCondensedSemiBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond SemBd:style=ExtraCondensed SemiBold,Regular
- NotoSansBalinese-Regular.ttf: Noto Sans Balinese:style=Regular
- NotoSansArmenian-ExtraCondensedLight.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSerifLao-CondensedBlack.ttf: Noto Serif Lao,Noto Serif Lao Cond Blk:style=Condensed Black,Regular
- NotoSansHebrew-CondensedBold.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond:style=Condensed Bold,Bold
- NotoSerifCJKkr-Black.otf: Noto Serif CJK KR,Noto Serif CJK KR Black:style=Black,Regular
- NotoSansMyanmarUI-Medium.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Md:style=Medium,Regular
- NotoSansDisplay-CondensedExtraBold.ttf: Noto Sans Display,Noto Sans Disp Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSansKhmer-ExtraCondensedMedium.ttf: Noto Sans Khmer,Noto Sans Khmer ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansKhmerUI-CondensedMedium.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI Cond Med:style=Condensed Medium,Regular
- NotoSansTamilUI-SemiCondensedExtraBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- C059-Bold.t1: C059:style=Bold
- NotoSansTibetan-Bold.ttf: Noto Sans Tibetan:style=Bold
- NotoSans-CondensedExtraLightItalic.ttf: Noto Sans,Noto Sans Cond ExtLt:style=Condensed ExtraLight Italic,Italic
- NotoSerifMyanmar-Bold.ttf: Noto Serif Myanmar:style=Bold
- NotoSerif-Thin.ttf: Noto Serif,Noto Serif Thin:style=Thin,Regular
- NotoSerif-CondensedSemiBoldItalic.ttf: Noto Serif,Noto Serif Cond SemBd:style=Condensed SemiBold Italic,Italic
- NotoSerifKhmer-SemiCondensed.ttf: Noto Serif Khmer,Noto Serif Khmer SemCond:style=SemiCondensed,Regular
- NotoSansMyanmar-ExtraCondensedLight.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansMyanmarUI-ExtraLight.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XLt:style=ExtraLight,Regular
- NotoSansLao-SemiCondensedBlack.ttf: Noto Sans Lao,Noto Sans Lao SemCond Blk:style=SemiCondensed Black,Regular
- NotoSerif-CondensedExtraBold.ttf: Noto Serif,Noto Serif Cond ExtBd:style=Condensed ExtraBold,Regular
- NotoSerifTamil-Bold.ttf: Noto Serif Tamil:style=Bold
- NotoSerifDisplay-SemiCondensedLightItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond Light:style=SemiCondensed Light Italic,Italic
- NotoSansTamil-SemiCondensedLight.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond Light:style=SemiCondensed Light,Regular
- NotoSansLaoUI-ExtraCondensedExtraBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansArmenian-ExtraCondensed.ttf: Noto Sans Armenian,Noto Sans Armenian ExtCond:style=ExtraCondensed,Regular
- NotoSerifArmenian-CondensedBold.ttf: Noto Serif Armenian,Noto Serif Armenian Cn:style=Condensed Bold,Bold
- NotoSerifDisplay-CondensedThin.ttf: Noto Serif Display,Noto Serif Disp Cond Thin:style=Condensed Thin,Regular
- NotoSansThai-CondensedThin.ttf: Noto Sans Thai,Noto Sans Thai Cond Thin:style=Condensed Thin,Regular
- NotoSerif-ExtraCondensedExtraBoldItalic.ttf: Noto Serif,Noto Serif ExtCond ExtBd:style=ExtraCondensed ExtraBold Italic,Italic
- NotoSerifEthiopic-CondensedThin.ttf: Noto Serif Ethiopic,Noto Serif Ethiopic Cn Th:style=Condensed Thin,Regular
- NotoSerif-ExtraCondensedExtraBold.ttf: Noto Serif,Noto Serif ExtCond ExtBd:style=ExtraCondensed ExtraBold,Regular
- NotoSansMono-Thin.ttf: Noto Sans Mono,Noto Sans Mono Thin:style=Thin,Regular
- NotoSerifEthiopic-Bold.ttf: Noto Serif Ethiopic:style=Bold
- NotoSansDevanagariUI-SemiBold.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmBd:style=SemiBold,Regular
- NotoSerifKhmer-ExtraBold.ttf: Noto Serif Khmer,Noto Serif Khmer ExtBd:style=ExtraBold,Regular
- NotoSansCJKtc-Medium.otf: Noto Sans CJK TC,Noto Sans CJK TC Medium:style=Medium,Regular
- NotoSerif-SemiCondensedLightItalic.ttf: Noto Serif,Noto Serif SemCond Light:style=SemiCondensed Light Italic,Italic
- NotoSansDisplay-CondensedThin.ttf: Noto Sans Display,Noto Sans Disp Cond Thin:style=Condensed Thin,Regular
- NotoSansMyanmar-ExtraCondensedMedium.ttf: Noto Sans Myanmar,Noto Sans Myanmar ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSerif-ExtraCondensedExtraLight.ttf: Noto Serif,Noto Serif ExtCond ExtLt:style=ExtraCondensed ExtraLight,Regular
- NotoSansHebrew-CondensedExtraLight.ttf: Noto Sans Hebrew,Noto Sans Hebrew Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansMonoCJKjp-Bold.otf: Noto Sans Mono CJK JP,Noto Sans Mono CJK JP Bold:style=Bold,Regular
- NotoSansSinhalaUI-SemiCondensedExtraBold.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSansTamil-ExtraCondensedLight.ttf: Noto Sans Tamil,Noto Sans Tamil ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansDevanagari-CondensedExtraBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn XBd:style=Condensed ExtraBold,Regular
- NotoSansGurmukhiUI-Bold.ttf: Noto Sans Gurmukhi UI:style=Bold
- NotoSerifKhmer-ExtraCondensedLight.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSansThaiUI-Bold.ttf: Noto Sans Thai UI:style=Bold
- NotoSansSinhala-CondensedExtraLight.ttf: Noto Sans Sinhala,Noto Sans Sinhala Cond ExtLt:style=Condensed ExtraLight,Regular
- c059036l.pfb: Century Schoolbook L:style=Bold Italic
- NotoSerifTamil-Medium.ttf: Noto Serif Tamil,Noto Serif Tamil Med:style=Medium,Regular
- NotoSerif-Light.ttf: Noto Serif,Noto Serif Light:style=Light,Regular
- NotoSerifDisplay-ExtraBold.ttf: Noto Serif Display,Noto Serif Disp ExtBd:style=ExtraBold,Regular
- p052024l.pfb: URW Palladio L:style=Bold Italic
- NotoSansSinhalaUI-Light.ttf: Noto Sans Sinhala UI,Noto Sans Sinhala Light:style=Light,Regular
- NotoSansMyanmarUI-ExtraCondensedExtraBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI XCn XBd:style=ExtraCondensed ExtraBold,Regular
- NotoSans-SemiCondensedMediumItalic.ttf: Noto Sans,Noto Sans SemCond Med:style=SemiCondensed Medium Italic,Italic
- NotoSerifGeorgian-ExtraCondensedMedium.ttf: Noto Serif Georgian,Noto Serif Georgian XCn Md:style=ExtraCondensed Medium,Regular
- NotoSansDevanagariUI-CondensedLight.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari Cn Lt:style=Condensed Light,Regular
- URWBookman-Light.t1: URW Bookman:style=Light
- DejaVuSerif.ttf: DejaVu Serif:style=Book
- NotoSansTamil-SemiCondensed.ttf: Noto Sans Tamil,Noto Sans Tamil SemCond:style=SemiCondensed,Regular
- NotoSansDisplay-CondensedBlack.ttf: Noto Sans Display,Noto Sans Disp Cond Blk:style=Condensed Black,Regular
- NotoSansEthiopic-ExtraCondensedMedium.ttf: Noto Sans Ethiopic,Noto Sans Ethiopic ExtCond Med:style=ExtraCondensed Medium,Regular
- NotoSansTibetan-Regular.ttf: Noto Sans Tibetan:style=Regular
- NotoSerifDisplay-SemiCondensedSemiBoldItalic.ttf: Noto Serif Display,Noto Serif Disp SemCond SemBd:style=SemiCondensed SemiBold Italic,Italic
- P052-Roman.otf: P052:style=Roman
- NotoSansLimbu-Regular.ttf: Noto Sans Limbu:style=Regular
- NotoSerifMyanmar-CondensedSemiBold.ttf: Noto Serif Myanmar,Noto Serif Myanmar Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansKhmerUI-ExtraCondensed.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond:style=ExtraCondensed,Regular
- NotoSansDisplay-SemiCondensedBoldItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond:style=SemiCondensed Bold Italic,Bold Italic
- NotoSansMyanmar-Light.ttf: Noto Sans Myanmar,Noto Sans Myanmar Light:style=Light,Regular
- NotoSansTifinagh-Regular.ttf: Noto Sans Tifinagh:style=Regular
- NotoSansCypriot-Regular.ttf: Noto Sans Cypriot:style=Regular
- NotoSansLao-SemiCondensedMedium.ttf: Noto Sans Lao,Noto Sans Lao SemCond Med:style=SemiCondensed Medium,Regular
- NotoSerifHebrew-ExtraLight.ttf: Noto Serif Hebrew,Noto Serif Hebrew ExtLt:style=ExtraLight,Regular
- NotoSansArabic-SemiCondensedBold.ttf: Noto Sans Arabic,Noto Sans Arabic SemCond:style=SemiCondensed Bold,Bold
- NotoSerifTamil-SemiCondensedBlack.ttf: Noto Serif Tamil,Noto Serif Tamil SemCond Blk:style=SemiCondensed Black,Regular
- NotoSans-Thin.ttf: Noto Sans,Noto Sans Thin:style=Thin,Regular
- NotoSansSamaritan-Regular.ttf: Noto Sans Samaritan:style=Regular
- NotoSansDisplay-SemiCondensedExtraBoldItalic.ttf: Noto Sans Display,Noto Sans Disp SemCond ExtBd:style=SemiCondensed ExtraBold Italic,Italic
- NotoSansLao-ExtraCondensedBlack.ttf: Noto Sans Lao,Noto Sans Lao ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansSyriacWestern-Regular.ttf: Noto Sans Syriac Western:style=Regular
- NotoSansArmenian-Medium.ttf: Noto Sans Armenian,Noto Sans Armenian Med:style=Medium,Regular
- NotoSansDevanagari-ExtraCondensedSemiBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari XCn SmBd:style=ExtraCondensed SemiBold,Regular
- NotoSansSinhala-SemiCondensedExtraLight.ttf: Noto Sans Sinhala,Noto Sans Sinhala SemCond ExtLt:style=SemiCondensed ExtraLight,Regular
- NotoSerif-Medium.ttf: Noto Serif,Noto Serif Med:style=Medium,Regular
- NotoSansCham-Regular.ttf: Noto Sans Cham:style=Regular
- NotoSansHebrew-SemiCondensedThin.ttf: Noto Sans Hebrew,Noto Sans Hebrew SemCond Thin:style=SemiCondensed Thin,Regular
- C059-Bold.otf: C059:style=Bold
- NotoSansDisplay-ExtraCondensedBlack.ttf: Noto Sans Display,Noto Sans Disp ExtCond Blk:style=ExtraCondensed Black,Regular
- NotoSansHebrew-Light.ttf: Noto Sans Hebrew,Noto Sans Hebrew Light:style=Light,Regular
- NotoSansDevanagari-CondensedSemiBold.ttf: Noto Sans Devanagari,Noto Sans Devanagari Cn SmBd:style=Condensed SemiBold,Regular
- NotoSerifLao-Condensed.ttf: Noto Serif Lao,Noto Serif Lao Cond:style=Condensed,Regular
- P052-Bold.otf: P052:style=Bold
- NotoSansMyanmarUI-SemiBold.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI SmBd:style=SemiBold,Regular
- NotoSansKhmerUI-ExtraCondensedThin.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansLaoUI-CondensedExtraLight.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond ExtLt:style=Condensed ExtraLight,Regular
- NotoSansMyanmarUI-CondensedBlack.ttf: Noto Sans Myanmar UI,Noto Sans Myanmar UI Cn Bk:style=Condensed Black,Regular
- NotoSansThai-SemiCondensedMedium.ttf: Noto Sans Thai,Noto Sans Thai SemCond Med:style=SemiCondensed Medium,Regular
- NotoSerifHebrew-SemiCondensedLight.ttf: Noto Serif Hebrew,Noto Serif Hebrew SemCond Light:style=SemiCondensed Light,Regular
- NotoSerifKhmer-ExtraCondensedBold.ttf: Noto Serif Khmer,Noto Serif Khmer ExtCond:style=ExtraCondensed Bold,Bold
- NotoSansTamilUI-ExtraCondensedLight.ttf: Noto Sans Tamil UI,Noto Sans Tamil ExtCond Light:style=ExtraCondensed Light,Regular
- NotoSans-ExtraCondensedExtraLightItalic.ttf: Noto Sans,Noto Sans ExtCond ExtLt:style=ExtraCondensed ExtraLight Italic,Italic
- NotoSansLao-CondensedSemiBold.ttf: Noto Sans Lao,Noto Sans Lao Cond SemBd:style=Condensed SemiBold,Regular
- NotoSerifArmenian-SemiCondensedLight.ttf: Noto Serif Armenian,Noto Serif Armenian SmCn Lt:style=SemiCondensed Light,Regular
- NotoSansDevanagari-SemiCondensedExtraLight.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn XLt:style=SemiCondensed ExtraLight,Regular
- NotoSansDevanagari-SemiCondensedMedium.ttf: Noto Sans Devanagari,Noto Sans Devanagari SmCn Md:style=SemiCondensed Medium,Regular
- NotoSerifDisplay-CondensedThinItalic.ttf: Noto Serif Display,Noto Serif Disp Cond Thin:style=Condensed Thin Italic,Italic
- NotoSansLaoUI-CondensedThin.ttf: Noto Sans Lao UI,Noto Sans Lao UI Cond Thin:style=Condensed Thin,Regular
- NotoSansLaoUI-SemiCondensedExtraBold.ttf: Noto Sans Lao UI,Noto Sans Lao UI SemCond ExtBd:style=SemiCondensed ExtraBold,Regular
- NotoSans-SemiBold.ttf: Noto Sans,Noto Sans SemBd:style=SemiBold,Regular
- NotoSansArabicUI-ExtraCondensedExtraLight.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn XLt:style=ExtraCondensed ExtraLight,Regular
- NotoSerifArmenian-ExtraCondensedSemiBold.ttf: Noto Serif Armenian,Noto Serif Armenian XCn SmBd:style=ExtraCondensed SemiBold,Regular
- NotoSerifKhmer-CondensedSemiBold.ttf: Noto Serif Khmer,Noto Serif Khmer Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansArabicUI-ExtraCondensedBold.ttf: Noto Sans Arabic UI,Noto Sans Arabic UI XCn:style=ExtraCondensed Bold,Bold
- NotoSansDevanagariUI-SemiCondensedMedium.ttf: Noto Sans Devanagari UI,Noto Sans Devanagari SmCn Md:style=SemiCondensed Medium,Regular
- NotoSans-Condensed.ttf: Noto Sans,Noto Sans Cond:style=Condensed,Regular
- NimbusRoman-Italic.otf: Nimbus Roman:style=Italic
- NotoSerifLao-CondensedSemiBold.ttf: Noto Serif Lao,Noto Serif Lao Cond SemBd:style=Condensed SemiBold,Regular
- NotoSansKhmerUI-ExtraCondensedBold.ttf: Noto Sans Khmer UI,Noto Sans Khmer UI ExtCond:style=ExtraCondensed Bold,Bold
- n019003l.pfb: Nimbus Sans L:style=Regular
- NotoSans-SemiCondensedBlackItalic.ttf: Noto Sans,Noto Sans SemCond Blk:style=SemiCondensed Black Italic,Italic
- NotoSerif-ExtraCondensedThin.ttf: Noto Serif,Noto Serif ExtCond Thin:style=ExtraCondensed Thin,Regular
- NotoSansMono-ExtraBold.ttf: Noto Sans Mono,Noto Sans Mono ExtBd:style=ExtraBold,Regular
- NotoSansTamilUI-Bold.ttf: Noto Sans Tamil UI:style=Bold
- NotoSerifArmenian-ExtraCondensedExtraBold.ttf: Noto Serif Armenian,Noto Serif Armenian XCn XBd:style=ExtraCondensed ExtraBold,Regular
- NotoSerif-LightItalic.ttf: Noto Serif,Noto Serif Light:style=Light Italic,Italic
- NotoSans-ThinItalic.ttf: Noto Sans,Noto Sans Thin:style=Thin Italic,Italic
- NotoSansTamilUI-SemiCondensedBold.ttf: Noto Sans Tamil UI,Noto Sans Tamil SemCond:style=SemiCondensed Bold,Bold
Operations on Renditions
The API gateway provides the following endpoints for the handling of renditions. The individual operations are documented in the corresponding object’s audit trail.
kind of rendition |
text |
pdf |
slide |
---|---|---|---|
Retrieval for current object version |
GET /api/dms/objects/{objectId}/contents/renditions/text |
GET /api/dms/objects/{objectId}/contents/renditions/pdf |
GET /api/dms/objects/{objectId}/contents/renditions/slide |
Retrieval for any object version |
- |
GET /api/dms/objects/{objectId}/versions/{versionNr}/contents/renditions/pdf |
GET /api/dms/objects/{objectId}/versions/{versionNr}/contents/renditions/slide |
Update |
POST /api/dms/objects/{objectId}/contents/renditions/text |
- |
- |
Rendition Repository
A default rendition repository can be configured. Renditions of supported types (listed below) of binary content files assigned to objects can be stored in the default rendition repository. Thus, renditions can be retrieved from storage and are not regenerated for each retrieval request. Whenever a rendition of a supported type is requested for an object, it is retrieved from the default rendition repository. If available, the stored rendition will be returned. If not available, the requested rendition is generated from the binary content file that is assigned to the object, stored in the default rendition repository and finally returned.
The initial generation of a rendition is triggered by its first request.
If a default rendition repository is configured and accessible, the following rendition types are managed in this repository:
Type | Content-Type | Description |
---|---|---|
|
|
The PDF representation of the binary content file. No distinction between PDF, PDF/A or PDF with embedded OCR. |
|
|
A thumbnail representation of the binary content file. |
If the default rendition repository is not available or not configured, any request for a rendition triggers the generation of a new rendition file. The result is returned but not stored in a repository. Thus, for subsequent requests of the same rendition, it has to be regenerated each time.
Asynchronous Full-text Indexing
The asynchronous full-text creation is integrated in the document lifecycle management and controlled by tagging. The operation of the responsable renditiontextworker
service requires the following configuration steps.
-
Create a cross-tenant service account for the
renditiontextworker
service. -
Configure its credentials via environment variables for the
renditiontextworker
service:-
YUUVIS_TENANT
- The tenant in which the cross-tenant service account is created. -
YUUVIS_USER
- The username of the cross-tenant service account. -
YUUVIS_PASSWORD
- The password of the cross-tenant service account.
-
-
Optional: The values can be protected in a Kubernetes secret.
-
Optional: If you want to store the calculated text renditions in the rendition repository, set the parameter
rendition.store.text: true
in a service-specific YAML configuration file, e.g.renditiontextworker-prod.yml
.
The renditiontextworker
is called via the preconfigured lifecycle hook in the system hook configuration:
{
"systemhooks": {
"amqp": [...],
"lifecycle": [
...
{
"type" : "dms.request.objects.upsert.database-before",
"enable" : true,
"predicate" : "spel:contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null",
"tagname": "system:ren:text",
"tagstate": 1
}
...
],
"webhooks": [...]
}
}
2.4.6. Audit Trail
The audit trail is the history protocol of an object, serving to document its entire lifecycle. It is managed by the audit
service. There are many different actions that trigger the creation of a new entry in the respective object’s audit trail.
The created audit entries are stored in a separated database table.
If necessary, the creation of specific audit entries can be skipped. Please be aware that the skipped audit entries are actually NOT CREATED ANYWHERE. The corresponding actions on DMS objects in your system will not be documented at all. |
The endpoint GET /dms/objects/{objectId}/history
endpoint returns the list of audit trail entries for the specified DMS object.
action code |
detail value |
subaction code |
Endpoints triggering the entry | Description |
---|---|---|---|---|
Import: |
||||
100 |
|
- |
POST |
The specified object was created by functions of the client or by an import without binary content. |
101 |
|
- |
POST POST |
The object was created using functions of the client or via an import operation including binary content. |
110 |
|
|
POST |
A tag for the object was created. |
Deletion: |
||||
200 |
|
- |
DELETE DELETE |
The object was deleted and cannot be restored. |
201 |
|
- |
As of 2023 Summer: DELETE |
Binary content of the object is removed. A new object version was created that has no |
202 |
|
- |
DELETE |
Object marked for deletion. |
210 |
|
|
DELETE |
The tag for the object was deleted. |
220 |
|
- |
DELETE |
The object version was deleted and cannot be restored. |
Update: |
||||
300 |
|
- |
POST PATCH |
The metadata of the object or its status was edited using functions of the client or via an update carried out during the import operation. |
301 |
|
- |
DELETE |
The document content was edited using functions of the client or via an update carried out during the import operation. |
302 |
|
- |
POST |
The document content and metadata were both edited within one request. |
303 |
|
- |
POST POST |
The object was updated and the binary content was moved. |
306 |
|
1 |
As of 2022 Winter: POST |
The rendition of the binary content file of a DMS object was added or updated via endpoint. The subaction specifies the type of rendition. |
310 |
|
- |
POST POST |
One of the object’s tags was changed. |
325 |
|
- |
POST |
The data of the old object version were used to update the current object version. |
340 |
|
- |
POST PATCH |
The value for the |
Retrieve: |
||||
400 |
|
- |
GET GET GET |
The document content was read by the user, printed, or otherwise output. No changes were made. As of 2022 Summer: If a user retrieves the binary content file of the same object version multiple times within 10 minutes, only the first retrieval is documented in the audit trail. The following processes internally retrieve the object’s binary content file and thus trigger the creation of an audit entry as well:
|
401 |
|
- |
POST GET GET GET |
The object’s metadata were retrieved for viewing. The following processes internally retrieve the object’s metadata and thus trigger the creation of an audit entry as well:
|
402 |
|
1 |
GET |
Rendition of the binary content accessed. If a user retrieves the same type of rendition for the same object multiple times within 10 minutes, only the first retrieval is documented in the audit trail. The subaction specifies the |
2 |
GET |
|||
3 |
GET |
2.5. Access Management
Any operation via yuuvis® Momentum API requires authentication. The authentication process is managed by the authentication
service and an identity provider of customer’s choice. The supported authentication methods are described below.
After successful authentication, a session is opened. The available operations within the session are determined by:
-
endpoint access configuration and
-
role-based permission for DMS operations.
2.5.1. Authentication against the Core API
A yuuvis® Momentum user has to be authenticated in order to be authorized to access to whatever resources or functions his role entitles him too. To achieve this, yuuvis® Momentum connects to an identity provider, which may offer Single Sign-On (SSO) functionality. An existing corporate systems environment usually already uses some sort of identity provider. An identity provider is a software managing user accounts and authentication, the classic example being Microsoft® Active Directory® (AD) or OpenLDAP implementations. Using the yuuvis® Momentum authentication
service requires an identity provider to handle authentication by providing the endpoints used in the OAuth 2.0 authorization workflows.
Choosing an Authentication Method
Depending on the circumstances in which your yuuvis® API client application is supposed to authenticate itself, the recommendation toward an authentication method changes. The diagram below shows an example decision process that should be adhered to by developers of yuuvis® API applications.
Authentication Method | Purpose |
---|---|
Authorization Code Flow |
This type of authentication flow is used to authenticate users coming from either browsers or mobile apps. Unauthenticated calls to the yuuvis® API are redirected to the identity provider, where the user authenticates using whatever method the identity provider is configured for. This can be a simple login form, Kerberos, a two- or multi-factor login, or anything else out of the multitude of possibilities. After authentication, the call is routed back to the yuuvis® API in authenticated form. |
Password Credentials Flow |
In this authentication flow, a client application transmits the users’ credentials together with its own client credentials to the yuuvis® API as the Base64-encoded content of an ‘Authorization’ header. This authentication flow lends itself to backend operations, such as applications migrating data to yuuvis® API. |
Device Flow |
This flow is intended to support any application that is supposed to work with yuuvis® API but does not have access to a native browser or the identity provider itself to obtain a pair of client credentials. An endpoint designed for this case supplies that kind of application with a user_code, device_code and verification URI which can be called using a remote browser to authenticate at the identity provider and obtain an access token. |
All OAuth 2.0 authentication flows end with the client application obtaining an access token representing the users’ credentials that can be used to authenticate at yuuvis® API. They form the basis for all available authentication procedures.
Authentication with Authorization Code Flow
When using web clients, authentication should be accomplished using the Authorization Code Flow. For each tenant known to the identity provider, an authentication URL is created that users of the tenant can use to reach login forms to authenticate with.
https://<yuuvis-base-url>/oauth/<tenant>
default
tenant:https://yuuvis.io/oauth/default
If an unauthenticated user tries to call any webclient URL other than the tenant-specific authentication URL and fails to supply a Tenant Header, he/she will be redirected to the tenant form of the identity provider. Once the authentication has been completed, all following calls to yuuvis® API URLs will be contextualized using tenant and identity of the user.
For every tenant that’s supposed to support this authentication flow, the properties clientId
, clientSecret
, userAuthorizationUri
, accessTokenUri
, userInfoUri
and userNameExtractionPattern
need to be defined for the authentication service. Optionally, the property ‘endSessionUri’ can be configured to ensure logging out of yuuvis® API also infers a logout at the identity provider.
If the authentication service only defines a single tenant, unauthenticated users may reach the login form of identity provider without naming their tenant.
Authentication with Basic Authentication
For client applications, dealing with the OAuth 2.0 flows can be circumvented by authenticating using basic authentication. Simply send the tenant and credentials of the user in the respective HTTP headers when trying to call any yuuvis® API endpoint. Behind the scenes, the entered credentials will be relayed into the authorization code flow, so the same configuration setup requirements apply.
"Authorization": "Basic <base64 encoded <username>:<password>>"
"X-ID-TENANT-NAME": "<tenant>"
"Authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQK"
"X-ID-Tenant-Name": "default"
Obtaining a Token with Password Credentials Flow
In this flow intended for backend applications, a client application requests an access token from the identity provider directly. However, it requires the client application to be registered at the identity provider, and in turn, the developer of the client application needs administrative access to the identity provider.
The credentials of a user (username, password) and the credentials of the trusted client (client_id, client_secret) together with a grant type flag are delivered to the identity providers’ token URL (i.e. https://<keycloak>/auth/realms/<tenant>/protocol/openid-connect/token
) as a text payload with the MimeType application/x-www-form-urlencoded
. The identity provider will respond with a token and a corresponding token type. This token then needs to be delivered to the Identity Provider similar to the user credentials during Basic authentication.
For this authentication flow, the authentication service’ application-oauth2.yml
configuration file must contain a configuration of the properties userInfoUri
and userNameExtractionPattern
for each tenant. Other tenant-specific configuration properties can be ignored for this flow.
Authentication at the API using an existing access token
For customers that want work with an enriched access token as their method of authentication for their client application, it’s possible to supply a valid access token instead of the credentials. The Password Credentials Flow can be used to obtain the token from the identity provider.
Similar to the credentials-based authentication, the authenticating access token is delivered to the API in the Authorization header.
For this authentication flow, the authentication service must contain a configuration of the properties userInfoUri
and userNameExtractionPattern
for each tenant. Other tenant-specific configuration properties can be ignored for this flow.
"Authorization": "Bearer <access token>>"
"X-ID-TENANT-NAME": "<tenant>"
"Authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQK"
"X-ID-Tenant-Name": "default"
Authentication at the API Using the OAuth 2.0 Device Flow
The OAuth 2.0 device flow serve to authenticate devices without native browsers or the ability to use the regular authentication flows to authenticate their native applications. The yuuvis® API authentication service implements the device flow based on its’ 12th revision (https://tools.ietf.org/html/draft-ietf-oauth-device-flow-12).
Device Flow Process
-
The client application calls
https://<base_url>/tenant/<tenant>/loginDevice
. yuuvis® API responds withdevice_code
,user_code
andverification_uri
-
The client application calls
https://<base_url>/<verfication_uri>?user_code=<user_code>
whereverification_uri
anduser_code
are replaced by the response from step 1. This redirects to the identity provider, where the user authenticates with his credentials. If there is no system browser available to the client application, the user can manually call this URI from any browser on any device. -
The client application starts polling the yuuvis® API authentication service for the status of the authentication at the URL
http://<host>/auth/info/state?device_code=<device_code>
. The polling interval can be derived from the response in step -
During the authentication process, the state polling will return the error
authorization_pending
with status 400. The first state poll after a successful authentication returns the access token and the token type with status 200. The two response parts need to be composited in theAuthorization
header like"Authorization": <token_type> <access_token>
and sent within a final call to any yuuvis® API endpoint, which will authenticate the user using the access token.
Five minutes after their issuance, device_code
and user_code
become invalid. Therefore the authentication needs to be completed within that time frame, otherwise the device flow needs to be repeated from the start. A client application can detect the passage of 5 minutes during polling when the verification URI yields the error expired_token
, implying that polling can be stopped. The lifespan of the user and device code can be configured in the authentication service using the property authentication.oauth2.deviceCodeExpiration
, which defines the codes’ TTL.
Authentication Using External Authentication Services
So far, we’ve detailed the authentication mechanisms available when using the proprietary yuuvis® API authentication service. It is likely that at a later date, most customers will be using yuuvis® API through a managed API gateway, authenticating using a subscription key tied to a platform-specific account (i.e. a Microsoft account for Azure Managed API) instead of user credentials. Since these managed API gateways replace both the Identity Provider and the authentication service, not much can be generally said about the way to authenticate at these external services. If you are using a yuuvis® API build utilizing such a managed API, refer to that API’s documentation when trying to authenticate.
Access via Certificate
In order to granularly manage system security, it is possible to enable a login via certificates that can be used by service accounts. Thus, it is not required anymore to specify user name and password for those accounts in a configuration file. If you want to use the authentication via certificates, ensure that it is supported by your identity provider. In this article, an example configuration is explained that uses Keycloak as identity provider.
An example service is available on GitHub.
Creating a Certificate
The following commands create a certificate to be used for a Kubernetes client within the cluster, e.g., a custom service. The ACCOUNT
variable contains the user name of the service account to which the login via certificate is to be configured.
ACCOUNT=service1 ; \
openssl genpkey -algorithm RSA -out $ACCOUNT-key.pem ; \
openssl req -new -x509 -days 365 -key $ACCOUNT-key.pem -out $ACCOUNT-cert.pem -subj /C=DE/ST=DE-DE/L=Berlin/CN=$ACCOUNT ; \
cat $ACCOUNT-key.pem $ACCOUNT-cert.pem > $ACCOUNT.pem ; \
rm $ACCOUNT-key.pem $ACCOUNT-cert.pem
Creating a Kubernetes Secret
The following command uses the previously created certificate to create a Kubernetes secret.
kubectl -n infrastructure create secret generic client-certificates \
--from-file=service1.pem=/path/to/service1.pem \
--from-file=service2.pem=/path/to/service2.pem
Adjusting the Stateful Set in Keycloak
-
With this command, the Stateful Set of Keycloak is opened for editing.
kubectl -n infrastructure edit sts keycloak
-
Register the secret as volume by extending the
volumes
section as follows:volumes: - name: client-certificates secret: secretName: client-certificates
-
Extend the
volumeMounts
section to activate the volume:volumeMounts: - name: client-certificates readOnly: true mountPath: /secrets/client-certificates
-
Register the certificate in the
env
section:- env: - name: X509_CA_BUNDLE value: /secrets/client-certificates/service1.pem /secrets/client-certificates/service2.pem
Configuring an Account in Keycloak
-
Create the account for which login via certificate should be supported via Users > Add user.
-
Optionally, you can set a password. Assign roles to the account according to its use case.
-
Create a new authentication flow:
-
Via Authentication > Flows > New, create a new Top Level Form. For Alias, use
Client Certificate
. -
Via Add execution, add an authentication step with the provider
X509/Validate Username
. -
Click the Actions link for the new authentication step and open the configuration menu.
-
Specify any Alias, e.g.,
User to certificate mapping
. -
For User Identity Source, select
Subject’s Common Name
. -
For User mapping method, select
Username or Email
. -
Save the configuration.
-
-
Create a Client dedicated to the new authentication flow:
-
Via Client > Create, create a new client with the ID
X509-access
. -
Deactivate Standard Flow Enabled.
-
Via the sub menu Authentication Flow Overrides, select the new Authentication
Flow Client Certificate
for Direct Grant Flow. -
Save the configuration.
-
Testing via curl
-
Test the access:
curl -i -k \ -d "client_id=X509-access" \ -d "grant_type=password" \ -E "service1.pem" \ "https://keycloak-https.infrastructure/auth/realms/yuuvistest/protocol/openid-connect/token"
-
Test the account identity:
curl -i -k \ -H "Accept: application/json" \ -H "Authorization: Bearer eyJhbGciOiJSUzI...." \ "https://keycloak-https.infrastructure/auth/realms/yuuvistest/protocol/openid-connect/userinfo"
2.5.2. Session Management
After a successful log-in process, the session state is stored by the authentication
service. If multiple service instances are used, it is stored in a Redis database.
A session cookie stores the identification of the user’s session via a Cookie Manager of the calling HTTP client (e.g., the browser) such that further requests of the same user are enriched with the session cookie GWSESSIONID
. Thus, the user does not need to log on again for each request.
If the client application uses a browser, the following cookies will be additionally set:
-
i18next
- Stores the language for the tenant selection web page (e.g.,en_US
orde
). -
tenant
- Stores the tenant that was selected on the tenant selection web page.
Further cookies might be set by your identity provider (e.g., Keycloak cookies).
2.5.3. Roles
The Core API protects documents against access by unauthorized persons through a permission system. Each user has one or more roles in this system, giving them access to various documents for specified actions. The user-role mapping manages the assignment of roles to users. In yuuvis® Momentum, this mapping is managed separately from the authentication process itself and can be configured according to the customers' needs. Furthermore, in the configuration of the yuuvis® authentication
service, access conditions can be defined individually for each API endpoint.
Structure of the Permissions System
Roles and Role Sets
The permissions to access documents or to perform certain actions are assigned to specific roles. Users of the system are assigned to particular roles, and through those role assignments acquire the permissions needed — they become the owner of the roles. In general, roles are reusable groups of various permissions. Each role has a unique name and contains one or more permissions that are granted to its owners.
In the header of each incoming and authenticated API call, the roles of the corresponding user are included among other user-specific information. If you assign too many roles with long names to individual users, you might exceed the overall size limit of 8 KB for the header. |
Permissions
Permissions denote access rights to certain objects and are assigned to a role. A permission consists of one or more actions and, optionally, a condition. The condition defines which objects are allowed to be managed by owners of a role with the permission, whereas actions define what procedures are allowed upon meeting the condition. In other words, if a user tries to access an object, the authorization system will go through that user’s roles to see if one of the conditions within their permissions is met by the object. If the object meets the condition of one of the user’s permissions, the user will be able to work with the object according to the actions defined by that permission.
- Actions
-
The actions of a permission specify access rights for specific purposes, whereby a distinction is currently made between
create
access,read
access,delete
access,write
access andtag
access (as of 2024 Spring). The actions can be combined by simply adding multiple actions to the permission.create
(as of 2021 Autumn)
permission to create new objects
read
permission to know about the existence of objects, to receive them in search results and to call various GET endpoints to a special object delete permission that allows to delete content or metadata of objects for which also
read
permission is grantedwrite
permission to update objects or to move the content of objects for which also
read
permission is grantedtag
permission to create/update/delete tags for objects for which also a
read
permission is granted. - Conditions
-
Conditions are statements in the proprietary CMIS-based query language that define the subset of documents in the system affected by a permission. If the condition for a document is met (meaning evaluating the query language expression returns
true
), the owner of the role gets to access that document. For example, conditions can limit a user’s access to a specific type of object or hide documents that are older than a specific date. The conditions are applied to all requests from the role owner and thereby act as filters for the corresponding search results.In a permission the CONTAINS()
query function cannot be used in a condition. The whole statement would always be evaluated asfalse
, even if the condition contains other sub-statements that do not useCONTAINS()
and that would individually be evaluated astrue
.The condition can also be left out – indicating that the permission applies to all documents in the system.
The following code block explains the definition of permissions with an example of creation permissions assigned to different roles.
Examples for Creation Permissions with Condition and without<!-- This role does not grant any permission to create, update or delete any object. --> <role> <name>CAN_CREATE_NOTHING</name> </role> <!-- This role grants creation permission for any object. No conditions have to be matched. --> <role> <name>CAN_CREATE_EVERYTHING</name> <permission> <action>create</action> </permission> </role> <!-- This role grants creation permission for objects that match the condition. In this case, only objects of type 'appTable:order' or 'appEmail:email' can be created. --> <role> <name>CAN_CREATE_SOMETHING</name> <permission> <action>create</action> <condition> system:objectTypeId IN ('appTable:order', 'appEmail:email') </condition> </permission> </role>
As of 2023 Summer, it is possible to specify conditions referencing the
abac
(attribute-based access control) section within the internal JWT (JSON Web Token). The following example role grantsread
permission for objects with at least one entry of the string list propertyappEmail:mailboxes
contained in the current user’s@abac.mailGroups
string list within the JWT.Example for Read Permissions with Condition<role> <name>CAN_CREATE_SOMETHING</name> <permission> <action>read</action> <condition> appEmail:mailboxes IN @abac.mailGroups </condition> </permission> </role>
Endpoints for Managing Permissions
The following endpoints are available for setting up and managing your tenant-specific permissions system:
-
Retrieve the tenant role set -
GET /api/admin/permissions
-
Update the tenant role set -
POST /api/admin/permissions
-
Validate the tenant role set -
POST /api/admin/permissions/validate
For system administrators, the following endpoints are available for managing the global permissions system:
-
Retrieve the global role set -
GET /api/system/permissions
-
Update the global role set -
POST /api/system/permissions
-
Validate the global role set -
POST /api/system/permissions/validate
Since version 2.4, yuuvis® Momentum has the ability to further structure the global role set into applications. This goes hand in hand with the usage of application schemata
, as the new functionality is meant to exclude any role set entries related to an optional application schema from the main global role set.
-
Retrieve a global application role set -
GET /api/system/apps/{app}/permissions
-
Update a global application role set -
POST /api/system/apps/{app}/permissions
-
Validate a global application role set -
POST /api/system/apps/{app}/permissions/validate
To streamline the process of defining yuuvis® Momentum role sets, a number of REST endpoints were made available to retrieve the current role set structures and to apply modifications. As seen in the permissions concept page, there are three options used to structure the role set, coming from two endpoint categories. The /system/permissions
and /system/apps/{app}/permissions
endpoints are both used to modify the global role set applicable to all users of the system, whereas the /admin/permissions
endpoint serves to change the role set specific to the current tenant.
Complete role set files can be supplied to one of the endpoints via an HTTP POST request, overwriting the previous role set present at that position. Thus, retrieving and extending the previous role set state using a GET request on the same endpoint is strongly recommended. New role sets can also be validated by posting them to the role set endpoint URLs using the added URL suffix /validate
.
Code examples in gitHub.
Role Administration
Defining Roles
The roles are defined in role sets. Each role set is stored via the configservice
in a file roleset.xml
that should only be changed using the above listed endpoints.
A role has a name and a list of permissions. Each permission can have one or more actions: read
, delete
and write
. Additionally, they can be restricted by a condition.
Example: a read-permission with the condition system:objectTypeId = 'email'
allows to receive all objects of type email
in search results and to call various GET endpoints for this type of objects.
<?xml version="1.0" encoding="utf-8"?>
<roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://optimal-systems.org/ns/dmscloud/roleset/dmsCloud-roles.xsd">
<role>
<name>RoleEmail</name>
<permission>
<action>read</action>
<condition>system:objectTypeId = 'email:email'</condition>
</permission>
</role>
<role>
<name>RoleDocument</name>
<permission>
<action>read</action>
<condition>system:objectTypeId = 'document'</condition>
</permission>
</role>
<role>
<name>RoleEmailAndDocument</name>
<permission>
<action>read</action>
<condition>system:objectTypeId in ('email:email', 'document')</condition>
</permission>
</role>
<role>
<name>AdminRole</name>
<permission>
<action>read</action>
<action>delete</action>
</permission>
</role>
</roleSet>
For the usage of some additional services a fixed role set is required. |
User-Role Mapping
When users log in at the beginning of a session and are successfully authenticated by the identity provider, a JSON web token is generated in which the users' roles are listed under authorities
. The GET user.info
webhook is responsible for providing the users' roles. By customizing the webhook, it is possible to connect any access management provider delivering the users' roles in a suitable format. Per default, the webhook calls the organization
service that is responsible for providing the role information.
To assign individual roles to the users of the system, an external identity provider is used, which takes over the responsibility for role assignment. Per default, the organization
service reads the keycloak profile and thus requests the information from the identity provider Keycloak.
In order to run the organization
service in Keycloak mode, the keycloak
profile has to be activated and the following connection parameters in the application-oauth2.yml
profile are required:
-
keycloak.server
-
keycloak.admin.username
-
keycloak.admin.password
The roles of users control their rights regarding DMS objects but also regarding yuuvis® Momentum administration. In the default configuration, e.g., the YUUVIS_SYSTEM_INTEGRATOR role allows editing of global configuration files like role sets and schemata. Thus, it is highly important to configure your role management software such that only system operators can assign roles that provide themselves and other users with global rights.
|
2.5.4. Endpoint Access Configuration
Access permissions can be configured for each endpoint (core API URLs and service URLs) in the yuuvis® API authentication service. For this purpose, endpoint patterns are assigned to access conditions.
For each incoming request, the first condition is determined with an endpoint pattern that matches the request URL. This condition is evaluated and decides whether access is granted or not. Access permissions without access conditions are granted after log in. The requesting client can identify rejected requests by the status code 403 (forbidden).
The access conditions are described in the access
attribute of the access permission. User attributes (like user ID, tenant membership or user roles) and request attributes (like IP address or request header) can be used. Complex access conditions can be formed with operators and functions.
By means of the expose
flag, endpoints can be made accessible for unauthenticated access. That means that clients can call the endpoint without having to log in first. The access condition for such endpoints can only contain functions for the evaluation of IP addresses and request headers. Access conditions for expose endpoints always have precedence over those with mandatory authentication, even if they are further down in the mapping list. Services that are called via expose endpoints cannot determine the identity of the caller, even if the caller was authenticated by another endpoint. Without the expose flag, access permissions are only granted after authentication.
Access permissions can be limited to specific HTTP methods (method attribute of the access permission). If you omit the specification, then the permission is applied to all HTTP methods. An access permission can contain multiple endpoint patterns and HTTP methods separated by commas.
Access permissions are registered as an authorization.accesses
list in the configuration of the authentication
service. If multiple lists are entered, only the last one is applied.
Rules for Endpoint Patterns
-
?
placeholder for exactly one random character -
*
placeholder for exactly one path segment -
**
placeholder for any number of path segments -
the query string cannot be included in the pattern
Examples:
-
/com/t?st.html
→ matches
com/test.html
but alsocom/tast.html
orcom/txst.html
-
/com/*.html
→ matches all
.html
files in the com directory -
/com/**/test.html
→ matches all test.html files underneath the com path
-
/org/springframework/*/.html
→ matches all
.html
files underneath theorg/springframework
path -
/org/**/servlet/test.html
→ matches
org/springframework/servlet/test.html
but alsoorg/springframework/testing/servlet/test.html
andorg/servlet/test.html
Syntax for Access Conditions
- Operators
-
-
or
,and
,()
- operators for forming complex access conditions -
==
- compares strings
-
- Functions for expose endpoints
-
-
hasIpAddress('<IP range>')
- returns true if the request comes from the passed IP address range -
hasHeader('<header name>', '<value>')
- returns true if the request contains the passed header and its value starts with the passed value
-
- Functions for endpoints with authentication requirement
-
-
permitAll()
- returns true (parentheses can be omitted) -
denyAll()
- returns false (parentheses can be omitted) -
not(<expression>)
- negates passed expression -
hasIpAddress('<IP range>')
- returns true if the request comes from the passed IP address range -
principal.getId()
- returns caller’s ID -
principal.getUsername()
- returns the login name of the user account (this can occur several times in multi-tenancy systems) -
principal.getTenant()
- returns the caller’s tenant -
hasAuthority('<user role>')
- returns true if the caller has the passed role -
hasAnyAuthority('<role1>','<role2>',…)
- returns true if the caller has one of the passed roles
-
Combined Examples
Callers from the IP address range 192.168.1.0/24
can access managed endpoints without authentication. All other callers must login and have one of the following roles: EXAMPLE_ADMIN_ROLE
or EXAMPLE_INTEGRATOR_ROLE
.
authorization.accesses:
- endpoints: /manage/**,/*/manage/**
expose: true
access: hasIpAddress('192.168.1.0/24')
- endpoints: /manage/**,/*/manage/**
access: hasAnyAuthority('EXAMPLE_ADMIN_ROLE','EXAMPLE_INTEGRATOR_ROLE')
Endpoints for using the web application are accessible for all authenticated users.
authorization.accesses:
- endpoints: /api/dms/**,/api-web/**,/api/sandbox/renditions/**
The yuuvis® core API is read-only. access: permitAll
can be omitted as it corresponds to the default setting. The prohibition condition for the POST method and DELETE method can also be omitted, because the access to unlisted endpoints is generally denied.
authorization.accesses:
- endpoints: /api/dms/objects/**
method: POST,DELETE
access: denyAll
- endpoints: /api/dms/objects/**
method: GET
access: permitAll
- endpoints: /api/dms/objects/search/**
method: POST
access: permitAll
Only users of the default tenant and dev tenant may use custom services.
authorization.accesses:
- endpoints: /custom/**
access: principal.getTenant() == 'default' or principal.getTenant() == 'dev'
Users of the dev tenant are denied access to the custom service. All other users have access.
authorization.accesses:
- endpoints: /custom/**
access: not(principal.getTenant() == 'dev')
The user with the ID 78d3b2a8535b
has unrestricted document access. All other users only have access to the latest document version.
authorization.accesses:
- endpoints: /api/dms/objects/*/versions/**
access: principal.getId() == '78d3b2a8535b'
- endpoints: /api/dms/objects/**
The users historyTracker
of all tenants only have access to the document history. They have no access to other document information. All other users have unrestricted document access.
authorization.accesses:
- endpoints: /api/dms/objects/*/history
- endpoints: /api/dms/objects/**
access: not(principal.getUsername() == 'historyTracker')
2.5.5. Internal JSON Web Tokens
Each call of a yuuvis® Momentum endpoint is routed through the authentication
service. After successful authentication, an internal JSON Web Token (JWT) is created and assigned to the call containing user-specific information. This JWT authorizes the call in every service within the data processing chain.
The JWT is assigned to the call via Authorization header.
Depending on the concrete call, multiple headers might be assigned to it (e.g. containing the user’s roles). However, the sum of all header sizes must not exceed the overall size limit of 8 KB. For systems with many roles and/or many custom user attributes, it is recommended to use the user attributes cache. |
Structure of internal JWTs
The internal JWTs consist of
-
header with signature algorithm RS256,
-
payload and
-
as of 2021 Autumn, a signature of header and payload.
These three parts are included as .-separated Base64-encoded blocks in each authorization request header for API calls, optionally encrypted.
The payload contains key-value pairs specifying the following parameters:
Parameter | Description |
---|---|
|
User ID of the user requesting the API call. |
|
Tenant the requesting user belongs to. |
|
Account name of the user. |
|
Contains the external authentication token taken from the identity provider. |
|
A list containing the roles that are assigned to the user. |
|
(as of 2023 Summer) Optional: a map with single string keys and a list of strings as value for each key. Allows for attribute-based access control (see example below). |
|
Identifies the time at which the JWT was issued. |
|
Identifies the expiration time on and after which the JWT MUST NOT be accepted for processing. Numeric date |
An example payload is displayed in the code block below (abac
section available as of 2023 Summer).
{
"sub": "3cfaf962-b254-45c8-b0e9-82f79f2c26ee",
"tenant": "sales-office",
"name": "mustermann",
"accessToken": "Bearer eyJhbGciOiJS...",
"iat": 1621324798,
"exp": 1621325698,
"authorities": [
"YUUVIS_DEFAULT",
"YUUVIS_MANAGE_SETTINGS",
"ACCESS_MAILBOXES"
],
"abac": {
"mailGroups": [
"mailbox_sales",
"mailbox_pm"
],
"sap_permissions": [
"sap_read",
"sap_write"
]
}
}
Caching User Attributes
The authentication
service can be configured to exclude the authorization
and abac
sections from the JWT to reduce its size. Instead, the full set of user attributes including authorization
and abac
sections is stored for 5 minutes in a userAttributes
Redis cache for each logged-in user.
All services within the yuuvis® Momentum cluster that need the authorization
and abac
information retrieve them from the userAttributes
Redis cache.
Within the cluster, the userAttributes
cache is available via Redis CLI:
-
The following command retrieves a list of all user attributes-related keys for all tenants:
redis-cli keys 'userAttributes*'
Each key contains the tenant und the user ID for a logged-in user. If only one user is currently logged-in, the response could be, e.g.,
redis-cli keys 'userAttributes*' 1) "userAttributes::yuuvistest,3cfaf962-b254-45c8-b0e9-82f79f2c26ee"
-
userAttributes
is the cache name. It is the same for all keys. -
yuuvistest
is the example tenant name. -
3cfaf962-b254-45c8-b0e9-82f79f2c26ee
is the example user ID.
-
-
For each key, the stored value contains the full set of user attributes for the corresponding user. For the example user, it can be retrieved via
redis-cli get userAttributes::yuuvistest,d90b12d5-1288-4a73-92fc-d9b6872df812
The response is a string containing the encoded JSON object, e.g.,
"\"{\\\"username\\\":\\\"root\\\",\\\"id\\\":\\\"d90b12d5-1288-4a73-92fc-d9b6872df812\\\",\\\"title\\\":\\\"First User\\\",\\\"email\\\":\\\"testroot@yuuvis\\\",\\\"firstname\\\":\\\"First\\\ ",\\\"lastname\\\":\\\"User\\\",\\\"domain\\\":\\\"dd\\\",\\\"tenant\\\":\\\"yuuvistest\\\",\\\"authorities\\\":[\\\"YUUVIS_DEFAULT\\\",\\\"YUUVIS_SYSTEM_INTEGRATOR\\\",\\\"YUUVIS_TENANT_ADMI N\\\"],\\\"accountNonExpired\\\":true,\\\"accountNonLocked\\\":true,\\\"credentialsNonExpired\\\":true,\\\"enabled\\\":true}\""
Furthermore, an internal endpoint of the authentication
service GET /session/updateUserAttributesCache/{tenant}/{userId}
is available. It can be called by services within the cluster to retrieve user information and refresh the cache in case a logged-in user is missing (e.g., if the maximum item storage time of 5 minutes is exceeded).
To activate the userAttributes
cache, the following points have to be considered:
-
The
authorization.cacheUserAttributes
parameter has to be configured totrue
in theauthentication-prod.yml
configuration file. -
All services that need
authorization
andabac
information require theredis
profile. This applies to the following core services:-
api
gateway -
audit
service -
authentication
service -
index
service -
registry
service -
repository
service -
search
service -
system
service
-
-
Custom services that might run within the yuuvis® Momentum cluster can retrieve
authorization
andabac
information from Redis or via the endpointGET /session/updateUserAttributesCache/{tenant}/{userId}
if necessary.
Validation of internal JWTs
In order to prevent unauthorized access from outside by faking the JWT, its signature can be used for an additional validation of the caller’s authorization. As of version 2022 Spring, the expiration date is validated as well. Thus, it is not possible to authenticate with a token anymore if its expiration date is exceeded. The validation is provided by the internal endpoint GET /jwt/verify
of the authentication
Service.
2.5.6. Accessing External Services via 'authentication' Service
The authentication
service manages the access to the yuuvis® Momentum API gateway. With a suitable configuration, also the access to external services running in the same Kubernetes cluster can be managed via the authentication
service of yuuvis® Momentum.
Involved Services
Two services of yuuvis® Momentum are responsible for the service routing:
-
the
authentication
service and -
the API gateway.
After successful authentication of incoming requests, the authentication
service sends the requests to the API gateway.
Configuring 'authentication' Service
The service has its own endpoints that are configured in the file authentication-prod.yml
in the section and authorization.accesses
.
The authentication
service endpoints are only available for endpoints listed in authorization.accesses
. The following HTTP methods are supported and tested:
-
DELETE
-
GET
-
HEAD
-
OPTIONS
-
PATCH
-
POST
-
PUT
-
TRACE
Further HTTP methods can be used on the customers' own responsibility and have to be tested regularly by themselves.
Permissions can be defined for the access to the individual endpoints and sub-paths.
Configuring 'api' Gateway
The API gateway uses the Spring Cloud Kubernetes DiscoveryClient in order to dynamically create routes. This DiscoveryClient sends requests to the Kubernetes API. The corresponding permissions are configured via the Kubernetes objects ServiceAccount, RoleBinding and Role.
The pod for the API gateway is executed via the service account that is used by the DiscoveryClient to request namespaces.
The number of the Kubernetes Services can be limited. This can be configured in the file application-kubernetes.yml in the filter for Kubernetes Services. Only for services matching the filter internal routes are created by the API gateway. Per default, the following filter is applied:
metadata!=null && metadata.labels!=null && metadata.labels['yuuvis']=="true"
In order to create a route for a service in the API gateway, the entry yuuvis: true has to be added in the <externalservice>-service.yaml file in the labels section.
Example Configuration
In this example scenario, the required steps of configuration are shown. Afterwards, the external service app in the namespace other will be available via the authentication
service.
Follow these steps:
-
Deploy the pod for the external service app in the namespace
other
.app-deployment.yaml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
apiVersion: apps/v1 kind: Deployment metadata: namespace: other name: app spec: replicas: 1 selector: matchLabels: name: app template: metadata: labels: name: app spec: containers: - name: app ... ports: - containerPort: 80 ...
-
Create a Kubernetes Service for app in the namespace
other
, e.g., app-svc.app-service.yaml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
apiVersion: v1 kind: Service metadata: name: app-svc labels: name: app-svc namespace: other spec: ports: - name: "http" port: 80 targetPort: 80 selector: name: app type: ClusterIP
-
Create the Kubernetes Service in the namespace yuuvis. Use the type externalName that references the namespace other.
<externalservice>-service.yaml1 2 3 4 5 6 7 8 9 10 11 12
apiVersion: v1 kind: Service metadata: name: app labels: yuuvis: "true" namespace: yuuvis spec: type: ExternalName externalName: app-svc.other.svc.cluster.local ports: - port: 80
-
Add the external service app to the section
authorization.access
in the authentication-prod.yml file.authentiaction-prod.yml1 2 3 4
authorization.accesses: - endpoints: /app/** # add # optionally restrict to a method, e.g.: method: Post # optionally restrict to users with specific roles, e.g.: hasAuthority('COGNISPHERE')
-
Restart the
authentication
service.
2.5.7. Cross Tenant Service Accounts
Within your yuuvis® Momentum cluster, you might want to operate a service for asynchronous background processing that is working on all the data in your system independently of the tenant they belong to. Such services need to access the data of all tenants. In order to enhance their performance, they can use an internal service account (as of version 2021 Autumn) that allows for cross-tenant requests and thus avoid high numbers of requests to individual tenants. To configure internal service accounts, read this article carefully and make sure you do not skip any of the described configuration steps in order to ensure and secure the tenant separation.
General Remarks
The concept of service accounts is designed for the operation of background processes within the yuuvis® Momentum cluster.
-
The permissions for the service accounts are specified by the assignment of roles. We recommend to assign only roles that are available in all tenants.
-
The authentication with service accounts is accepted only within the yuuvis® Momentum cluster. External login attempts using service accounts are always rejected.
To ensure this access blocking, service accounts need to be explicitly specified in the yuuvis® Momentum configuration. -
Only selected endpoints of the API gateway can be called with service accounts.
-
In the identity provider, service accounts are associated with a tenant per definition. However, considering the permissions via their roles, they have access to resources of all tenants, e.g., objects including their binary content files and renditions.
Safety Note
The |
Available Endpoints
Every endpoint matching one of the following wildcard patterns can be called via service accounts. For some of them, only particular HTTP request methods are enabled. If not specified (n/a), all HTTP request methods supported by the core API are available.
Pattern | Limited to HTTP Request Methods |
---|---|
|
n/a |
|
POST |
|
n/a |
|
GET |
|
n/a |
|
POST |
As of 2022 Summer: |
PATCH |
Available Metadata Properties
A service account can operate on objects belonging to any tenant of the system. For each individual object, metadata properties can be accessed that are either system properties or defined in a schema that is available for the service account’s tenant:
-
system properties
-
properties defined in the global schema
-
properties defined in the tenant schema for the service account’s tenant
-
properties defined in an app schema that is available in all tenants
-
properties defined in an app schema that is available for the service account’s tenant
Those properties can be managed as usual and used in search queries.
Properties defined in the tenant schema of a different tenant or in an app schema that is not available within the service account’s tenant are not accessible. They cannot be retrieved, searched or modified.
Handling Cross-Tenant Requests
Each authorized request is enriched with an internal JSON Web Token (JWT) containing the service account’s tenant, among other information. If the request calls an operation on an object of a different tenant, the corresponding object’s system:tenant
in the request body will have a different value. It is important to keep this difference in mind, especially for the definition of system hooks.
An operation on an object performed via a service account will trigger the creation of a new entry in the audit trail as usual. Since the executor was the service account, its account ID as defined in the identity provider will be referenced. NOTE: If you are using yuuvis® client as reference implementation, the service account’s ID will also appear in the object history view as soon as the corresponding object has been processed via the service account.
Roles of a Service Account
The permissions of a service account are defined via its roles. Assign as few roles as possible, i.e., only the roles that are required for proper operation of your background process. We recommend to assign only roles that are available in all tenants:
-
roles defined in the global role set or
-
roles defined in an app-specific role set for a system-wide available app.
With roles defined in a tenant-specific role set or in an app-specific role set that is not available for all tenants, the service account will consequently have the corresponding permissions only within the corresponding tenant(s).
Configuring Service Accounts
Create a user account and assign roles in your identity provider.
-
Choose the tenant for the service account. As described above, tenant-specific properties of this tenant will be available for the service account.
-
Assign roles to the account that allow for the specific operations your background process needs to perform in cross-tenant manner. Do not assign more roles than necessary for your specific purpose. Avoid tenant-specific roles.
-
Extract the ID of the account for the configuration in yuuvis® Momentum.
Specify the service account in the yuuvis® Momentum authentication
service configuration.
-
In the configuration file
authentication-prod.yml
, add a new entry to theauthorization.serviceAccounts
list with the syntax<tenant>\<account-id>
.Example with two service accounts:
authorization.serviceAccounts: - account: 'services-tenant\ddffd2d5-5dc5-494a-b706-2250cefee60a' - account: 'services-tenant\fbbe75cf-008e-4de2-bced-f71e402b4369'
-
Restart the
authentication
service.
2.5.8. Customizing the Tenant Selection Web Page
Users accessing yuuvis® Momentum via a browser have to select their tenant before their credentials are requested. This tenant selection web page is provided by the authentication
service. In order to customize the design, it is possible to replace the underlying default form files by a set of custom form files.
Required Sources
A directory public
has to be available in the root of the authentication
service’s container when the service is started. In this public
directory, there must be at least the files tenant.html
and error.html
.
In the tenant.html
file, the reference on http://www.thymeleaf.org
(line 2) and the corresponding form definition are required (lines 11–12) in order to provide the tenant selection functionality.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="res/tenant.css" />
</head>
<body>
<span id="container">
<span>
<h3>Type in your tenant.</h3><br>
<form id="tenant" th:action="@{/tenant}" method="post">
<input type="text" name="tenant" placeholder="Tenant" /><br>
<img src="res/next-btn.svg" onclick="document.getElementById('tenant').submit()">
</form>
</span>
</span>
</body>
</html>
In the error.html
file, the reference on http://www.thymeleaf.org
(line 2) and the three span definitions are required (lines 8–10) in order to provide error details.
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
</head>
<body>
An error has occurred <br /><br />
<span th:text="${status}" /> (<span th:text="${reason}" />) <br />
<span th:utext="${message}" /> <br />
<span th:text="'timestamp: '+${timestamp}" style="display: none" />
</body>
</html>
The usage of resource files is possible if they are located in the sub-directory /public/res/
or if they are stored by a client application.
The example custom form files used in this article are available for download as public.zip
file.
Possible Procedures
There are different ways to proceed:
-
Kubernetes ConfigMaps
-
Manual replacement after starting the pod
-
A custom Docker image with the custom form files in a separated layer
-
Integration of the custom form files via Kubernetes Volumes
In this documentation, only the first procedure via Kubernetes ConfigMaps is described. The replacement of the default form files is explained by means of a simple example.
Configuration via Kubernetes ConfigMaps
By following these steps, you configure a simple custom web page for the tenant selection dialog:
-
Add the following line in the
authentication-prod.yml
configuration file:spring.thymeleaf.prefix: 'file:/public/'
-
Unpack the
public.zip
file. -
Create a ConfigMap for the files in the public directory via the command:
kubectl -n yuuvis create configmap templates --from-file=./public/
-
Adjust the Kubernetes deployment of the
authentication
service via the command:kubectl -n yuuvis edit deploy authentication
-
Extend the
volumes
section as follows:volumeMounts: - name: templates mountPath: /public/tenant.html subPath: tenant.html - name: templates mountPath: /public/error.html subPath: error.html - name: templates mountPath: /public/res/tenant.css subPath: tenant.css - name: templates mountPath: /public/res/next-btn.svg subPath: next-btn.svg
-
Restart the
authentication
service.
2.6. Apps
Management of apps that are based on yuuvis® Momentum via schema, permissions, system hook configuration and availability configurations.
2.6.1. Concept of Apps
The yuuvis® Momentum core system can be used as basis for apps. Apps are additional logical units that enhance the core system. The core system itself provides the possibility to define specific resources for the individual apps. Thus, each app can have its own schema and its own role set. As of version 2021 Summer, apps can be enabled or disabled for individual tenants. The system
service manages the corresponding resource files. There are endpoints provided by the API gateway that allow for retrieval, validation or update of the resource files.
The system can support various apps.
2.6.2. App Information
System integrators can see all existing apps in the system by using the endpoint
Users can see all apps that are enabled for their tenant by using the endpoint
2.6.3. App Management
To create an app, deploy any app-specific resource file (schema, role set, system hook configuration). It has to be valid or completely empty. Alternatively, you can introduce a new app by specifying its name and its tenant-specific state in an app set as described below.
The endpoints for the management of app-specific resource files are provided by the API gateway and call the system
Service internally.
App names are case-insensitive. Furthermore, the system stores uppercase letters in app names in a lowercase form. For example, if you post an app schema for the app name myNewApp
(via POST /system/apps/myNewApp/schema
), this new app appears with the name mynewapp
in the results of endpoints like GET /api/dms/apps
or GET /api/system/apps
.
Additionally, app names have to match the regular expression ([a…zA…Z][a…zA…Z0…9]*-)?([a…zA…Z][a…zA…Z0…9]*
and must not be longer than 255 characters in order to be consistent with the schema validation of app-specific prefixes.
App Schemata
App-specific schemata are managed via the following endpoints:
-
GET /api/system/apps/{app}/schema
-
POST /api/system/apps/{app}/schema
-
POST api/system/apps/{app}/schema/validate
In the multi-tenant landscape of yuuvis® Momentum, any object types or properties that need to be available for multiple or all tenants, need to be introduced to the system schema. To prevent cluttering the system schema, avoid dependencies and allow for duplicate names, the system schema can be structured into applications, which provide a namespace for properties and object types pertaining to a particular use case.
2.6.4. Role Sets for Apps
App-specific role sets are managed via the following endpoints:
-
GET /api/system/apps/{app}/permissions
-
POST /api/system/apps/{app}/permissions
-
POST /api/system/apps/{app}/permissions/validate
The permissions to access objects or to perform certain actions are assigned to specific roles that are listed in the role set. yuuvis® Momentum has the ability to further structure the global role set into applications.
2.6.5. App-specific System Hooks
As of 2022 Summer, it is possible to configure app-specific system hooks in separate resource files.
The following endpoints are available to manage those app-specific resources:
-
GET /api/system/apps/{app}/systemhooks
-
POST /api/system/apps/{app}/systemhooks
-
POST /api/system/apps/{app}/systemhooks/validate
-
App Sets for Availability Management
As of version 2021 Summer, the availability of an app for a specified tenant is managed in an app set via the following endpoints:
-
GET /api/system/tenants/{tenant}/apps
-
POST /api/system/tenants/{tenant}/apps
-
POST /api/system/tenants/{tenant}/apps/validate
An app does not necessarily need its own resources within the core system. The core system can be used to only mark tenants to have a specific app. A new app can be introduced to the system by simply enabling if for a tenant. It is not necessary to create an initial resource (schema, role set or system hook configuration) for the app before you enable it for a tenant.
The configuration of the availability of each app for the specified tenant is stored and managed in the apps.xml
file as shown in the example code block below. In this app set, each app has its own section (<app></app>
) containing the app’s name (<name></name>
) and state of availability (<state></state>
) which can be either enabled or disabled. The default value for state is disabled. Thus, each app that is not listed in the passed configuration XML will not be available for the corresponding tenant. There is no difference in the configuration of not-listed apps and apps listed as disabled.
<?xml version="1.0" encoding="utf-8"?>
<apps xmlns="http://optimal-systems.org/ns/yuuvis/apps/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://optimal-systems.org/ns/yuuvis/apps/yuuvis-core-apps.xsd">
<app>
<name>clientsystem</name>
<state>enabled</state>
</app>
<app>
<name>client</name>
<state>enabled</state>
</app>
<app>
<name>email</name>
<state>disabled</state>
</app>
<app>
<name>acl</name>
<state>disabled</state>
</app>
</apps>
The apps.xml
configuration file is stored via the config
service and should only be changed using the above listed endpoints.
If there is no apps.xml file, the GET endpoint will return the error code 404. Especially in systems of version 2020 Winter and older, there is no app set. If the file is missing entirely, all apps are enabled for all tenants in the system. |
There can be dependencies between different app and tenant schemata via property references or secondary object type references. The validation of the app set considers these dependencies. If the schema of an app is referenced by the global or the corresponding tenant schema, the app cannot be disabled for the specified tenant. Equally, if the schema of an app (A) is referenced by the schema of another app (B), it is not possible to disable the first app (A) and enable the second app (B) for any tenant.
Creating a new dependency considers app availability for all tenants. If a new reference on an app schema (A) is introduced into an app schema (B), the referenced app (B) has to be enabled for each tenant for which the referencing app (A) is enabled. The validation fails if there is a tenant for which the app (A) is enabled and the app (B) is disabled.
2.7. Metrics
As of 2023 Spring, the API gateway offers endpoints to retrieve and manage metrics. For example, it is possible to dynamically calculate the binary storage used by individual tenants. This information could be useful, e.g., for billing purposes.
The following endpoints are available. The URLs contain the metric path parameter to specify the type of metric.
Retrieval | Reset | |
---|---|---|
metric for all tenants |
|
|
metric for any specified tenant |
|
|
metric for currently active tenant |
|
|
2.7.1. Storage Metric
As of 2023 Spring, the storage metric allows to dynamically calculate the binary storage used by individual tenants, e.g., for billing purposes.
In the endpoint URLs above, use storage
as value for the metric
path parameter. For example:
https://<host>/api/system/metrics/storage
The number is calculated from the content stream length stored in the database. The number includes all binary content files assigned to a DMS object or an old version of a DMS object. Invisible objects (flagged with OBJECT_FLAGGED_FOR_DELETION
in the search index) are included as well. Binary content files that are referenced by multiple DMS objects (e.g., compound documents) are counted only once. Rendition files are also NOT included.
The initial calculation or triggered recalculation is a counting process via database statements over all tenants. It is managed by the audit
service and its behavior (automation and fail safety) can be adjusted in the audit
service’s configuration. No storage metric can be retrieved during the counting process in the database. Requests to the GET endpoints listed above return an error.
After the successful counting process in the database, the result is stored in Redis and dynamically updated during any operations on binary content files via API gateway.
2.7.2. Object Count Metric
As of 2023 Summer, the object count metric provides the number of DMS objects (including folder objects) within one specific tenant. In addition, the number of folder objects is provided separately. The information might be used for billing purposes as well as for an emptiness check before removing a tenant from the system.
For the object count metric only the tenant-specific retrieval endpoints GET /api/system/tenants/{tenant}/metrics/{metric}
and GET /api/admin/metrics/{metric}
are available. In the endpoint URLs above, use objectCount as value for the metric path parameter. For example:
https://<host>/api/system/metrics/objectCount
The count includes all current versions of DMS objects regardless of role-based access permissions. Moreover, it includes invisible objects (flagged with OBJECT_FLAGGED_FOR_DELETION
in the search index) as well.
2.8. Error Handling
Errors may occur in many different situations during data processing. In addition to the HTTP status code, yuuvis® Momentum core offers a well-defined structure and labeling of any thrown error. It is thus possible to easily localize the origin of the problem. At the same time, automated catching and analyzing of errors can be implemented based on the fixed error structure and error codes.
2.8.1. Error Structures
Single Errors
The errors are JSON structures with the following parameters:
Parameter | Description |
---|---|
|
Three-digit integer specifying the HTTP status code as a class of the response in which the error is returned. |
|
Integer specifying the concrete error type. |
|
Timestamp of the error occurance in format |
|
String message describing the concrete error. |
|
Origin of the error. As of 2021 Autumn, |
|
The name of the service that threw the error. |
|
The string tenant name where the error occured. |
|
As of 2022 Winter. Wrapped original error thrown by a webhook (find details below). |
{
"httpStatusCode" : 409,
"serviceErrorCode" : 2800,
"time" : "2021-04-21T04:36:30.813",
"message" : "A non-empty folder cannot be deleted.",
"stackTrace" : [ "com.os.enaio.cloud.gateway.resource.api.DmsController.deleteDmsObject(DmsController.java:719)" ],
"service" : "api",
"tenant" : "default"
}
Error Lists during Validation Processes
If errors occur during one of the following validation process, they are collected and returned in the validationErrors
list in JSON format.
-
schema validation
-
role set validation
-
app set validation
Other validation processes return only single errors in the structure described above.
Within the JSON list validationErrors
, the following parameters are provided for each error in the list:
Parameter | Description |
---|---|
|
String message describing the concrete error. |
|
Four-digit integer specifying the concrete error type. |
Together with each non-empty validation error list, the HTTP status code 422 is always returned, but not specifically added to the individual entries.
The following code block shows an example error structure that can occur during a schema validation:
{
"validationErrors": [
{
"message": "Ambiguous IDs. There are 2 property type definitions with the ID 'from'.",
"serviceErrorCode": 2110
},
{
"message": "Wrong base ID. The base ID of the system:document type definition 'email' must be 'system:document', but it is 'system:folder'.",
"serviceErrorCode": 2131
},
{
"message": "Invalid property reference 'fromm' in type definition 'email'.",
"serviceErrorCode": 2132
},
{
"message": "Invalid secondary object type reference 'appAcl:aclowner' in type definition 'email'.",
"serviceErrorCode": 2135
}
]
}
Errors Thrown by Webhooks
If a webhook throws an error in the yuuvis® Momentum error format, its individual parameters are presented as JSON substructure. The serviceErrorCode is 99999. The HTTP status code used for the final response depends on the webhook type. Errors thrown by dms.request.objects.contents webhooks, e.g., have the final HTTP status code 404.
{
"serviceErrorCode": 99999,
"service": "repository",
"messageHistory": "\nMessage History\n---------------------------------------------------------------------------------------------------------------------------------------\nRouteId ProcessorId Processor Elapsed (ms)\n[insertDocumentSetR] [insertDocumentSetR] [direct://insertDocumentSet ] [ 2456]\n[insertDocumentSetR] [[conan] enrich add] [bean[ref:analyzeConfigurationPr [...]",
"innerError": {
"httpStatusCode": 422,
"serviceErrorCode": 12345,
"time": "2022-11-22T14:57:41.7317312",
"message": "Virus [XXXX] detected. See inner error for further details.",
"service": "virus-detection-app",
"innerError": {
"httpStatusCode": 0,
"serviceErrorCode": 0,
"message": "The virus [XXX] was detected in the file [myvirus.exe]. This virus is part of SIV 1.14356.234 from 2022-03-13. See 'https://gprivate.com/61xd3'."
}
},
"time": "2022-11-22T14:57:41.735",
"stackTrace": [
"com.os.services.hel.repo.web.RepositoryRestController.postDmsObjects(RepositoryRestController.java:88)"
],
"message": "Virus [XXXX] detected. See inner error for further details.",
"tenant": "default",
"httpStatusCode": 422
}
If the error thrown by the webhook does not match the yuuvis® Momentum error format, the entire original error is wrapped as String message of the inner error. The serviceErrorCode is 2471 and the HTTP status code is 422.
{
"serviceErrorCode": 2471,
"service": "repository",
"messageHistory": "\nMessage History\n---------------------------------------------------------------------------------------------------------------------------------------\nRouteId ProcessorId Processor Elapsed (ms)\n[insertDocumentSetR] [insertDocumentSetR] [direct://insertDocumentSet ] [ 2456]\n[insertDocumentSetR] [[conan] enrich add] [bean[ref:analyzeConfigurationPr [...]",
"innerError": {
"httpStatusCode": 422,
"serviceErrorCode": 0,
"message": "{\"wrong_body_format\":{\"httpStatusCode\":422,\"serviceErrorCode\":12345,\"time\":\"2022-11-22T15:19:52.3241064\",\"message\":\"Virus [XXXX] detected. See inner error for further details.\",\"service\":\"virus-detection-app\",\"innerError\":{\"httpStatusCode\":0,\"serviceErrorCode\":0,\"message\":\"The virus [XXX] was detected in the file [myvirus.exe]. This virus is part of SIV 1.14356.234 from 2022-03-13. See 'https://gprivate.com/61xd3'.\"}}}"
},
"time": "2022-11-22T15:19:52.34",
"stackTrace": [
"com.os.services.hel.repo.web.RepositoryRestController.postDmsObjects(RepositoryRestController.java:88)"
],
"message": "Webhook response with statuscode '422' did not match the expected failure body format. Please see documentation to ensure correct webhook failure handling and have a look at the inner exception for details.",
"tenant": "default",
"httpStatusCode": 422
}
Any other problems related to the execution of webhooks are indicated with the serviceErrorCode 2470.
2.8.2. Error Codes and Messages
The following table provides an overview of errors that may occur during operation of yuuvis® Momentum core.
In case you want to catch errors and analyse their content, please use the serviceErrorCode as unique identification of the error type. Please do NOT use the message since we reserve to modify it in future. |
serviceErrorCode | httpStatusCode | message | Occurance |
---|---|---|---|
2100 |
- |
The ID '%s' is invalid. If the ID has a prefix, it is not allowed to start with 'ten' or 'app'. |
schema validation |
2101 |
- |
The ID '%s' is invalid. If the ID has a prefix, it is expected to be '%s'. |
schema validation |
2102 |
- |
The ID '%s' is invalid. The ID of an object type is not allowed to start with '%s'. |
schema validation |
2103 |
- |
The ID '%s' is invalid. The ID of a property type is not allowed to start with '%s'. |
schema validation |
2104 |
- |
Too many property types. There are %s property types. Up to %s are allowed. This is a configurable limit. |
schema validation |
2105 |
- |
There are references from the global schema to the schema of app '%s'. For tenant '%s' app '%s' is disabled. |
schema validation |
2106 |
- |
There are references from the schema of app '%s' to the schema of app '%s'. For tenant '%s' app '%s' is enabled and app '%s' is disabled. |
schema validation |
2110 |
- |
Ambiguous IDs. There are %s %s type definitions with the ID '%s'. |
schema validation |
2111 |
- |
Missing ID. There is a %s definition without ID. |
schema validation |
2112 |
- |
Invalid ID. There is a %s with the invalid ID '%s'. The ID must match '%s'. |
schema validation |
2113 |
- |
ID too long. The maximum length for an ID is %s without prefix. The length of '%s' is %s. |
schema validation |
2120 |
- |
Missing property type. The attribute 'propertyType' of the property type definition '%s' is missing. |
schema validation |
2121 |
- |
Wrong property type. The property type of the %s property type definition '%s' must be '%s', but it is '%s'. |
schema validation |
2122 |
- |
Invalid attribute 'queryable' in the %s property type definition '%s'. The value 'false' is only supported for table property type definitions. |
schema validation |
2123 |
- |
Illegal minimum length of the property '%s'. The minimum length of a string property must not exceed %s. |
schema validation |
2124 |
- |
Illegal maximum length of the property '%s'. The maximum length of a string property must not exceed %s. |
schema validation |
2125 |
- |
Illegal cardinality of the property '%s'. The cardinality of a table property must not be 'multi'. |
schema validation |
2126 |
- |
Invalid number of column property definitions for property '%s'. The maximum number of columns in a table must not exceed %s. Column count: '%s' |
schema validation |
2127 |
- |
Illegal cardinality of the property '%s'. The cardinality of a structured data property must not be 'multi'. |
schema validation |
2130 |
- |
Missing base ID. The attribute 'baseId' of the type definition '%s' is missing. |
schema validation |
2131 |
- |
Wrong base ID. The base ID of the %s type definition '%s' must be '%s', but it is '%s'. |
schema validation |
2132 |
- |
Invalid property reference '%s' in type definition '%s'. |
schema validation |
2134 |
- |
There are %s property references with the value '%s' in the definition of the object type '%s'. |
schema validation |
2135 |
- |
Invalid secondary object type reference '%s' in type definition '%s'. |
schema validation |
2136 |
- |
Secondary object type '%s' in type definition '%s' can be referenced only once. |
schema validation |
2140 |
- |
The document type '%s' does not allow content and has a static reference to the secondary object type '%s' that requires content. It is not possible to create instances of this document type. |
schema validation |
2141 |
- |
The document type '%s' does not allow content and has a non-static reference to the secondary object type '%s' that requires content. This secondary object type cannot be assigned to instances of this document type. |
schema validation |
2142 |
- |
The document type '%s' requires content and has a static reference to the secondary object type '%s' that does not allow content. It is not possible to create instances of this document type. |
schema validation |
2143 |
- |
The document type '%s' requires content and has a non-static reference to the secondary object type '%s' that does not allow content. This secondary object type cannot be assigned to instances of this document type. |
schema validation |
2144 |
- |
The document type '%s' has static references to secondary object types that require content ('%s') and that do not allow content ('%s'). It is not possible to create instances of this document type. |
schema validation |
2145 |
- |
The document type '%s' has static references to secondary object types that require content ('%s') and non-static references to secondary object types that do not allow content ('%s'). These non-static secondary object types cannot be assigned to instances of this document type. |
schema validation |
2146 |
- |
The document type '%s' has static references to secondary object types that do not allow content ('%s') and non-static references to secondary object types that require content ('%s'). These non-static secondary object types cannot be assigned to instances of this document type. |
schema validation |
2150 |
- |
The folder type '%s' has static references to secondary object types that require content ('%s'). It is not possible to create instances of this folder type. |
schema validation |
2151 |
- |
The folder type '%s' has non-static references to secondary object types that require content ('%s'). These non-static secondary object types cannot be assigned to instances of this folder type. |
schema validation |
2152 |
- |
The folder type '%s' has static references to secondary object types that allow content ('%s'). It is not possible to create instances of this folder type. |
schema validation |
2153 |
- |
The folder type '%s' has non-static references to secondary object types that allow content ('%s'). These non-static secondary object types cannot be assigned to instances of this folder type. |
schema validation |
2200 |
422 |
Empty lists are not allowed. The property '%s' has an empty list as value. |
schema validation |
2201 |
422 |
The cardinality of the property '%s' is 'multi', but the value is not a list: %s. |
schema validation |
2202 |
422 |
The cardinality of the property '%s' is 'single', but the value is a list: %s. |
schema validation |
2203 |
422 |
Illegal number of values. The cardinality of the property '%s' is 'single', but there are multiple values: %s. |
schema validation |
2204 |
422 |
Null values are not allowed in lists. Property ='%s' |
schema validation |
2210 |
422 |
Illegal property value. The property '%s' is a boolean property and is unable to accept the value '%s'. |
schema validation |
2211 |
422 |
Illegal property value. The property '%s' is a datetime property and is unable to accept the value '%s'. |
schema validation |
2212 |
422 |
Illegal property value. The property '%s' is a decimal property and is unable to accept the value '%s'. |
schema validation |
2213 |
422 |
Illegal property value. The property '%s' is an ID property and is unable to accept the value '%s'. |
schema validation |
2214 |
422 |
Illegal property value. The property '%s' is an integer property and is unable to accept the value '%s'. |
schema validation |
2215 |
422 |
Illegal property value. The property '%s' is a string property and is unable to accept the value '%s'. |
schema validation |
2216 |
422 |
Malformed table. The property part 'columnNames' of the table property '%s' is expected to be a list of strings. ColumnNames: '%s' |
schema validation |
2217 |
422 |
Malformed table. The value of the table property '%s' is expected to be a list. Table value: %s |
schema validation |
2218 |
422 |
Malformed table. A row of the table '%s' is not a list. Row: '%s' |
schema validation |
2219 |
422 |
Illegal property value. The value of the structured data property '%s' is expected to be a list or map. Value: %s |
schema validation |
2220 |
422 |
Invalid JSON. The value of the structured data property %s must be valid JSON. Value = '%s'. Error message: %s |
schema validation |
2240 |
422 |
Illegal property value. The property '%s' is a datetime property with resolution 'date' and is unable to accept the value '%s'. |
schema validation |
2250 |
422 |
The decimal value %s is not valid. The type '%s' does not permit values smaller than %s. |
schema validation |
2251 |
422 |
The decimal value %s is not valid. The type '%s' does not permit values larger than %s. |
schema validation |
2260 |
422 |
The integer value %s is not valid. The type '%s' does not permit values smaller than %s. |
schema validation |
2261 |
422 |
The integer value %s is not valid. The type '%s' does not permit values larger than %s. |
schema validation |
2270 |
422 |
String value is too short. The type '%s' permits only strings with a length of at least %s. The length of '%s' is %s. |
schema validation |
2271 |
422 |
String value is too long. The type '%s' permits only strings with a length up to %s. The length of '%s' is %s. |
schema validation |
2272 |
422 |
String value is too long. A string property permits only strings with a length up to %s. The property '%s' has a value with the length %s: '%s'. |
schema validation |
2280 |
422 |
Illegal column. A table of type '%s' cannot have a column named '%s'. |
schema validation |
2281 |
422 |
Illegal column names. The column '%s' occures %s times. |
schema validation |
2282 |
422 |
Malformed table. The maximum number of rows in a table must not exceed %s. Row count: '%s' |
schema validation |
2283 |
422 |
Invalid row. The row of a table property '%s' is expected to contain exactly %s entries, but row no. %s contains %s entries. |
schema validation |
2290 |
422 |
Structure data value too large. The value of the property '%s' contains %s sub-values. Only up to %s are allowed. |
schema validation |
2291 |
422 |
Structured data value too deep. The value of the property '%s' has a depth of %s. The maximum depth is %s. |
schema validation |
2292 |
422 |
Invalid value of structure data property '%s'. Non-string key found: '%s'. |
schema validation |
2293 |
422 |
Key too long. The length of the key '%s' in the value of the structured data property '%s' is %s. The maximum length is %s. |
schema validation |
2294 |
422 |
Invalid key '%s' in the value of the structured data property '%s'. The key must match the regex '%s'. |
schema validation |
2300 |
422 |
A required property is missing. property='%s' |
schema validation |
2470 |
422 |
Webhook execution resulted in an unexpected failure |
webhook execution |
2471 |
422 |
Webhook response with statuscode '%s' did not match the expected failure body format. Please see documentation to ensure correct webhook failure handling and have a look at the inner exception for details. |
webhook execution |
2880 |
- |
Unable to disable app '%s'. There are references from the tenant schema to the schema of app '%s'. |
app set validation |
2881 |
- |
Unable to disable app '%s'. There are references from the global schema to the schema of app '%s'. |
app set validation |
2882 |
- |
Unable to disable app '%s' and enable app '%s'. There are references from the schema of app '%s' to the schema of app '%s'. |
app set validation |
2900 |
403 |
Method not allowed for tenant independent accounts. |
authentication |
2901 |
403 |
External access is not allowed for the service account. |
authentication |
2902 |
403 |
External access is not allowed for this endpoint. |
authentication |
2903 |
422 |
Could not create JWT. Cause [%s] |
authentication |
2950 |
500 |
Could not write audit entry. Cause [%s] |
audit |
2951 |
500 |
Database unreachable. Cause [%s] |
audit |
99999 |
depends on webhook type |
<custom message> |
webhook execution |
2.9. System Hooks and Interceptors
System hooks are functions that apply to core functions of the yuuvis® Momentum API whenever certain conditions are met and that extend or modify those functions. As such, they serve as a modular, external approach for introducing new functionalities as extensions of already existing ones. There are different types of system hooks available:
-
Lifecycle hooks
-
Webhooks
-
AMQP hooks
2.9.1. Predicate
The predicate specifies a SPEL condition for the call of individual hooks. It is declared in the hook configuration.
In the condition, the metadata of DMS objects can be referenced. The available properties depend on the webhook type as they match the DMS objects at different processing states. However, the options
section is kept constant as far as possible.
Availability of 'options' Properties for Hooks
During Import
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Lifecycle Hook |
|
|
Webhook |
|
|
Webhook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
During Batch Metadata Update
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Lifecycle Hook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
Webhook |
|
|
Webhook |
|
|
During Single Metadata Update
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Lifecycle Hook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
Webhook |
|
|
Webhook |
|
|
During Pure Content Update
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Lifecycle Hook |
|
|
Webhook |
|
|
Webhook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
During Multipart Update
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Lifecycle Hook |
|
|
Webhook |
|
|
Webhook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
During Content Deletion
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Lifecycle Hook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
Webhook |
|
|
Webhook |
|
|
During Restore Version
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Lifecycle Hook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
Webhook |
|
|
Webhook |
|
|
During Tag Creation/Update/Deletion
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Lifecycle Hook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
Webhook |
|
|
Webhook |
|
|
During Tag Search&Set
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Webhook |
|
|
Lifecycle Hook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
Webhook |
|
|
Webhook |
|
|
During Content Move
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
AMQP Hook |
|
|
Webhook |
|
|
During Single Deletion
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Webhook |
|
|
AMQP Hook |
|
|
Webhook |
|
|
During Batch Deletion
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Webhook |
|
|
AMQP Hook |
|
for actually deleted objects: |
Webhook |
|
for actually deleted objects: |
During Search
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
Webhook |
|
|
Webhook |
|
|
During Metadata Retrieval
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
During Content Retrieval
Hook Category | Hook Type | Available 'options' properties |
---|---|---|
Webhook |
|
|
2.9.2. Lifecycle Hooks
As of 2024 Spring.
These hooks provide an easy way to automatically add/update tags to DMS objects during their creation or during update processes.
The tag’s name
and state
are specified in the lifecycle hooks configuration.
A predicate
allows to specify a condition that has to be matched by the DMS object to be tagged via lifecycle hook.
The assigned tags can be used to implement an asynchronous custom processing chain to continue working on the tagged DMS objects according to the business use case.
Types of Lifecycle Hooks
dms.request.objects.upsert.database-before
- Applies to enriched objects just before indexing during import or content/metadata/tag update.
- As of Version
-
2024 Spring
- Description
-
This lifecycle hook can be triggered by
-
an object import,
-
an update of the content,
-
an update of the metadata,
-
or a tag update.
The lifecycle hook receives the completed objects just before they are indexed. This means that the objects are already enriched with system properties and default values (wherever necessary), normalized and validated.
The corresponding webhook entry point dms.request.objects.upsert.database-before
is reached after the lifecycle hooks' entry point. Thus, if configured, a webhook might manipulate the tag information again. -
- Affected API Requests and Action Codes/History Codes
-
100 - OBJECT_CREATED
101 - OBJECT_CREATED_WITH_CONTENTPOST /api/dms/uploads/{uploadId}/objects
(as of 2024 Summer)101 - OBJECT_CREATED_WITH_CONTENT
300 - OBJECT_METADATA_CHANGED
POST /api/dms/objects/{objectId}
(multipart) (as of 2024 Spring)300 - OBJECT_METADATA_CHANGED
302 - OBJECT_METADATA_DOCUMENT_CHANGED301 - OBJECT_DOCUMENT_CHANGED
DELETE /api/dms/objects/{objectId}/contents/file
(as of 2023 Summer)201 - OBJECT_CONTENT_DELETED
POST /api/dms/objects/{objectId}/versions/{versionNr}/actions/restore
(as of 2022 Spring)325 - OBJECT_RESTORED_FROM_VERSION
110 - OBJECT_TAG_CREATED
310 - OBJECT_TAG_UPDATED210 - OBJECT_TAG_DELETED
110 - OBJECT_TAG_CREATED
310 - OBJECT_TAG_UPDATED
- Called by Service
-
registry
service - Example list of DMS objects
-
{ "objects" : [ { "properties" : { "system:objectId" : { "value" : "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId" : { "value" : "system:document" }, "system:objectTypeId" : { "value" : "smallDocument" }, "system:createdBy" : { "value" : "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate" : { "value" : "2021-07-22T15:30:05.020Z" }, "system:lastModifiedBy" : { "value" : "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate" : { "value" : "2021-07-22T15:30:21.520Z" }, "system:versionNumber" : { "value" : 2 }, "system:tenant" : { "value" : "tenant1" }, "system:traceId" : { "value" : "97a35859dbb4c435" }, "Name" : { "value" : "exampledocument-without-content after update" } }, "options" : { "action" : 300, "detail" : "OBJECT_METADATA_CHANGED", "tenant" : "tenant1", "user" : "root", "authorities" : [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_TENANT_ADMIN" ], "inputVersion" : { "properties" : { "system:objectId" : { "value" : "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:objectTypeId" : { "value" : "smallDocument" }, "Name" : { "value" : "exampledocument-without-content after update" } } }, "currentVersion" : { "properties" : { "system:objectId" : { "value" : "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId" : { "value" : "system:document" }, "system:objectTypeId" : { "value" : "smallDocument" }, "system:createdBy" : { "value" : "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate" : { "value" : "2021-07-22T15:30:05.020Z" }, "system:lastModifiedBy" : { "value" : "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate" : { "value" : "2021-07-22T15:30:21.520Z" }, "system:versionNumber" : { "value" : 1 }, "system:tenant" : { "value" : "tenant1" }, "system:traceId" : { "value" : "672c49b7070ebd21" }, "Name" : { "value" : "exampledocument-without-content" } } } } } ] }
- Example Predicate
-
Check if the object type is
appEmail:email
:spel:'appEmail:email'.equals(properties['system:objectTypeId']['value'])
Configuring Lifecycle Hooks
As a type of system hooks, lifecycle hooks are configured in the systemHookConfiguration.json
configuration file. The configuration is managed via the endpoints listed here.
2.9.3. Webhooks
System hooks that extend a function call by an HTTP call under defined conditions.
In order to insert an additional action into the process flow of a functional sequence, the ability for reacting to a function call is required. In yuuvis® Momentum, webhooks are a suitable option for this purpose. They belong to the system hooks and thus are triggered by function calls under specified conditions defined on their predicate
attribute.
A webhook extends the function by an HTTP call. Whenever the predicate of a webhook delivers a true result, an optional HTTP call to a web URL defined in the webhook configuration is performed. The process flow is interrupted until the webhook activity is finished. Thus, the webhook can perform additional processing steps before passing the data back to resume the interrupted main process. If the predicate
of a webhook delivers a false result, the HTTP call is skipped.
For the additional processing, a custom service has to be implemented. This service must be able to handle the request body and the assigned headers. Please note the maximum header size that should be supported by your custom service.
Import and content update webhooks are called in the Repository service, all others in the API-gateway service.
Any changes to the webhook configuration require a restart of the services that are responsible for the call of the affected functions.
Webhook Types
Depending on their type, webhooks are triggered in different situations within the data processing chain.
The webhook type dms.response.objects
can be triggered in various situations. For some of them there are special webhook types (dms.response.objects.insert
, dms.response.objects.update
, dms.response.objects.search
, dms.response.objects.delete
). These sub-webhooks are triggered directly after dms.response.objects
.
GET user.info
- Retrieves roles and any additional available information about the current user logging in to the authentication system from the URL.
- As of Version
-
2019 Winter
- HTTP Method
-
GET
- Response Format
-
JSON
- Parameter
-
String tenant, String userID
- Description
-
Retrieves roles and any additional available information about the current user logging in to the authentication system from the URL.
In the predicate, the tenant of the user who sent the request can be referenced to formulate a condition.
- Requirements for External Endpoint
-
The target URL must return the JSON structure shown in the example response below.
- Called by Service
-
Authentication service
- Example Response
-
{ "username": "111a222b-3c44-5d66-7777-8e999f0000a1", "id": "222a333b-4c55-6d77-8888-9e000f1111a2", "domain": "dd", "tenant": "default", "authorities": [ "TENANT_ADMIN", "SYSTEM_INTEGRATOR", "ACCESS_FOREIGN_JOURNAL_OBJECTS" ], "accountNonExpired": true, "accountNonLocked": true, "credentialsNonExpired": true, "enabled": true }
- Example Predicate
-
Check if the calling user belongs to the
default
tenant:spel:'default'.equals(options['tenant'])
POST dms.request.objects.upsert.storage-before
- Applies to not-enriched objects during import or content/metadata/tag update.
- As of Version
-
2020 Spring
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
This webhook can be triggered by
-
an object import,
-
an update of the content,
-
an update or the metadata,
-
or a tag update.
The original body is an object list with the metadata of the import/update and the corresponding options properties. The metadata are not yet enriched with the system properties that are automatically set by the system. To refer to those properties in a webhook, use POST dms.request.objects.upsert.database-before (Webhook).
The body is modified by the webhook and returned for the resumption of the original process.
The predicate is applied to every single object in the list. The webhook is triggered for the whole object list as soon as one object satisfies the predicate.
-
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests and Action Codes/History Codes
POST /api/dms/objects |
100 - OBJECT_CREATED |
||
POST /api/dms/objects/{objectId} |
300 - OBJECT_METADATA_CHANGED |
||
POST /api/dms/objects/{objectId} (multipart) (as of 2024 Spring) |
300 - OBJECT_METADATA_CHANGED |
||
PATCH /api/dms/objects |
300 - OBJECT_METADATA_CHANGED
|
||
POST /api/dms/objects/{objectId}/contents/file |
301 - OBJECT_DOCUMENT_CHANGED |
||
POST /api/dms/objects/{objectId}/versions/{versionNr}/actions/restore (as of 2022 Spring) |
325 - OBJECT_RESTORED_FROM_VERSION |
||
POST /api/dms/objects/tags/{name}/state/{state}?query=<SQL> |
110 - OBJECT_TAG_CREATED (since 2021 Summer) |
||
DELETE /api/dms/objects/{objectId}/tags/{name} |
210 - OBJECT_TAG_DELETED (since 2021 Summer) |
||
POST /api/dms/objects/{objectId}/tags/{name}/state/{state} |
110 - OBJECT_TAG_CREATED (since 2021 Summer) |
||
POST /api/dms/objects/{objectId}/tags/{name}/state/{state}?overwrite=true |
310 - OBJECT_TAG_UPDATED (since 2021 Summer) |
- Called by Service
-
repository
service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "objects": [{ "properties": { "system:objectTypeId": { "value": "object" }, "label": { "value": "Label" }, "subentitaet": { "value": "Sub" }, "idn": { "value": "6754" }, "titel": { "value": "Titel" }, "medientyp": { "value": "Cool filename" } }, "contentStreams": [{ "cid": "cid_63apple", "mimeType": "application/pdf", "fileName" : "document01.pdf" }], "options": { "action": 101, "detail": "OBJECT_CREATED_WITH_CONTENT", "tenant": "tenant1" } }] }
- Example Predicate
-
Check if there is an object with binary content:
spel:contentStreams!=null
POST dms.request.objects.upsert.database-before
- Applies to enriched objects just before indexing during import or content/metadata/tag update.
- As of Version
-
2021 Autumn
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
This webhook can be triggered by
-
an object import,
-
an update of the content,
-
or a tag update.
The webhook receives the completed objects just before they are indexed. This means that the objects are already enriched with system properties and default values (wherever necessary), normalized and validated.
In version 2021 Autumn, if there are invalid objects, the entry point of this webhook type is not reached. A validation exception is thrown before.
As of version 2021 Winter, the following behavior is implemented:
-
Each object is still validated before the entry point of the webhook, but a validation exception is thrown after the webhook entry point. Thus, webhooks of this type can be triggered even in case of an invalid object.
-
Those objects contain the corresponding validation errors in their options (see example below). Hence, it is possible to, e.g., add required properties to the original request body subsequently via a webhook.
-
The object validation is performed again after the webhook. Only if there still are validation errors, a validation exception is thrown.
-
If multiple webhooks of this type are configured, a validation is performed between every triggered webhook and its succeeding webhook. Especially if objects have validation errors that were corrected by one webhook, the succeeding webhook gets the valid objects without validation errors in their options. If there are still invalid objects after the last webhook, then a validation exception is thrown.
As of version 2021 Winter: example validation errors that will be included in the 'options' of an invalid object{ ... "options": { "action": 300, "detail": "OBJECT_METADATA_CHANGED", "validationErrors": [ { "message": "Illegal property. An object of type 'appEmail:email' cannot have a property named 'decSingle'.", "serviceErrorCode": 2607 }, { "message": "A required property is missing. property='appEmail:from'", "serviceErrorCode": 2300 } ] ... } }
The predicate is applied to every single object in the list. The webhook is triggered for the whole object list as soon as one object satisfies the predicate.
The objects returned by the webhook are normalized and validated again before the interrupted processing chain will be continued. Hence, by means of this webhook, it is not possible to introduce invalid objects into the system. Furthermore, the object list in the original request body cannot be completely overwritten. The following rules apply:
-
It is not allowed to change the number of objects in the object list. An error will be thrown.
-
It is not allowed to modify the value of the
system:objectId
property. An error will be thrown. -
System properties that are set by the system as well as content stream properties cannot be changed. An error will be thrown.
-
In particular, the values for
system:lastModificationDate
(and system:creationDate in case of an import process) are set before and are not updated due to any manipulations via webhook. -
The expiration date cannot be removed or replaced by an earlier one.
-
If the value for
system:parentId
is changed, the new parent must be visible for the user who sent the original request. -
As of version 2022 Autumn: If the webhook removes a secondary object type (SOT) from an object, all properties that were provided by the SOT are automatically removed from that object as well.
-
As of version 2022 Autumn: If the webhook adds an SOT to an object, all properties provided by the SOT can be added to that object by the webhook as well. If those properties are not added by the webhook, they will be automatically added with their default values afterwards (if available).
-
Data in the options section are read-only for the webhook. Changes will be ignored, and the original values will be used. An error will not be thrown.
Specific rules for metadata updates (
action
has value300
):-
At the webhook entry point, all objects match exactly one of the following states:
-
None of the options
system:response
orvalidationErrors
are available. → The object is valid and successfully updated unless a webhook applies improper changes. -
The
validationErrors
option is available. → The object is currently invalid. The metadata update fails unless a webhook corrects the conflicts. -
As of 2023 Winter: The
system:response
option is available and itshttpStatusCode
value is >= 400. → The object’s update was requested within a batch request and has failed. There is NO way to resume its update process via webhook.
-
-
If tags are added by webhook during an import or metadata update, the values of
system:lastModificationDate
andsystem:traceId
are used forcreationDate
andtraceId
of these tags. -
If tags are added/updated by an import or metadata update and manipulated by webhook, the value of
system:lastModificationDate
is used for the tags' creationDate. -
If tags are added or updated during a pure tag operation,
creationDate
is set according to the original request. -
In general, any changes of the object applied by the webhook must match the action specified in the options section. Otherwise, the original request will result in an error. Consider the restrictions for these specific action codes in particular:
Value for 'action' Restriction 301
A webhook cannot change custom properties, retention properties or the
system:secondaryObjectTypeIds
property. As an exception, however, it is possible to add, update, or remove tags. Non-resistant tags are already removed from the object at this stage. A webhook can add resistant and non-resistant tags. All of them will be assigned to the final object. Further removals of non-resistant tags are not applied after the webhook.110/210/310
Only changes to the
system:tags
property matching the individual action are allowed.
Considering the action code, the webhook might be allowed to change tags. In the audit trail, the tagging-related entry will be the same if the tag modification was specified in the original request or by means of the webhook, e.g.:
-
If an update adds a tag and a webhook removes this tag within the same update request, no audit entries are created.
-
If an update adds a tag and a webhook changes the state of this tag within the same update request, only one audit entry (OBJECT_TAG_CREATED) is created.
-
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests and Action Codes/History Codes
-
100 - OBJECT_CREATED
101 - OBJECT_CREATED_WITH_CONTENT300 - OBJECT_METADATA_CHANGED
POST /api/dms/objects/{objectId}
(multipart) (as of 2024 Spring)300 - OBJECT_METADATA_CHANGED
302 - OBJECT_METADATA_DOCUMENT_CHANGED300 - OBJECT_METADATA_CHANGED
-
In a batch update, it is possible that processing is possible for some objects and for others not due to different reasons (see option
system:response
described in the endpointPATCH /api/dms/objects
). -
During the update processing, objects always have the same action value, regardless of whether they are processable or not. Consider the action value to decide what should be done with the objects.
-
Successful and failed processing can be distinguished by the option
system:response
of each individual DMS object in the batch.
301 - OBJECT_DOCUMENT_CHANGED
DELETE /api/dms/objects/{objectId}/contents/file
(as of 2023 Summer)201 - OBJECT_CONTENT_DELETED
POST /api/dms/objects/{objectId}/versions/{versionNr}/actions/restore
(as of 2022 Spring)325 - OBJECT_RESTORED_FROM_VERSION
110 - OBJECT_TAG_CREATED (since 2021 Summer)
310 - OBJECT_TAG_UPDATED (since 2021 Summer)210 - OBJECT_TAG_DELETED (since 2021 Summer)
110 - OBJECT_TAG_CREATED (since 2021 Summer)
310 - OBJECT_TAG_UPDATED (since 2021 Summer)
-
- Called by Service
-
registry
service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "objects" : [ { "properties" : { "system:objectId" : { "value" : "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId" : { "value" : "system:document" }, "system:objectTypeId" : { "value" : "smallDocument" }, "system:createdBy" : { "value" : "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate" : { "value" : "2021-07-22T15:30:05.020Z" }, "system:lastModifiedBy" : { "value" : "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate" : { "value" : "2021-07-22T15:30:21.520Z" }, "system:versionNumber" : { "value" : 2 }, "system:tenant" : { "value" : "tenant1" }, "system:traceId" : { "value" : "97a35859dbb4c435" }, "Name" : { "value" : "exampledocument-without-content after update" } }, "options" : { "action" : 300, "detail" : "OBJECT_METADATA_CHANGED", "tenant" : "tenant1", "user" : "root", "authorities" : [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_TENANT_ADMIN" ], "inputVersion" : { "properties" : { "system:objectId" : { "value" : "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:objectTypeId" : { "value" : "smallDocument" }, "Name" : { "value" : "exampledocument-without-content after update" } } }, "currentVersion" : { "properties" : { "system:objectId" : { "value" : "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId" : { "value" : "system:document" }, "system:objectTypeId" : { "value" : "smallDocument" }, "system:createdBy" : { "value" : "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate" : { "value" : "2021-07-22T15:30:05.020Z" }, "system:lastModifiedBy" : { "value" : "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate" : { "value" : "2021-07-22T15:30:21.520Z" }, "system:versionNumber" : { "value" : 1 }, "system:tenant" : { "value" : "tenant1" }, "system:traceId" : { "value" : "672c49b7070ebd21" }, "Name" : { "value" : "exampledocument-without-content" } } } } } ] }
- Example Predicate
-
Check if the object type is appEmail:email:
spel:'appEmail:email'.equals(properties['system:objectTypeId']['value'])
POST dms.request.search
- Applies to the search query parameter after calling a search-related endpoint.
- As of Version
-
2019 Winter
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
The search endpoint and any endpoint containing a search request can trigger this webhook. Check the value of the incoming search query parameter.
The webhook accepts a body containing an object that is modified (if necessary) and returned.
The predicate is applied to the search query parameter.
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests
- Called by Service
-
api
gateway service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "query": { "statement": "select * from appEmail:email where appEmail:bcc is not null", "skipCount": 0, "maxItems": 10 }, "options": { "tenant": "default" } }
- Example Predicate
-
Check whether the query statement contains the string
bcc
:spel:query!=null && query['statement']!=null && query['statement'].toLowerCase().contains('bcc'))
POST dms.request.objects.contents
- Can be triggered by a request for retrieval of a binary content file or a rendition. Applies to the corresponding DMS object as stored in the system including properties, contentStreams and options sections.
- As of Version
-
2022 Winter
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
A webhook of this type can be triggered by a request for retrieval of a binary content file or a rendition.
The original body that is available at the webhook entry point is an object list containing the object for which the content/rendition and the corresponding options properties should be retrieved.
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects. The following responses are expected:
Return HTTP status code 200 to continue with the content/rendition retrieval. Changes in the body introduced within the webhook are ignored. Return any HTTP status code indicating an error (400…599) and a properly formatted error structure in the body to prohibit the content/rendition retrieval. Your error structure will finally be presented as response of the originally called endpoint with HTTP status code 404. If your webhook returns an error structure that does not match the expected format, the content retrieval fails with HTTP status code 422. The webhook error is wrapped as plain text.
- Affected API Requests and Action Codes/History Codes
-
400 - DOCUMENT_ACCESSED
402 - RENDITION_ACCESSED
- Called by Service
-
api
gateway service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "objects": [ { "properties": { "system:objectId": { "value": "27602f73-7e3f-4013-babb-10a4dc042ff0" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:createdBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate": { "value": "2021-05-22T00:09:05.400Z" }, "system:lastModifiedBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:lastModificationDate": { "value": "2021-05-22T00:09:05.400Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "default" }, "system:traceId": { "value": "f08d5290e5a81753" }, "testString": { "value": "test import" } }, "contentStreams": [ { "contentStreamId": "EBC1760B-BA91-11EB-8277-D1DE73C78E3D", "archivePath": "default/DOCUMENT/BC/17/6/", "length": 431397, "mimeType": "message/rfc822", "fileName": "content.eml", "digest": "11857B6FAD61E41AFB3E7398BA1BA4BFB6B0A5422762FF41A0907BC0BFF7748F", "repositoryId": "repo242" } ], "options": { "action": 400, "detail": "DOCUMENT_ACCESSED", "tenant": "default", "system:hook:type": "dms.request.objects.contents", "system:request:method": "GET" } } ] }
- Example Predicate
-
The configured webhook will be triggered for each retrieval of a PDF rendition.
spel:options!=null && options['action']>402 && "2".equals(''+options['subaction'])
POST dms.request.objects.delete
- Applies to the active version of the object or the specific version that is to be deleted.
- As of Version
-
2021 Summer
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
The webhook is triggered if the object or version to delete exists and is deletable, i.e., if the user has sufficient permissions and if the object is not a non-empty folder.
The body contains an object list with the active version or the version to delete of the object(s).
The predicate is applied to every single object in the list. The webhook is triggered for the whole object list as soon as one object satisfies the predicate.
Changing Deletion to a Metadata UpdateAs of 2023 Spring, it is possible to turn a deletion request into a metadata update via webhook. The following rules apply:
-
The webhook has to change the options parameter action from 200 (stands for deletion) to 300 (stands for metadata update). If the webhook is triggered by a batch deletion request, the action has to be adjusted for all objects in the list.
-
The webhook can additionally change values of the objects' metadata properties.
-
In the audit trail, an entry with 300 OBJECT_METADATA_CHANGED will be created instead of the deletion audit entries 202 OBJECT_FLAGGED_FOR_DELETE and 200 OBJECT_DELETED.
-
If further webhooks of the same type are configured, they get the modified objects list in the body as usual, but they are not allowed to change the action value back to 200.
-
With the modified object list, a POST update with
waitForSearchConsistency=true
is internally performed. -
The webhook entry point can only be reached with a
delete
permission on the objects. There is no additional check for awrite
permission. -
The processing chain after the last webhook of type
dms.request.objects.delete
is now the metadata update chain. Thus, system hook entry points of other types later in the deletion procession chain are not reached anymore (e.g., webhookdms.response.objects.delete
or AMQP hookdms.response.delete
). Instead, the webhook entry points of the metadata update chain are passed and such webhooks can be triggered. -
It is not possible to change the deletion of a single version (action 220) into a metadata update.
-
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests and Action Codes/History Codes
-
200 - OBJECT_DELETED
220 - VERSION_DELETED
- Called by Service
-
api
gateway service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "objects": [ { "properties": { "system:traceId": { "value": "adcb4edd823fca4c" }, "system:objectTypeId": { "value": "document" }, "system:versionNumber": { "value": 3 }, "testString": { "value": "new test import" }, "system:createdBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate": { "value": "2020-07-23T13:12:34.370Z" }, "system:lastModificationDate": { "value": "2020-07-23T13:12:35.910Z" }, "system:baseTypeId": { "value": "system:document" }, "system:tenant": { "value": "default" }, "system:lastModifiedBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:objectId": { "value": "9ce1ab26-1a6b-4bc2-aa4b-2b099bff7468" } }, "contentStreams": [ { "contentStreamId": "4710AB82-C1B4-11EA-B395-49C30F249D00", "archivePath": "default/DOCUMENT/71/0A/B/", "length": 431397, "mimeType": "application/octet-stream", "digest": "11857B6FAD61E41AFB3E7398BA1BA4BFB6B0A5422762FF41A0907BC0BFF7748F", "repositoryId": "repo252" } ], "options": { "action": 200, "detail": "OBJECT_DELETED", "tenant": "default", "user": "root", "authorities": [ "ACL_ADMIN", "YUUVIS_TENANT_ADMIN", "uma_authorization" ] } } ] }
- Example Predicate
-
Check if the object type is
appEmail:email
:spel:'appEmail:email'.equals(properties['system:objectTypeId']['value'])
POST dms.response.objects
- Applies directly before the return whenever objects lists are part of the HTTP response: Search queries, Object imports/retrievals/updates, …
- As of Version
-
2019 Winter
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
Delivers a list of predicate-matching objects to a secondary recipient.
Any request returning an object list triggers this webhook directly before the return. Applies whenever object lists are part of the HTTP response:
-
Search queries
-
Object imports
-
Object GETs
-
Object metadata updates
-
Moving content
For example, properties can be extracted to hide them for individual users.
The body contains the object list that will be returned. In most cases, this list is of length 1. Only for the search endpoint, there are also numItems, hasMoreItems and totalNumItems. The body is modified by the webhook and returned afterwards.
The predicate is applied to every single object in the list. The webhook is triggered for the whole object list as soon as one object satisfies the predicate.
-
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests and Action Codes/History Codes
-
100 - OBJECT_CREATED
101 - OBJECT_CREATED_WITH_CONTENT (since 2021 Summer)300 - OBJECT_METADATA_CHANGED
POST /api/dms/objects/{objectId}
(multipart) (as of 2024 Spring)300 - OBJECT_METADATA_CHANGED
302 - OBJECT_METADATA_DOCUMENT_CHANGED300 - OBJECT_METADATA_CHANGED
-
In a batch update, processing may be possible for some objects and not for others for various reasons (see option
system:response
described in the endpointPATCH /api/dms/objects
). -
During the update processing, objects always have the same action value, regardless of whether they are processable or not. Consider the action value to decide what should be done with the objects.
-
Successful and failed processing can be distinguished by the option
system:response
of each individual DMS object in the batch.
301 - OBJECT_DOCUMENT_CHANGED (since 2021 Summer)
DELETE /api/dms/objects/{objectId}/contents/file
(as of 2023 Summer)201 - OBJECT_CONTENT_DELETED
POST /api/dms/objects/{objectId}/versions/{versionNr}/actions/restore
(as of 2022 Spring)325 - OBJECT_RESTORED_FROM_VERSION
110 - OBJECT_TAG_CREATED
310 - OBJECT_TAG_UPDATED210 - OBJECT_TAG_DELETED
110 - OBJECT_TAG_CREATED
310 - OBJECT_TAG_UPDATED
303 - OBJECT_UPDATE_CONTENT_MOVED
-
-
-
-
DELETE /api/dms/objects/{objectId}
(since 2021 summer)200 - OBJECT_DELETED (the delete request was successful)
201 - OBJECT_CONTENT_DELETED (the object is flagged for delete and the content and the object in the SQL database are deleted, but the deletion in Elasticsearch failed)
202 - OBJECT_FLAGGED_FOR_DELETE (the object is flagged for deletion, which makes it invisible, but it is not actually deleted. If asynchronous deletion is activated in the service configuration, this is the only possible action.)200 - OBJECT_DELETED (the delete request was successful. All deletable objects in the batch are deleted.)
201 - OBJECT_CONTENT_DELETED (the deletable objects in the batch are flagged for deletion, their contents are deleted and their representations in the SQL database are deleted, but the deletion in Elasticsearch failed)
202 - OBJECT_FLAGGED_FOR_DELETE (the deletable objects in the batch are flagged for deletion, which makes them invisible, but they are not actually deleted. If asynchronous deletion is activated in the service configuration, this is the only possible action.)-
In a batch deletion, deletion may be possible for some objects and not for others for various reasons (see option
system:deletionResult
described in the endpointDELETE /api/dms/objects
). -
During the deletion processing, objects always have the same action value, no matter if they are deletable or not. Consider the action value to decide what should be done with the objects.
-
Successful and failed deletion processing can be distinguished by the option
system:deletionResult
of each individual DMS object in the batch.
DELETE /api/dms/objects/{objectId}/versions/{versionNr}
(since 2021 summer)220 - VERSION_DELETED
-
- Called by Service
-
api
gateway service,repository
service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "objects" : [ { "properties" : { "appEmail:subject" : { "value" : "any subject" }, "appEmail:to" : { "value" : [ "user1@example.de" ] } } }, { "properties" : { "appEmail:subject" : { "value" : "another subject" }, "appEmail:to" : { "value" : [ "user2@example.de" ] } } } ], "numItems" : 2, "hasMoreItems" : true, "totalNumItems" : 356 }
- Example Predicate
-
Check if the object has the property
appEmail:bcc
.spel:properties['appEmail:bcc']!=null
POST dms.response.objects.insert
- Import requests trigger this webhook after successful import directly before the return.
- As of Version
-
2021 Summer
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
Import requests trigger this webhook after successful import directly before the return.
The body contains the object list that will be returned. The body is modified by the webhook and returned afterwards.
The predicate is applied to every single object in the list. The webhook is triggered for the whole object list as soon as one object satisfies the predicate.
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests
- Action Codes - History Codes
-
101 - OBJECT_CREATED_WITH_CONTENT
100 - OBJECT_CREATED - Called by Service
-
repository
service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "objects": [ { "properties": { "system:objectId": { "value": "27602f73-7e3f-4013-babb-10a4dc042ff0" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:createdBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate": { "value": "2021-05-22T00:09:05.400Z" }, "system:lastModifiedBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:lastModificationDate": { "value": "2021-05-22T00:09:05.400Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "default" }, "system:traceId": { "value": "f08d5290e5a81753" }, "testString": { "value": "test import" } }, "contentStreams": [ { "contentStreamId": "EBC1760B-BA91-11EB-8277-D1DE73C78E3D", "archivePath": "default/DOCUMENT/BC/17/6/", "length": 431397, "mimeType": "message/rfc822", "fileName": "content.eml", "digest": "11857B6FAD61E41AFB3E7398BA1BA4BFB6B0A5422762FF41A0907BC0BFF7748F", "repositoryId": "repo242" } ], "options": { "action": 101 } } ] }
- Example Predicate
-
Check if the object type is
appEmail:email
:spel:'appEmail:email'.equals(properties['system:objectTypeId']['value'])
Check if at least one imported object has content:
spel:options['action']==101
POST dms.response.objects.update
- Update requests trigger this webhook after successful update directly before the return. This concerns content updates, metadata updates and tag updates.
- As of Version
-
2021 Summer
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
Update requests trigger this webhook after successful update directly before the return. This concerns content updates, metadata updates and tag updates.
The body contains the object list that will be returned. The body is modified by the webhook and returned afterwards.
The predicate is applied to the single object in the list.
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests and Action Codes/History Codes
-
300 - OBJECT_METADATA_CHANGED
POST /api/dms/objects/{objectId}
(multipart) (as of 2024 Spring)300 - OBJECT_METADATA_CHANGED
302 - OBJECT_METADATA_DOCUMENT_CHANGED300 - OBJECT_METADATA_CHANGED
-
In a batch update, processing may be possible for some objects and not for others for various reasons (see option
system:response
described in the endpointPATCH /api/dms/objects
). -
During the update processing, objects always have the same action value, regardless of whether they are processable or not. Consider the action value to decide what should be done with the objects.
-
Successful and failed processing can be distinguished by the option
system:response
of each individual DMS object in the batch.
301 - OBJECT_DOCUMENT_CHANGED
DELETE /api/dms/objects/{objectId}/contents/file
(as of 2023 Summer)201 - OBJECT_CONTENT_DELETED
POST /api/dms/objects/{objectId}/versions/{versionNr}/actions/restore
(as of 2022 Spring)325 - OBJECT_RESTORED_FROM_VERSION
110 - OBJECT_TAG_CREATED
310 - OBJECT_TAG_UPDATED210 - OBJECT_TAG_DELETED
110 - OBJECT_TAG_CREATED
310 - OBJECT_TAG_UPDATED
-
- Called by Service
-
api
gateway service,repository
service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "objects": [ { "properties": { "system:objectId": { "value": "d7bd24b0-f8aa-49dc-a698-5513763d347a" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:createdBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate": { "value": "2021-05-21T14:16:50.010Z" }, "system:lastModifiedBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:lastModificationDate": { "value": "2021-05-22T00:35:30.180Z" }, "system:versionNumber": { "value": 3 }, "system:tenant": { "value": "default" }, "system:traceId": { "value": "981f85ee55debc7d" }, "testString": { "value": "new test import" } }, "contentStreams": [ { "contentStreamId": "99F9EE58-BA38-11EB-A4CA-43B80C415ED8", "archivePath": "default/DOCUMENT/9F/9E/E/", "length": 431397, "mimeType": "message/rfc822", "fileName": "test.txt", "digest": "11857B6FAD61E41AFB3E7398BA1BA4BFB6B0A5422762FF41A0907BC0BFF7748F", "repositoryId": "repo242" } ], "options": { "action": 300, "action_bckp": 300, "detail": "OBJECT_METADATA_CHANGED", "previousVersion": { "properties": { "system:traceId": { "value": "e48801d4a97cb6ff" }, "system:objectTypeId": { "value": "document" }, "system:versionNumber": { "value": 2 }, "testString": { "value": "test import" }, "system:createdBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate": { "value": "2021-05-21T14:16:50.010Z" }, "system:lastModificationDate": { "value": "2021-05-21T14:17:27.880Z" }, "system:baseTypeId": { "value": "system:document" }, "system:tenant": { "value": "default" }, "system:lastModifiedBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:objectId": { "value": "d7bd24b0-f8aa-49dc-a698-5513763d347a" } }, "contentStreams": [ { "contentStreamId": "99F9EE58-BA38-11EB-A4CA-43B80C415ED8", "archivePath": "default/DOCUMENT/9F/9E/E/", "length": 431397, "mimeType": "message/rfc822", "fileName": "test.txt", "digest": "11857B6FAD61E41AFB3E7398BA1BA4BFB6B0A5422762FF41A0907BC0BFF7748F", "repositoryId": "repo242" } ] }, "tenant": "default", "user": "root", "authorities": [ "ACL_ADMIN", "YUUVIS_TENANT_ADMIN", "uma_authorization" ] } } ] }
- Example Predicate
-
Check if the update is a metadata update:
spel:options!=null && options['action']==300
Check if the update is a tag update:
spel:options!=null && T(java.util.List).of(110,210,310).contains(options['action'])
POST dms.response.objects.delete
- Triggered directly after the successful deletion of an object. Applies tp the active version of the object or the specific version that is deleted.
- As of Version
-
2020 Autumn
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
This webhook is triggered directly after the successful deletion of a document and after the equivalent AMQP hook, and can for instance inform other systems.
The predicate is applied to every single object in the list. The webhook is triggered for the whole object list as soon as one object satisfies the predicate.
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests and Action Codes/History Codes
-
200 - OBJECT_DELETED (the delete request was successful)
201 - OBJECT_CONTENT_DELETED (the object is flagged for delete and the content and the object in the SQL database is deleted, but the deletion in Elasticsearch failed)
202 - OBJECT_FLAGGED_FOR_DELETE (the object is flagged for deletion, which makes it invisible, but it is not actually deleted. If asynchronous deletion is activated in the service configuration, this is the only possible action.)
200 - OBJECT_DELETED (the delete request was successful. all deletable objects in the batch are deleted)
201 - OBJECT_CONTENT_DELETED (the deletable objects in the batch are flagged for deletion, their contents are deleted and their representations in the SQL database are deleted, but the deletion in Elasticsearch failed)
202 - OBJECT_FLAGGED_FOR_DELETE (the deletable objects in the batch are flagged for deletion, which makes them invisible, but they are not actually deleted. If asynchronous deletion is activated in the service configuration, this is the only possible action.)
-
In a batch deletion, it is possible that some objects are deletable and others are not due to different reasons (see option
system:deletionResult
described in the endpointDELETE /api/dms/objects
). -
During the deletion processing, objects always have the same action value, no matter if they are deletable or not. Consider the action value to decide what should be done with the objects.
-
Successful and failed deletion processing can be distinguished by the option
system:deletionResult
of each individual DMS object in the batch.
220 - VERSION_DELETED (since 2021 Summer)
-
- Called by Service
-
api
gateway service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
{ "properties": { "system:traceId": { "value": "0000000000000000" }, "system:objectTypeId": { "value": "appTable:order" }, "appTable:ordernumber": { "value": 1 }, "system:versionNumber": { "value": 1 }, "appTable:items": { "value": [ [ "fruits", 10 ], [ "milk", 1 ], [ "sweeties", 5 ] ] }, "system:creationDate": { "value": "2020-09-17T14:17:31.480Z" }, "system:lastModificationDate": { "value": "2020-09-17T14:17:31.480Z" }, "system:baseTypeId": { "value": "system:document" }, "system:tenant": { "value": "default" }, "appTable:customername": { "value": "customer1" }, "system:createdBy": { "value": "111c226c-3a44-5e66-7777-8d999a0000e1" }, "system:lastModifiedBy": { "value": "222c222c-2c22-2e22-2222-2d222d2222e2" }, "system:objectId": { "value": "f4efc4e4-1234-4321-4f74-4de4ff34f744" } }, "contentStreams": [ { "contentStreamId": "0AB98765-CDEF-4321-ABCD-098EF76AB543", "archivePath": "default/DOCUMENT/12/34/5/", "length": 9000003, "mimeType": "image/jpg", "digest": "1234567812345678123456781234567812345678123456781234567812345678", "repositoryId": "repo002" } ], "options": { "action": 200, "detail": "OBJECT_DELETED" } }
- Example Predicate
-
Check if the object type is
appTable:order
:spel:'appTable:order'.equals(options['currentVersion']['properties']['system:objectTypeId']['value'])
POST dms.response.objects.search
- Search requests trigger this webhook if they were successful directly before the return. Applies to the search result entries.
- As of Version
-
2021 Summer
- HTTP Method
-
POST
- Response Format
-
JSON
- Description
-
Search requests trigger this webhook if they were successful directly before the return.
The body contains the search result that will be returned.
The predicate is applied to every single object in the search result. The webhook is triggered for the whole search result as soon as one object satisfies the predicate.
- Requirements for External Endpoint
-
The target URL must be a POST endpoint accepting and returning a list of objects.
- Affected API Requests
- Action Codes - History Codes
-
-
- Called by Service
-
api
gateway service - Header
-
Authorization-Header
X-B3-TraceId
- Example Request Body
-
for the search query
select system:objectTypeId, system:objectId, system:creationDate from document
{ "objects" : [ { "properties" : { "system:objectTypeId" : { "value" : "document" }, "system:objectId" : { "value" : "2be7b709-745a-4c0c-809e-512f9850876b" }, "system:creationDate" : { "value" : "2020-08-21T07:09:04.590Z" } } }, { "properties" : { "system:objectTypeId" : { "value" : "document" }, "system:objectId" : { "value" : "9ce1ab26-1a6b-4bc2-aa4b-2b099bff7468" }, "system:creationDate" : { "value" : "2020-07-23T13:12:34.370Z" } } }, { "properties" : { "system:objectTypeId" : { "value" : "document" }, "system:objectId" : { "value" : "436f9b7d-05f3-49d5-be31-2d7225ce00f7" }, "system:creationDate" : { "value" : "2020-07-21T11:27:31.410Z" } } } ], "numItems" : 3, "hasMoreItems" : true, "totalNumItems" : 208 }
- Example Predicate
-
Check if at least one object of the result list contains the property
appAcl:acl
:spel:properties['appAcl:acl']!=null
Configuring Webhooks
As a type of system hooks, webhooks are configured in the \service-manager\config\system\systemHookConfiguration.json
configuration file within the service manager in JSON format. Any changes to the system hook configuration will not apply until the affected services have been restarted.
The timeouts that limit the process time of webhooks in order to avoid system bottlenecks are configured in the application-prod.yml
configuration file.
If multiple webhooks are registered for the same webhook type, the predicate is applied to the original predicate target for each of them and in the order of definition. Imagine an example scenario with two registered webhooks of the type dms.response.objects.search
:
{
"enable": true,
"predicate": "spel:true",
"type": "dms.response.objects.search",
"url": <suitable endpoint removing the property 'appEmail:bcc'>,
"useDiscovery": true
},
{
"enable": true,
"predicate": "spel:properties['appEmail:bcc']!=null",
"type": "dms.response.objects.search",
"url": <any suitable endpoint>,
"useDiscovery": true
}
If objects in a search result have the appEmail:bcc
property and the first webhook removes this property from the objects, the predicate of the second webhook still matches.
The same behavior holds for the webhook type dms.response.objects and one of its sub-webhook types dms.response.objects.*
:
{
"enable": true,
"predicate": "spel:true",
"type": "dms.response.objects",
"url": <suitable endpoint removing the property 'appEmail:bcc'>,
"useDiscovery": true
},
{
"enable": true,
"predicate": "spel:properties['appEmail:bcc']!=null",
"type": "dms.response.objects.search",
"url": <any suitable endpoint>,
"useDiscovery": true
}
Loggers for Webhooks
As of version 2022 Spring, the input and output data for each webhook can be monitored via loggers.
The logging level can be specified
-
for all webhooks, e.g.,
os.dev.webhooks=DEBUG
, or -
for individual webhook types, e.g.,
os.dev.webhooks.dms.request.search=DEBUG
.
The logging configuration for each webhook has to be read by the service that calls the webhook. For the individual webhook types, different services are responsible. Thus, please ensure that your webhook logging configuration is defined in a configuration file that is read by its calling service. In order to apply the configuration changes, each calling service has to be refreshed or restarted.
Depending on the logging level, the following details are logged:
Logging Level | Logged Information |
---|---|
|
Only enabled webhooks are considered. The following data are logged:
|
|
For enabled webhooks, the same information is logged as is the case for the Disabled webhooks are listed together with the information: |
2.9.4. AMQP Hooks
System Hooks, that allow for messaging triggered by function calls under specified conditions.
With an AMQP Hook, messages are sent to a configured messaging system using Advanced Message Queuing Protocol 1.0 (AMPQ). Where and when these messages are sent is defined in the System Hook configuration. Any changes to the System Hook configuration will not apply until the affected services have been restarted.
The AMQP Hooks allow for asynchronous reactions to events like object creation, update or deletion. There are different types of AMQP Hooks available, each of them specialized for selected function calls. The messages contain the object metadata which is the target of the function call triggering the AMQP Hook. The action code is included in the message as well as the history code that is added to the audit trail. The AMQP Hook can be triggered by any endpoint that induced the characteristic history codes of the AMQP Hook.
Types of AMQP Hooks
dms.response.delete
-Object deletion events can trigger this AMQP Hook with the corresponding object properties in its body.
- As of Version
-
2020 Autumn
- Description
-
Object deletion events can trigger this AMQP Hook with the corresponding object properties in its body.
- Example Predicate
-
-
reaction to every object deletion:
spel:true
-
reaction to every object deletion of type document:
spel:properties['system:objectTypeId']['value']=='document'
-
reaction to every failed deletion of objects that were flagged for deletion:
spel:options['action']==202
-
- Action Codes - History Codes
-
200 - OBJECT_DELETED
202 - OBJECT_FLAGGED_FOR_DELETE - Example Message
-
{ "objects": [ { "properties": { "system:objectId": { "value": "333c226c-3a44-5e66-7777-8d999a0000e1" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:createdBy": { "value": "111c226c-3a44-5e66-7777-8d999a0000e1" }, "system:creationDate": { "value": "2020-09-16T16:57:40.780Z" }, "system:lastModifiedBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:lastModificationDate": { "value": "2020-09-16T16:57:40.780Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "default" }, "system:traceId": { "value": "e686f806ed44f37d" }, "Name": { "value": "test.eml" } }, "contentStreams": [ { "contentStreamId": "0AB98765-CDEF-4321-ABCD-098EF76AB543", "archivePath": "default/DOCUMENT/32/15/7/", "length": 82683, "mimeType": "message/rfc822", "fileName": "test.eml", "digest": "2713BB70F1B3F8F556D2661286A5D45157EB723A815E1066E50F1808228075F7", "range": "47578-68248,115827-136497,184076-204746,252320-272989", "repositoryId": "repo252" } ], "options": { "action": 200, "detail": "OBJECT_DELETED" } } ] }
dms.response.insert
-Object creation events can trigger this AMQP Hook with the corresponding object properties in its body.
- As of Version
-
2019 Winter
- Description
-
Object creation events can trigger this AMQP Hook with the corresponding object properties in its body.
- Example Predicate
-
-
reaction to every object creation:
spel:true
-
reaction to every object creation having a content range attribute:
spel:contentStreams[0]['range'].length() > 0
-
reaction to every object creation without content:
spel:options['action']=100
-
- Action Codes - History Codes
-
101 - OBJECT_CREATED_WITH_CONTENT
100 - OBJECT_CREATED - Example Message
-
{ "objects": [ { "properties": { "system:objectId": { "value": "333c226c-3a44-5e66-7777-8d999a0000e1" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:createdBy": { "value": "111c226c-3a44-5e66-7777-8d999a0000e1" }, "system:creationDate": { "value": "2020-09-16T16:57:40.780Z" }, "system:lastModifiedBy": { "value": "111c226c-3a44-5e66-7777-8d999a0000e5" }, "system:lastModificationDate": { "value": "2020-09-16T16:57:40.780Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "default" }, "system:traceId": { "value": "1234567887654321" }, "Name": { "value": "test.eml" } }, "contentStreams": [ { "contentStreamId": "0AB98765-CDEF-4321-ABCD-098EF76AB543", "archivePath": "default/DOCUMENT/32/15/7/", "length": 82683, "mimeType": "message/rfc822", "fileName": "test.eml", "digest": "12345678123456781234567812345678123456781234567812345678", "range": "1234-12345,123456-123458,123489-234567,245678-345678", "repositoryId": "repo252" } ], "options": { "action": 101, "detail": "OBJECT_CREATED_WITH_CONTENT" } } ] }
dms.response.update
- Object update events and tag operations can trigger this AMQP Hook with the corresponding object properties in its body.
- As of Version
-
2020 Autumn
- Description
-
Object update events and tag operations can trigger this AMQP Hook with the corresponding object properties in its body.
- Example Predicate
-
-
reaction to every object update:
spel:true
-
reaction to every tag creation:
spel:options['action']==110
-
reaction to every tag deletion:
spel:options['action']==210
-
reaction to every metadata update:
spel:options['action']==300
-
reaction to every content update:
spel:options['action']==301
-
- Action Codes - History Codes
-
300 - OBJECT_METADATA_CHANGED
301 - OBJECT_DOCUMENT_CHANGED
303 - OBJECT_UPDATE_CONTENT_MOVED
110 - OBJECT_TAG_CREATED
310 - OBJECT_TAG_UPDATED
210 - OBJECT_TAG_DELETED - Example Message
-
To the object a tag
ocr
is added.In the
options
section, thepreviousVersion
attribute contains the previous document before the update.{ "objects": [ { "properties": { "system:objectId": { "value": "333c226c-3a44-5e66-7777-8d999a0000e1" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:createdBy": { "value": "111c226c-3a44-5e66-7777-8d999a0000e1" }, "system:creationDate": { "value": "2020-09-16T16:57:40.780Z" }, "system:lastModifiedBy": { "value": "111c226c-3a44-5e66-7777-8d999a0000e5" }, "system:lastModificationDate": { "value": "2020-09-16T16:57:40.780Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "default" }, "system:traceId": { "value": "e686f806ed44f37d" }, "Name": { "value": "test.eml" }, "system:tags": { "value": [["ocr", 1, "2020-09-16T16:57:40.780Z", "ce03f1c20308d77d" ]] } }, "contentStreams": [ { "contentStreamId": "1D2AD7BA-F82B-11EA-A5EA-7FE7FFB009F6", "archivePath": "default/DOCUMENT/32/15/7/", "length": 82683, "mimeType": "message/rfc822", "fileName": "test.eml", "digest": "12345678123456781234567812345678123456781234567812345678", "range": "1234-12345,123456-123458,123489-234567,245678-345678", "repositoryId": "repo252" } ], "options": { "action": 110, "detail": "OBJECT_TAG_CREATED", "previousVersion" : { "properties": { "system:objectId": { "value": "2b7a3b0a-3038-433e-96bd-493d7702b510" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:createdBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate": { "value": "2020-09-16T16:57:40.780Z" }, "system:lastModifiedBy": { "value": "111c226c-3a44-5e66-7777-8d999a0000e5" }, "system:lastModificationDate": { "value": "2020-09-16T16:57:40.780Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "default" }, "system:traceId": { "value": "1234567887654321" }, "Name": { "value": "test.eml" } }, "contentStreams": [{ "contentStreamId": "0AB98765-CDEF-4321-ABCD-098EF76AB543", "archivePath": "default/DOCUMENT/D2/AD/7/", "length": 82683, "mimeType": "message/rfc822", "fileName": "test.eml", "digest": "12345678123456781234567812345678123456781234567812345678", "range": "1234-12345,123456-123458,123489-234567,245678-345678", "repositoryId": "repo252" }] } } } ]}
Configuring AMQP Hooks
As a type of system hooks, AMQP Hooks are configured in the \service-manager\config\system\systemHookConfiguration.json
configuration file within the service manager in JSON format. Any changes to the system hook configuration will not apply until the affected services have been restarted.
2.9.5. Interceptors
Intervening a running process at a certain position and redirecting the process flow in order to include project-specific processing steps.
The interceptors allow for project-specific extensions of the yuuvis® Momentum standard process flows. The running process flow can be redirected by a condition set on the processed object that has to be specified in the interceptor definition. Whenever the process flow meets the condition, the project-specific process extension is included for the currently processed object at this position of the process flow. Thus, the alternative process can entirely replace the standard one from this position on or resume the standard process at a specified position.
Interceptor Configuration
The condition for the intervention of the process flow is defined in the interceptor configuration file interceptorConfiguration.json
.
The following parameters are available for the interceptor configuration:
Parameter | Type | Required | Description |
---|---|---|---|
|
String |
yes |
The type of the interceptor. It defines the position in the process flow where the interceptor can step in. |
|
String |
yes |
The condition that triggers the redirection of the process flow in order to include the project-specific process extension. The string can provide the condition either in Spring Expression Language (SpEL) or Javascript. Thus, the string always has to start with a prefix spel: for SpEL or js: for Javascript. |
|
String |
yes |
HTTP address of an external endpoint defining the project-specific process extension. Dynamic components (properties of the processed object) can be included in curly brackets. |
|
Boolean |
no |
Decides whether to resolve the url string at the Discovery-Service or not. If not specified, a default value is set. |
Interceptor Types
There are different types of interceptors available that interrupt the process flow at different positions. Their take-off points are at the API gateway or the repository
service. To activate a new interceptor configuration, the corresponding service has to be restarted.
Interceptor type | Evaluation target of the predicate | Interceptor input data | Description | Restart Service |
---|---|---|---|---|
|
API DMS object in JSON format derived from given objectId |
objectId |
Manipulation of the binary content of the return statement by a project-specific service. |
|
|
Structure of the specific class |
Search query object |
Manipulation of the search query parameter and the search result. |
|
|
First API DMS object in the list in JSON format that is passed to the corresponding update endpoint |
Updated metadata and metadata of current version |
Manipulation of the update properties that will be applied to a DMS object. |
|
|
All objects of the objects list in the data part of the multipart body after enrichment. |
a multipart request body |
The take-off point of the interceptor is after the |
|
dms.request.objects.upsert.database-before
- Details and Examples
- As of Version
-
2020 Winter
- HTTP Method
-
POST
- Response Format
-
JSON
- Predicate
-
The
predicate
is applied on all objects of the objects list in the data part of the multipart body after enrichment. If at least one object matches, the interceptor is called. - Description
-
It can be triggered by
-
an object import,
-
an update of the content or
-
an update of the metadata.
The take-off point of the interceptor is after the
repository
service. The initial request body is already normalized, validated and enriched with content stream properties as can be seen in the examples provided below.The enriched multipart request body is taken by the interceptor. It always contains a data part, that contains an objects list with the metadata of the affected objects. For each object, the options section contains the action parameter that specifies the type of the call in an action code.
The
predicate
is applied to every single object in the list. The interceptor is triggered for the entire object list as soon as one object meets thepredicate
.Within the interceptor, any user-defined operation can be executed on the corresponding metadata by calling the external endpoint specified as url in the interceptor configuration. Afterwards, the modified multipart has to be routed back to continue the regular process at a suitable point.
If the interceptor should continue the regular process exactly at the take-off point, pass the multipart to
http://registry/api/dms/objects
. -
- Requirements for external endpoint
-
The target URL must be a POST endpoint accepting a multipart request body and returning a list of objects as JSON.
- Affected API Requests
-
-
POST /api/dms/objects
-
POST /api/dms/objects/{objectId}
-
PATCH /api/dms/objects/{objectId}
-
POST /api/dms/objects/{objectId}/contents/file
-
- Restart Service
-
Repository service
- Header
-
Authorization-Header
- Examples
-
-
Importing Content
If an object with content is imported, the enriched multipart taken by the interceptor contains content stream properties in its data part. Depending on the document there can also be a text rendition. An import can be identified by the action with the code 100 or 101 in the options metadata section.
Data part of the original request{ "objects" : [ { "properties" : { "system:objectTypeid" : { "value" : "miscellaneous" }, "name" : { "value" : "my document" }, "description" : { "value" : "this is a test document" } }, "contentStreams" : [ { "mimeType" : "message/rfc822", "fileName" : "content.eml", "cid" : "content" } ] } ] }
Data part of the enriched multipart taken by the interceptor{ "objects" : [ { "properties" : { "system:objectTypeid" : { "value" : "miscellaneous" }, "name" : { "value" : "my document" }, "description" : { "value" : "this is a test document" } }, "contentStreams" : [ { "contentStreamId" : "85E76328-6651-11EB-88B6-71C8C8177575", "archivePath" : "default/DOCUMENT/5E/76/3/", "length" : 42938, "mimeType" : "message/rfc822", "fileName" : "content.eml", "digest" : "328B2AF519C144050A43EBBFFE21CC722C4E5A6DB40CD1DDCD5A7A54AFA6EE72", "repositoryId" : "repo242" } ], "renditions" : [ { "mimeType" : "text/plain", "kind" : "text", "contentStream" : { "length" : 40963, "mimeType" : "text/plain", "fileName" : "content.txt", "cid" : "rendition_195" } } ], "options" : { "traceid" : "a78d178f712cbd75", "analyzeMimeType" : true, "analyzeContent" : true, "action" : 101 } } ] }
-
Updating Content
A content update can be identified by the action with the code 301 in the
options
metadata section. Like in the import scenario, content stream properties are available in the enriched multipart, and depending on the document a text rendition can also be available.Data part of the original requestThe initial request does not contain a multipart body and thus no data part can be shown here.
Data part of the enriched multipart taken by the interceptor{ "objects" : [ { "properties" : { "system:objectId" : { "value" : "50971948-019a-493f-bdf5-571e91e61236" }, "system:objectTypeId" : { "value" : "appTest:miscellaneous" } }, "contentStreams" : [ { "contentStreamId" : "9C9EDCC3-6716-11EB-B18C-A9EA85931B27", "archivePath" : "default/DOCUMENT/C9/ED/C/", "length" : 14157, "mimeType" : "image/jpeg", "fileName" : "test2.txt", "digest" : "998FAFD7B3045767B64463C46AB267A7DCC442E28F0FAF5D68C6A32E7DA8987F", "repositoryId" : "repo242" } ], "options" : { "currentVersion" : { "properties" : { "system:traceId" : { "value" : "8e57d683bdc36de5" }, "system:objectTypeId" : { "value" : "appTest:miscellaneous" }, "system:versionNumber" : { "value" : 3 }, "system:createdBy" : { "value" : "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate" : { "value" : "2021-02-03T21:17:36.400Z" }, "appTest:name" : { "value" : "my document" }, "system:lastModificationDate" : { "value" : "2021-02-04T13:01:37.120Z" }, "system:baseTypeId" : { "value" : "system:document" }, "system:tenant" : { "value" : "default" }, "appTest:description" : { "value" : "this is a new description" }, "system:lastModifiedBy" : { "value" : "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:objectId" : { "value" : "50971948-019a-493f-bdf5-571e91e61236" } } }, "traceid" : "9a00c294eaf1e2af", "action" : 301 } } ] }
-
Updating Metadata
A metadata update can be identified by the action with the code 300 in the options metadata section of the enriched request body. Moreover, the objectId is added to the properties of the original request.
Data part of the original request{ "objects" : [ { "properties" : { "description" : { "value" : "this is a new description" } } } ] }
Data part in the enriched multipart taken by the interceptor{ "objects" : [ { "properties" : { "description" : { "value" : "this is a new description" }, "system:objectId" : { "value" : "50971948-019a-493f-bdf5-571e91e61236" } }, "options" : { "action" : 300, "preserve_missing_properties" : true, "currentVersion" : { "properties" : { "system:traceId" : { "value" : "df4735bd88e94678" }, "system:objectTypeId" : { "value" : "appTest:miscellaneous" }, "system:versionNumber" : { "value" : 1 }, "system:createdBy" : { "value" : "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate" : { "value" : "2021-02-03T21:17:36.400Z" }, "appTest:name" : { "value" : "my document" }, "system:lastModificationDate" : { "value" : "2021-02-03T21:17:36.400Z" }, "system:baseTypeId" : { "value" : "system:document" }, "system:tenant" : { "value" : "default" }, "appTest:description" : { "value" : "this is a test document" }, "system:lastModifiedBy" : { "value" : "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:objectId" : { "value" : "50971948-019a-493f-bdf5-571e91e61236" } } } } } ] }
-
Interceptor Configuration Example
The following example configures an interceptor that will be trigger by every update of a content (action code 301). At the take-off point after the repository
service, the enriched request body is passed to the external endpoint specified by url.
To activate this configuration, the repository
service needs to be restarted.
1
2
3
4
5
6
7
8
9
10
{
"interceptors": [
{
"type": "dms.request.objects.upsert.database-before",
"predicate": "spel:options['action']==301",
"url": "http://exampleinterceptorcontentupdate/api/dms/objects/upsert",
"useDiscovery": true
}
]
}
2.10. Configuration
2.10.1. Git and 'configservice'
Most of the yuuvis® Momentum core services are configured via profiles and corresponding configuration files. Following the basic concepts of Spring Boot, the configuration files are stored on a git server and are managed via the configservice
.
The configservice
cannot start without an active connection to the git server.
At runtime, the configservice
applies all changes to configuration files to its local resources first. At regular intervals of 5 minutes, the remote resources on the git server are synchronized according to the following procedure:
-
All changes in the local resources applied during the last five minutes are summarized in one single commit.
-
A git pull request with
THEIRS
merge policy is used to introduce changes made directly in the remote resources into the local resources.It is thus possible to overwrite changes that are applied to the local resources (e.g., via yuuvis® Momentum endpoints) by applying changes directly to the remote repository. However, those changes are NOT visible before the regular synchronization. -
The commit and the merge result are published via a single push request.
This procedure of collecting and summarizing changes reduces the number of commits that have to be managed by the configservice
in case of a high frequency of change requests.
Additionally, as of 2022 Summer, it is possible to synchronize the local resources of the configservice
and the remote resources on the git server via the endpoint POST <host>:<port_of_configservice>/manage/refresh
at any time. This synchronization is additional and independent of the automated synchronization every 5 minutes.
In case multiple instances of the configservice are running, the synchronization of the individual local resources is done at the regular intervals of 5 minutes as well. Thus, requests for resources that have been modified less than 5 minutes ago might lead to the retrieval of a deprecated version of those resources. Resources created less than 5 minutes ago might be not available.
|
In the Kubernetes environment, each instance of the configservice
additionally stores the resources in a separate persistent volume at /tmp/configservice
. In the default configuration, changes in those resources are used for the service initialization. I.e., changes that are not yet included in the commit are calculated via git diff
and considered during the synchronization procedure described above.
2.10.2. Configuration via Profiles
Each core service retrieves YAML configuration files from a central location managed by the CONFIG service. These YAML configuration files extend the base application.yml configuration file inherent to any Spring boot microservice. Each of the additional configuration files corresponds to a profile, denoted by the suffix of the file, which the service of interest will need to be configured to run in.
The architecture of services and profiles follows the basic concepts of Spring Boot. For more detailed information, please refer to the Spring Boot profiles documentation.
So how is this helpful? There are two main benefits:
-
They act as globally reusable configuration elements.
Configuration profiles allow for specific bits of configuration to be used by multiple services across the system. Any service can load the information from existing configuration files using its SPRING_PROFILES_ACTIVE environment variable. For example, a configuration file containing Elasticsearch connection parameters are loaded by both the
search
andindex
services. -
Profiles also allow for the customization of specific service instances.
For example, several instances of the
repository
service could be used to separate data into different data sources with a configuration profile containing access parameters for each of the available data sources.
Names of YAML Configuration Files
The name of the YAML configuration file defines whether it will be available to all services or to only one specific service: there are two types of profiles that are distinguished by their naming scheme:
-
Profiles containing information relevant to multiple services must adhere to the
application-<profile type>.yml
naming scheme in order to be referable to by any service in the system. -
Profiles specific to a single service have to be called
<service-identifier>-<profile type>.yml
.
The individual services do not reference a specific profile file name but only the profile type. It is important to consider the strict hierarchy implemented in Spring Boot profile-based configurations. A configuration specific to a single service (i.e., system-prod.yml
) always takes precedence over any global configuration (i.e., application-prod.yml
), which means that overriding a global configuration is entirely possible.
Profiles in Kubernetes
Configuration during Installation
You can set the configuration parameter values in advance during installation.
The configuration parameters are set in the values.yaml file of the yuuvis Helm chart. Modify a value of the listed parameters or add one of the available parameters listed in the above linked fact sheet of the corresponding profile with your desired value to overwrite its default value.
During the deployment, the settings defined in the values.yaml file will be written into the profile files that are read by the services when they are started.
Changing the Configuration of a Running System
For changes on a running system, you need to access your Git server.
Navigate to the root directory of the configuration git repositories' appropriate branch and find a list of the configuration files including the above listed profiles. Open the profile, modify it, and check in your changes.
After the modification of a profile, you need to restart the services that reference the profile in order to apply the changes.
Adding Custom Profiles
New profiles can be added by committing their configuration YAML files to the root directory of the configuration git repositories' appropriate branch.
To activate any custom profile-based configuration, the services that are meant to use them need to set them as their active Spring Profiles.
In Kubernetes, this can be accomplished by modifying the deployment file of the service. Using kubectl edit -n <namespace> deployment <service identifier>
, the active profiles of a given service can be changed. The active profiles are listed under the SPRING_PROFILES_ACTIVE environment variable. Any changes will incur a restart of the services.
Outsourcing Passwords from Profiles as Kubernetes Secrets
Passwords can be outsourced from profile files as Kubernetes Secrets. In the configuration file, placeholders are included instead that are replaced by the actual passwords during the pod’s runtime. Please note that passwords as Kubernetes Secrets can be displayed in plain text format in the environment variables of the pods and contained services. The following guideline explains the configuration procedure for the password corresponding to the database connection. The same procedure can also be applied to any other password contained in a profile file.
-
Convert the password in the
application-dbs.yml
file to Base64 format.Example command for Windows Powershell:
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("changeme"))
Example command for Linux:
echo -n "changeme" | base64 -w0
Both example commands lead to the output
Y2hhbmdlbWU=
. -
Create a
yuuvis-secrets.yml
file with the following content:apiVersion: v1 kind: Secret metadata: name: yuuvis-secrets namespace: yuuvis type: Opaque data: POSTGRES_PASSWORD: Y2hhbmdlbWU=
The section data contains a list of key-value pairs that can contain multiple entries. As spacers within the string key name, only underscores are allowed. The value is the password in Base64 format.
-
Create a Kubernetes Secret by running the command
kubectl apply -f yuuvis-secrets.yml
. -
Replace the password in the application-dbs.yml file by a placeholder:
yuuvis.db.password: ${POSTGRES_PASSWORD}
-
Adjust the deployments of all yuuvis® services using the profile dbs by extending the section
env
:env: - name: POSTGRE_PASSWORD valueFrom: secretKeyRef: name: yuuvis-secrets key: POSTGRE_PASSWORD
The name and the key given in
secretKeyRef
have to correspond to the name and the data value defined in the fileyuuvis-secrets.yml
.
Available Profiles
The following profiles are available and referenced by the listed services in the default installation.
Profile | Related Configuration File(s) | Referenced by | Description |
---|---|---|---|
Feature Profiles: The following profiles can be activated for the corresponding services in order to activate/deactivate a specific processing behavior. In the default installation, no specific YAML configuration files are available. |
|||
|
- |
|
Decides whether PostgreSQL wire protocol or MS SQL should be used for the database connection of the If |
|
- |
|
Decides whether a messaging provider should be used by the If
If
|
|
- |
|
Enables user-role mapping in Keycloak. |
Configuration Profiles: The following profiles are used to provide the related configuration parameters to all services for which they are activated in the default installation. |
|||
|
service-specific configurations:
|
all services except |
Separation of development and production environments. A service with prod (dev) as active profile is running in the production (development) environment. Per default, all services are deployed in the production environment. If you want to build a test environment, you need to manually create the corresponding profiles. The |
|
application-kubernetes.yml |
|
Used in Kubernetes systems. Services will use a Kubernetes-specific internal configuration. Furthermore, the |
|
application-redis.yml |
|
Redis connection parameters. |
|
application-mq.yml |
|
Messaging queue connection parameters. |
|
application-dbs.yml |
|
Database connection parameters. |
|
application-es.yml |
|
Elasticsearch connection parameters. Index configuration used to create Elasticsearch index. |
|
application-storage.yml |
|
Binary data storage connection parameters. |
|
application-oauth2.yml |
|
Contains authentication-related parameters. |
|
application-metrics.yml |
|
Profile under development. In the future, metrics should provide a possibility to monitor responses from the service instance. |
2.10.3. Available YAML Files
The YAML configuration files are read by a service if the corresponding profiles are activated.
Following files are available:
-
application-dbs.yml
- database connection configuration -
application-es.yml
- search engine connection -
application-oauth2.yml
- identity provider connection -
application-storage.yml
- binary storage connection -
authentication-prod.yml
-authentication
service configuration -
system-prod.yml
-system
service configuration -
commander-prod.yml
-commander
service configuration -
application-prod.yml
- configuration for all services
application-dbs.yml
Parameter | Description | Default Value | |||
---|---|---|---|---|---|
|
Integer number of connections to the database per service (
|
10 |
|||
|
Section of individual database configurations. |
||||
|
List of database definitions with the following required parameters:
|
|
|||
|
List of database configurations with the following required parameters:
|
|
If using MS SQL 2019…
SSL is required. To connect without SSL, append
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
storage:
databases:
defaultdb:
datasource: defaultds
predicate: 'spel:false'
default: true
database2:
datasource: db2source
predicate: "spel:properties['system:tenant']['value']=='tenant2'"
default: false
datasources:
defaultds:
url: 'jdbc:postgresql://abc/def'
username: yuuvis-postgresql
password: changeme123
driver-class-name: 'org.postgresql.Driver'
db2source:
url: 'jdbc:sqlserver://ghi/jkl'
username: yuuvis-sqlserver
password: changeme456
driver-class-name: 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
application-es.yml
As of 2023 Autumn:
Parameter | Description | Default value | |||
---|---|---|---|---|---|
|
Configurations of Elasticsearch instances. The ID of each instance is defined via the key (e.g., database1). For each search action requested for a DMS object, the list of search databases is read from the top. The first search database for which the predicate is evaluated to true is used. If no predicate is true, the default database is used.
For each Elasticsearch instance, the following parameters have to be specified. |
||||
|
Reference on a configuration in |
||||
|
SPEL statement specifying the condition under which the search database should be used. As of version 2023 Autumn, the condition can only reference the system:tenant property of DMS objects. |
||||
|
Boolean value that specifies whether the search database should be used as default search database (true) or not (false).
|
||||
|
List of search database (Elasticsearch index) configurations with the following parameters: |
||||
|
Required. Comma-separated list of one or more URLs to the corresponding Elasticsearch instance(s). |
- |
|||
|
Optional. Username to access the Elasticsearch instance(s). |
- |
|||
|
Optional. Password to access the Elasticsearch instance(s). |
- |
|||
|
Optional. Name of the Elasticsearch index. If no index with the specified name is available, a new index is created. |
|
|||
|
Optional. Read only during the creation of a new Elasticsearch index: Languages to be configured in the Elasticsearch analyzer configuration specified via ISO codes. |
|
|||
|
Optional. |
30000 |
storage:
searchdatabases:
database1:
datasource: dbsource1
predicate: 'spel:false'
default: true
database2:
datasource: dbsource2
predicate: "spel:properties['system:tenant']['value']=='yuuvistest'"
default: false
searchdatasources:
dbsource1:
urls: '<host1>:<portA>','<host2>:<portB>'
dbsource2:
urls: '<host3>:<portC>'
user: 'exampleuser'
password: 'examplepassword'
index: 'exampleindex'
languages: 'de;en'
timeout: 30000
Up to product version 2023 Summer, the following parameters are available:
Parameter | Description | Read by Service | Default Value | |
---|---|---|---|---|
|
Section of configuration parameters for the Elasticsearch index to be used by yuuvis® Momentum. |
|||
|
Name of the Elasticsearch index. If no index with the specified name is available, a new index is created. |
|
|
|
|
Read only during the creation of a new Elasticsearch index: Languages to be configured in the Elasticsearch analyzer configuration specified via ISO codes. |
|
|
application-oauth2.yml
This article describes the behavior of the core system. However, the configuration file is read by the TENANT-MANAGEMENT Service as well if installed. |
Parameter | Description | Read by Service | Default Value | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
The parameter is used as a variable for the IP address of the used Keycloak server that can be referenced in The value is set automatically during the installation of the infrastructure Helm chart during which the IP address of your Keycloak server has to be specified. If a different identity provider is used, you can remove this parameter and define an own one in order to reference it in authentication.oauth2.tenants. |
- |
- |
||||||||||||||||
|
List of tenant configurations read by the If Keycloak is used, check the settings via the Keycloak Admin Console. Further notes:
|
|
See code block below. |
||||||||||||||||
|
Required. Name of the tenant. If it is changed, please do not forget to adjust it in the |
|
|||||||||||||||||
|
Required. Identification of the |
|
|||||||||||||||||
|
Tenant-specific identification of the |
|
|||||||||||||||||
|
Contains the Authorization URI of the OAuth2 identity provider. |
|
|||||||||||||||||
|
Required. Contains the Token URI of the OAuth2 identity provider. |
|
|||||||||||||||||
|
Required. URL of the identity provider’s endpoint for retrieving user data. |
|
|||||||||||||||||
|
If this parameter is set, a logout from a yuuvis® Momentum session will trigger a logout from the identity provider as well. Set as value the endpoint of the identity provider that is responsible for the logout process. As of 2023 Summer: If Keycloak is used as identity provider, the
example configuration
|
|
|||||||||||||||||
|
Required. JSON path expression to extract the user name from the response of the endpoint specified in |
|
|||||||||||||||||
|
Comma-separated list of strings. Available values and their effects depend on the used identity provider. For Keycloak:
|
||||||||||||||||||
|
Parameter read by the |
|
|
||||||||||||||||
|
Parameter read by the |
|
|
||||||||||||||||
|
Parameter read by the |
|
|
authentication.oauth2.tenants:
- name: myfirsttenant
clientId: yuuvis-authentication-service
clientSecret: <my-secret>
userAuthorizationUri: https://${keycloak.host}/auth/realms/myfirsttenant/protocol/openid-connect/auth
accessTokenUri: https://${keycloak.host}/auth/realms/myfirsttenant/protocol/openid-connect/token
userInfoUri: https://${keycloak.host}/auth/realms/myfirsttenant/protocol/openid-connect/userinfo
endSessionUri: https://${keycloak.host}/auth/realms/myfirsttenant/protocol/openid-connect/logout
userNameExtractionPattern: $.sub
scope: openid
application-storage.yml
Configuration file containing parameters and archive profiles used by the archive
and repository
service in order to connect external archives.
- File Structure
-
storage: repositories: <repositoryId>: profiles: ['<archiveProfile>'] <parameter>: <value> profiles: <archiveDriverName>: <archiveProfile>: <parameter>: <value>
Define your repositories via
repositoryId
. For each of them, specify an archive profile and thus define the type of archive driver for the corresponding repository.As of 2024 Summer, most archive drivers are directly provided by the
repository
service. However, thehcp-s3
driver is provided only by thearchive
service yet. Therefore, the parametersurl
anduseDiscovery
are required for it as described below.For each type of archive driver identified by
archiveDriverName
, define one or more archive profiles. The name of each archive profile must be unique within the configuration file. Depending on the archive type, specific configuration parameters have to be set as described below too. - Parameters
-
Parameter Description Example storage.default-rendition-repository
As of 2021 Winter. Specify the ID of a default rendition repository. It will be used for the storage of renditions if no repository is specified in the corresponding request header. As of version 2021 Winter, only an S3 storage can be supported. It has to be defined in the
storage.repositories
section.It is recommended to configure a separate repository for the storage of renditions. The demands regarding storage of renditions differs from the storage of binary content files. E.g., retention is not supported.
renrepo
storage.repositories
Configurations of repositories for by the
repository
service. TherepositoryId
of each repository is defined via the key (e.g., s3 or netapp). For each repository, the following parameters have to be specified.s3: profiles: ['s3profile1'] default: true netapp: profiles: ['netapplike'] encryption: enabled: true password: "changeme"
profiles
A list of archive profile names, each of them referencing an archive profile defined in the
storage.profiles
section. The type of archive must be the same in the archive profile definition and in the repository configuration.For any repository that will be used as rendition repository, an S3 profile has to be specified.
Only the first list entry will be considered whereas further list entries will be ignored. url
As of 2024 Summer only required for
hcp-s3
driver.Address of the repository accessible via the
archive
service. The archive profile can be referenced as dynamic component in curly brackets (e.g.,http://archive/api/profiles/{profile}/dms/objects
).useDiscovery
As of 2024 Spring only required
hcp-s3
driver.Boolean value specifying if the given url contains a reference and should be interpreted via the discovery (
true
) or if an absolute address is specified (false
).predicate
Available as of 2023 Autumn. Specifies a condition using any properties of the target DMS objects before normalization. If the condition is matched by an imported DMS object, its binary content is stored in the corresponding repository instead of the default repository.
If a
repositoryId
is explicitly specified during a content-related request, this value dominates and there is nopredicate
evaluation.Default value:
'spel:false'
default
Optional: Boolean value specifying if the repository should be the default repository (
true
) or not (false
). Only one repository can be default repository.The default repository will be used for each content-related request where no
repositoryId
is explicitly specified AND none of the other repositories' predicates is matched.The default repository is NOT used as default rendition repository if
storage.default-rendition-repository
is missing.encryption
As of 2024 Summer.
Optional: Enable or disable (default) the encryption of binary content files before storing them. If enabled, storage administrators cannot open and read the files.
To enable the encryption, set the sub-parameters
enabled: true
andpassword
(can be specified via environment variable as well). If encryption is enabled but no password is set, each request to the repository will fail.The
digest
value is still calculated based on the original content file before the encryption.As the encryption reduces the performance of your system, use it only if necessary. Especially range requests for sections of very large content files might be slow. The entire content has to be decrypted before the requested range can be retrieved. storage.profiles
Archive profiles for each archive driver. Multiple profiles can be defined for each archive driver. The name of each profile is defined via the corresponding key (e.g.,
s3profile1
ornetapplike
). Each archive profile name has to be unique within the configuration file and can belong to only one archive driver type.The parameters for the configuration of an archive profile depend on the archive driver indicated by the corresponding
archiveDriverName
(e.g.,s3
ornetapp
). For the supported archive drivers, the configuration parameters are listed below.An S3 archive profile configuration is required for the usage of a rendition repository. s3: s3profile1: access-key: 'MGMWCOYTDUSLNCFE' secret-key: 'changeme' url: 'http://minio.infrastructure:9000' bucket: 'dmscloudrepodocker' netapp: netapplike: # use mountpoint of the persistent volume claim that provides the netapp storage # must be the same in the deployment of the archive app volume: '/var/lib/netapp/data' defaultRetentionInDays: 10
Parameters in Archive Profiles
Depending on the archive driver, the archive profiles have to be configured with specific parameters.
Drivers for the following Archives are available:
-
- General Parameters
-
Parameter Description defaultRetentionInDays
The
defaultRetentionInDays
parameter can be set in all following archive profiles. This value is used as retention time for objects that do not have a retention time specified within their metadata during their import. IfdefaultRetentionInDays
is set to 0 which is also the default value, no retention will be set for those objects. If the profile is used for a rendition repository, the parameter is ignored as renditions cannot be under retention.pathTemplate
Many of the below listed archive profiles allow to configure a
pathTemplate
to specify a path structure within the storage.The following variables can be used. They are referenced with curly brackets within the
pathTemplate value
(see example below).-
tenant
,system:tenant
-
contentStreamId
,system:contentStreamId
-
objectTypeId
,system:objectTypeId
We recommend to start the path with
{tenant}
to separate the individual tenant’s contents.With the
substring
operation, a specific part of a string can be referenced. For example, to reference the first two characters of thecontentStreamId
, use\{contentStreamId.substring(0,2)}
. The second index is excluded. If only one index is specified, the characters beginning from that index are referenced. For example, using'test'.substring(2)
would result in st.In some cases, the
DATE
operation can be useful to reference the current date stamp. By passing a parameter toDATE
, a format string is specified as defined by SimpleDateFormat. Without any parameter, ayyyyMMdd
is considered.Example:
-
Consider the
pathTemplate
configuration{tenant}/\{DATE(yyyy)/DATE(MM)/DATE(dd)/\{contentStreamId.substring(0,2)}}
-
The currently logged-in user belongs to the
yuuvistest
tenant. -
The user stores a binary content file at 21 DEC 2022 at 4.11 pm.
-
The binary content file gets
7850BB1A-F749-11E8-A21E-49DDF2475266
, as value for thecontentStreamId
. -
The archive path results to
yuuvistest/2022/12/21/78/
.
storeCurrentMetadataAlongWithBinary
As of 2024 Spring. Not available for
filesystem
andhcp-s3
drivers.Boolean value to enable (
true
) or disable (false
, default) additional archiving of the metadata for each stored DMS object. Please note that large sets of metadata require considerable storage resources. -
- Parameters for S3 Archive Profiles
-
Use
s3
as value forarchiveDriverName
.Parameter Description Default Value access-key
Access key
-
secret-key
Password
-
url
URL for S3
-
bucket
Name of the bucket in the archive system for filing.
-
defaultRetentionInDays
Retention time in days.
Objects under retention can still be deleted by administrators having direct access to the S3 storage. To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.If the profile is used for a repository used as rendition repository, the parameter is ignored for the storage of renditions as they cannot be under retention. However, if binary content files are stored in the same repository beside the renditions, the defaultRetentionInDays value is NOT ignored for the storage of binary content files.
0
region
As of 2022 Autumn. Specifies the location of the data center where to create new buckets.
If not specified, it is automatically determined via the S3 method
GetBucketLocation
.-
objectLock
As of 2022 Autumn. Boolean value that decides if the archive-internal retention (
objectLock
) is required (true
) or optional (false
) for the corresponding bucket.If
true
is set:-
Binary content files under retention specified via secondary object type (SOT)
system:rmDestructionRetention
can only be stored in buckets with activated ObjectLocking. -
Buckets automatically created by the
archive
service will have activated objectLock.
If
false
is set:-
For binary content files under retention specified via SOT
system:rmDestructionRetention
stored in buckets with activated ObjectLocking, an archive-internal retention will be set. -
For binary content files under retention specified via SOT
system:rmDestructionRetention
stored in buckets with deactivated ObjectLocking, no archive-internal retention will be set. Thus, binary content files can only be protected from manipulation via yuuvis® Momentum endpoints but not from manipulation by direct storage access. -
Buckets automatically created by the
archive
service will have deactivated objectLock.
In both cases: For objects without retention specified via SOT
system:rmDestructionRetention
, no archive-internal retention is set.true
pathTemplate
Optional: This parameter can be used to store objects in specific directories (paths) within a bucket. Find details in the description of the general parameters for all archives.
If the profile is used for a rendition repository, use only the
contentStreamId
as a placeholder in the specified path. Do not include a DATE reference to avoid path changes for each rendition update (Instead of a rendition update, a new rendition would be created and the previous rendition would have to be deleted.)-
retentionMode
Optional parameter to select a retention mode for S3 Object Lock.
Available values:
-
COMPLIANCE
- objects under retention cannot be modified/deleted even by a storage administrator. -
GOVERNANCE
- storage users with specific permissions can modify/delete objects under retention.
COMPLIANCE
-
- Parameters for NetApp Archive Profiles
-
Use
netapp
as value forarchiveDriverName
.Parameter Description Default Value volume
Archive location for the data to be saved.
-
defaultRetentionInDays
Optional: Retention time in days.
To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.0
enableReadOnly
Optional: Defines whether the drivers of the archive should define data to be read-only.
true
pathTemplate
Optional: This parameter can be used to store objects in specific directories (paths) within a bucket. Find details in the description of the general parameters for all archives.
-
- Parameters for iCAS Archive Profiles
-
Use
iternity
as value forarchiveDriverName
.Parameter Description Default Value userName
Name of the user with the appropriate rights for the archive.
-
userPassword
The user’s password.
-
endpoint
URL of the iCAS web service.
-
cscMode
Storage mode for objects and meta data.
The storage mode is specified with a sequence of four parameters:
Binary Content File Metadata Compression
Encryption
Compression
Encryption
S (without)
N (without)
S (without)
N (without)
L (with)
S (standard)
L (with)
S (standard)
A (AES 256)
A (AES 259)
Example:
LSSN
→ The binary content file is compressed (L) and encrypted with the standard method (S); the metadata is not compressed (S) and not encrypted (N).-
maxCreateCscSize
Determines the maximum size of containers.
The information is specified in bytes.
10000000
maxCreateCscFile
Determines the maximum number of objects for the containers.
1000
maxCreateCscSingleFileLimit
Determines the individual size limit of an object.
4000000
maxWorkChunkSize
Determines the maximum size of a single chunk.
The information is specified in bytes.
5000000
clientSslTrustStore
Optional: Resource path to a certificate trust store for encrypted communication with the web service.
-
clientSslTrustStorePassword
Optional: Password for the certificate trust store.
-
defaultRetentionInDays
Retention time in days.
To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.0
- Parameters for Hitachi Content Platform Archive Profiles
-
Use
hcp-s3
(up to 2023 Winterhcp_s3
) as value forarchiveDriverName
.Retention times cannot be subsequently extended in Hitachi Content Platform archives. If a binary content file is stored with a retention time (either via configured defaultRetentionInDays
or via object propertysystem:rmExpirationDate
), this time is fixed in the archive metadata during the entire storage time.Parameter Description Default Value access-key
Access key
-
secret-key
Password
-
url
URL for HCP
-
bucket
Name of the bucket in the archive system for filing.
-
defaultRetentionInDays
Retention time in days.
To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.0
pathTemplate
Optional: This parameter can be used to store objects in specific directories (paths) within a bucket. Find details in the description of the general parameters for all archives.
-
- Parameters for Cloudian HyperStore Archive Profiles
-
The Cloudian Hyperstore Content Platform provides an AWS-S3-compatible ,REST API with few extensions used by the
archive
service. In order to configure the Cloudian Hyperstore archive, you need to configure the following (S3-relevant) parameters.Use
cloudian_s3
as value forarchiveDriverName
.Parameter Description Default Value access-key
Access key
-
secret-key
Password
-
url
URL for Cloudian HyperStore
-
bucket
Name of the bucket in the archive system for filing.
-
defaultRetentionInDays
Retention time in days.
To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.0
pathTemplate
Optional: This parameter can be used to store objects in specific directories (paths) within a bucket. Find details in the description of the general parameters for all archives.
-
- Parameters for DELL S3 Archive Profiles
-
Available as of 2022 Autumn. Use
ecs-s3
as value forarchiveDriverName
.Parameter Description Default Value access-key
Access key
-
secret-key
Password
-
url
URL for S3
-
bucket
Name of the bucket in the archive system for filing.
-
defaultRetentionInDays
Retention time in days.
Objects under retention can still be deleted by administrators having direct access to the S3 storage. To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.If the profile is used for a repository used as rendition repository, the parameter is ignored for the storage of renditions as they cannot be under retention. However, if binary content files are stored in the same repository beside the renditions, the
defaultRetentionInDays
value is NOT ignored for the storage of binary content files.0
region
Specifies the location of the data center where to create new buckets. If not specified, it is automatically determined via the S3 method GetBucketLocation.
-
objectLock
Boolean value that decides if the archive-internal retention (objectLock) is required (
true
) or optional (false
) for the corresponding bucket.If
true
is set:-
Binary content files under retention specified via secondary object type (SOT)
system:rmDestructionRetention
can only be stored in buckets with activated ObjectLocking. -
Buckets automatically created by the
archive
service will have activated objectLock.
If
false
is set:-
For binary content files under retention specified via SOT
system:rmDestructionRetention
stored in buckets with activated ObjectLocking, an archive-internal retention will be set. -
For binary content files under retention specified via SOT
system:rmDestructionRetention
stored in buckets with deactivated ObjectLocking, no archive-internal retention will be set. Thus, binary content files can only be protected from manipulation via yuuvis® Momentum endpoints but not from manipulation by direct storage access. -
Buckets automatically created by the
archive
service will have deactivated objectLock.
In both cases: For objects without retention specified via SOT system:rmDestructionRetention, no archive-internal retention is set.
true
retentionMode
Optional parameter to select a retention mode for S3 Object Lock.
Available values:
-
COMPLIANCE
- objects under retention cannot be modified/deleted even by a storage administrator. -
GOVERNANCE
- storage users with specific permissions can modify/delete objects under retention.
COMPLIANCE
pathTemplate
Optional: This parameter can be used to store objects in specific directories (paths) within a bucket. Find details in the description of the general parameters for all archives.
If the profile is used for a rendition repository, use only the
contentStreamId
as a placeholder in the specified path. Do not include a DATE reference to avoid path changes for each rendition update (Instead of a rendition update, a new rendition would be created and the previous rendition would have to be deleted.)-
-
- Parameters for File System Profiles
-
Use
filesystem
as value forarchiveDriverName
.Parameter Description Default Value volume
Storage container location.
-
pathTemplate
This parameter is essential as it configures to store objects in specific directories (paths) within the volume. Find details in the description of the general parameters for all archives.
{tenant}/DOCUMENT/\{contentStreamId.substring(1,3)}/\{contentStreamId.substring(3,5)}/\{contentStreamId.substring(5,6)}
Each binary content file stored in a file system repository is portioned in sub-sets of data. Each of those chunks is named <contentStreamId>_<count>. All chunks belonging to the same binary content file are encapsulated in one ZIP file. Additionally, each ZIP file contains a meta.xml file containing processing information for the stored binary content file:
-
file name
-
version
-
mime type
-
unpacked file size
-
SHA-256 hash calculated by the
repository
service -
MD5 hash calculated by the
repository
service
example meta.xml<?xml version="1.0" encoding="UTF-8"?> <xmlmeta> <filename>content.eml</filename> <version>1.0</version> <mime>message/rfc822</mime> <size>156836</size> <sha256>0BA8B60F0A1D16DEB44D9EE427A75FADE6ADF751312BE9D22D7D4ED2CC3B2DA6</sha256> <md5>BF8782D1AD01CDF211AD09038AB64349</md5> <chunksize>156836</chunksize> </xmlmeta>
The number of chunks is determined by the file size of the binary content file to be stored:
size of binary content file number of chunks size of each chunk <= 1 MB
1
size of binary content file
>
1 MB to <= 10 MBsize of binary content file / 1MB
1MB (minimum chunk size)
>
10 MB to < 1280 MB (128 MB is the maximum chunk size)10
size of binary content file / number of chunks + 1 Byte
>
(x - 1) • 1280 MB to <= x • 1280 MBwhere (x = 2 … 2n, n ∈ ℕ)
10 • x
size of binary content file / number of chunks + 1 Byte
-
- Parameters for Azure Blob Storage Profiles with Buckets
-
Available as of 2022 Winter. Use
azure_blobstore
as value forarchiveDriverName
.Parameter Description Default Value connection
Connection string containing all required information for the access to Azure.
-
defaultRetentionInDays
Retention time in days.
Objects under retention can still be deleted by administrators having direct access to the storage. To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.0
pathTemplate
Optional: This parameter can be used to store objects in specific directories (paths) within a bucket. Find details in the description of the general parameters for all archives.
buckets
A map containing one or more configurations.
Specify a unique configuration name as configuration key. For each key, the name and retentionInYears parameters are required.
Whenever the content file of an object is stored in Azure, the
archive
service selects the container with the lowestretentionInYears
value that still ensures the retention for that concrete object (either scheduled viasystem:rmExpirationDate
object property or viadefaultRetentionInDays
). The name of the selected bucket is used as prefix for thecontentStreamId
that is generated for the object content file.-
name
Name of the container in Azure.
The container has to exist. retentionInYears
Retention time that is configured in Azure for the container specified by name.
If
retentionInYears
is 0, the corresponding container does not have archive-internal retention. It is used to store objects without retention (neither scheduled viasystem:rmExpirationDate
object property nor viadefaultRetentionInDays
).The specified retention time has to match the Azure container configuration. Example: Consider the configuration below. If the content file of an object with a scheduled retention time of 2 years would be stored,
blob20years
container would be used.Example Azure Blob Storage Profile Configurationstorage: repositories: ... profiles: ... azure_blobstore: azureImmutable1: connection: 'DefaultEndpointsProtocol=https;AccountName=immutablestorageos;AccountKey=AAAAAAAAAA==;EndpointSuffix=core.windows.net' defaultRetentionInDays: 0 buckets: 'blob1': name: 'blobNoRetention' retentionInYears: 0 'blob2': retentionInYears: 1 name: 'blob1year' 'blob3': retentionInYears: 20 name: 'blob20years'
- Parameters for Azure Profiles with Object Retention
-
Available as of 2023 Autumn. Use
azure_objectretention
as value forarchiveDriverName
.Parameter Description Default Value connection
Connection string containing all required information for the access to Azure.
-
defaultRetentionInDays
Retention time in days.
Objects under retention can still be deleted by administrators having direct access to the storage. To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.0
retentionMode
Optional parameter to select an Azure immutability policy lock similar to the retention mode for S3 Object Lock.
Available values:
-
COMPLIANCE
- objects under retention cannot be modified/deleted even by a storage administrator. Corresponds to Azure immutability policyLOCKED
. -
GOVERNANCE
- storage users with specific permissions can modify/delete objects under retention. Corresponds to Azure immutability policyUNLOCKED
.
COMPLIANCE
pathTemplate
Optional: This parameter can be used to store objects in specific directories (paths) within a bucket. Find details in the description of the general parameters for all archives.
Example Azure Profile Configuration with Object Retentionazure_objectretention: azureProfile1: connection: 'DefaultEndpointsProtocol=https;AccountName=XXXXX;AccountKey=xxxx....' bucket: test1 pathTemplate: '{tenant}/{DATE(yyyy)}/{DATE(MM)}/{DATE(dd)}/{contentStreamId.substring(0,2)}' defaultRetentionInDays: 2
-
- Parameters for Google Cloud Storage Profiles
-
Available as of 2024 Summer. Use
gcs
as value forarchiveDriverName
.Parameter Description Default Value connection
Connection string containing all required information for the access to Google Cloud.
To create the string, retrieve the
key.json
authentication file from your Google Cloud Platform. Encode the file’s content with Base64 encoding. The resulting string is your connection string.-
bucket
Name of the bucket in the archive system for filing.
-
defaultRetentionInDays
Retention time in days.
Objects under retention can still be deleted by administrators having direct access to the Google Cloud Storage. To transmit no retention time, set the value 0.
Scheduled retention time (
system:rmExpirationDate
) has priority over any times specified here.0
objectLock
Boolean value that decides if the archive-internal retention (
objectLock
) is required (true
) or optional (false
) for the corresponding bucket.If
true
is set:-
Binary content files under retention specified via secondary object type (SOT)
system:rmDestructionRetention
can only be stored in buckets with activated ObjectLocking. -
Buckets automatically created by the
repository
service will have activated objectLock.
If
false
is set:-
For binary content files under retention specified via SOT
system:rmDestructionRetention
stored in buckets with activated ObjectLocking, an archive-internal retention will be set. -
For binary content files under retention specified via SOT
system:rmDestructionRetention
stored in buckets with deactivated ObjectLocking, no archive-internal retention will be set. Thus, binary content files can only be protected from manipulation via yuuvis® Momentum endpoints but not from manipulation by direct storage access. -
Buckets automatically created by the
repository
service will have deactivated objectLock.
In both cases: For objects without retention specified via SOT
system:rmDestructionRetention
, no archive-internal retention is set.false
pathTemplate
Optional: This parameter can be used to store objects in specific directories (paths) within a bucket. Find details in the description of the general parameters for all archives.
-
retentionMode
Optional parameter to select a retention configuration for the bucket in the Google Cloud Storage.
Available values:
-
COMPLIANCE
- objects under retention cannot be modified/deleted even by a storage administrator. -
GOVERNANCE
- storage users with specific permissions can modify/delete objects under retention.
COMPLIANCE
Example Google Cloud Profile Configurationgcs: gcsexample: connection: "ew0KICAidHlwZ......................................" bucket: examplebucket pathTemplate: "{tenant}/{DATE(yyyy)}/{DATE(MM)}/{DATE(dd)}" storeCurrentMetaDataAlongWithBinary: false retentionMode: GOVERNANCE defaultRetentionInDays: 0 objectLock: false
-
authentication-prod.yml
Parameters of the configuration file used by the authentication
service in productive systems.
Parameters
Parameter | Description | Default Value | |||
---|---|---|---|---|---|
|
Defines a path that will be added to the URL automatically if |
|
|||
|
Section of Parameters for session cookie configuration.
|
||||
|
Configures whether browser sessions are allowed where yuuvis® Momentum is embedded in an external web page, e.g., via iframe. Available values:
|
|
|||
|
Prohibits unprotected sessions. Available values:
|
|
|||
|
Configures whether JavaScript functionality of a browser application can access the session cookie. Available values:
|
1800 |
|||
|
Defines the duration for which the session between gateway and client is authorized. Specified in seconds. |
1800 |
|||
Deprecated as of 2023 Winter: |
List of services for which the Also external services can be added here. |
|
|||
|
Definition of permissions for the access to individual endpoints and sub-paths. Structured as a list of endpoints and their individual access conditions specified via the parameters Any endpoint that should be accessible via |
See code block below. |
|||
|
Available as of 2023 Autumn. If If |
|
|||
Deprecated as of 2023 Winter: |
Specifies whether the user session states are stored centrally in a Redis database (value For scaling and fail-safe operation of the |
- |
|||
|
As of 2022 Spring. If For scaling and fail-safe operation of the |
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
### Manage-Endpunkte
- endpoints: /manage/**
expose: true
- endpoints: /*/manage/**
access: hasAuthority('YUUVIS_SYSTEM_INTEGRATOR')
### API-Endpunkte
- endpoints: /api/system/**
access: hasAuthority('YUUVIS_SYSTEM_INTEGRATOR')
- endpoints: /api/admin/**
access: hasAuthority('YUUVIS_TENANT_ADMIN')
- endpoints: /api/dms/**
### Endpunkte für Swagger-Webclient des API-Gateways
- endpoints: /api/swagger-ui.html/**,/api/**/springfox-swagger-ui/**,/api/**/swagger-resources/**,/api/**/v2/api-docs/**
- endpoints: /api/swagger-ui/**,/api/swagger/v3/api-docs/**
- endpoints: /api/api/system/**
access: hasAuthority('YUUVIS_SYSTEM_INTEGRATOR')
- endpoints: /api/api/admin/**
access: hasAuthority('YUUVIS_TENANT_ADMIN')
- endpoints: /api/api/dms/**
### Webclient
- endpoints: /search/**,/viewer/**,/architect/**
- endpoints: /client/**
expose: true
### Viewer Service
- endpoints: /viewer/view/**,/viewer/assets/**,/viewer/download/**
expose: true
- endpoints: /viewer/**
### Userservice
- endpoints: /userservice/**
### bpm-engine
- endpoints: /bpm-engine/internal/**
# access: denyAll
- endpoints: /bpm-engine/**
### Metricsservice
- endpoints: /metricsservice/**
access: hasAuthority('YUUVIS_SYSTEM_INTEGRATOR')
### api-web
- endpoints: /api-web/swagger-ui.html,/api-web/swagger-ui/**,/api-web/**/v3/api-docs/**
- endpoints: /api-web/api/resources/**,/api-web/api/users/**,/api-web/api/bpm/**,/api-web/api/dms/**
- endpoints: /api-web/api/system/**
access: hasAuthority('YUUVIS_SYSTEM_INTEGRATOR')
- endpoints: /api-web/api/admin/**
access: hasAuthority('YUUVIS_TENANT_ADMIN')
### tenant-management
- endpoints: /tenant-management/swagger-ui.html,/tenant-management/swagger-ui/**,/tenant-management/**/v3/api-docs/**
- endpoints: /tenant-management/api/system/**
access: hasAuthority('YUUVIS_SYSTEM_INTEGRATOR')
- endpoints: /tenant-management/api/admin/**
access: hasAuthority('YUUVIS_TENANT_ADMIN')
### office 365
- endpoints: /office365/**
- endpoints: /dashlet365/**
Impacts of Cookies on the Login via Browser
The following impacts of the server.servlet.session.cookie.same-site
configuration parameter (see description above) are tested with Firefox (version 113) and Google Chrome (version 113). The Connection has to be protected via SSL (HTTPS protocol).
Loop means here an infinite loop of requests between authentication
service and identity provider. It is not possible to authenticate.
System integrators or administrators have to be aware of the behavior and configure their installation according to their needs.
Value for 'same-site' | Behavior in Own Context | Behavior in Embedded Context | Comment |
---|---|---|---|
|
Firefox OK, Chrome OK |
Firefox OK, Chrome OK |
Low CSRF protection (OWASP SameSite) |
|
Firefox OK, Chrome OK |
Firefox Loop, Chrome loses session |
Default configuration |
|
Firefox Loop, Chrome OK |
Firefox Loop, Chrome loses session |
Highest protection but not recommended |
system-prod.yml
Parameters of the configuration file used by the system
service in productive systems.
Parameters
Parameter | Description | Default Value | ||
---|---|---|---|---|
|
Services that do not belong to yuuvis® core but need to be informed about any changes of the schema. |
|
||
|
Integer value defining the maximum number of property definitions allowed in a tenant schema.
|
20 |
||
|
Integer value defining the maximum number of property definitions allowed in a tenant schema.
|
10000 |
commander-prod.yml
Configuration file containing configuration parameters for the commander
service.
Parameters
Parameter | Description | Default Value | |
---|---|---|---|
|
Integer number of connections to the database. At least 2 are required. |
2 |
|
|
Section of SSH connection parameters |
||
|
8022 |
||
|
|
||
|
|
||
|
|
Example Configuration
1
2
3
4
5
6
ssh:
shell:
port: 8022
user: 'root'
password: 'changeme'
history-file: commander-history.log
application-prod.yml
Configuration file containing configuration parameters for all services (including webhooks).
Parameters
Parameter | Description | Default Value | |
---|---|---|---|
|
Integer. Time in milliseconds. Limits the time that should be acceptable for the creation of a cluster-internal connection between two services. The connection attempt is interrupted if no connection could be established within the configured time. |
3000 |
|
|
Integer. Time in milliseconds. Limits the time between cluster-internal HTTP request and response. The processing of the request is interrupted if no response could be sent within the configured time. |
60000 |
Example Configuration
1
2
3
service:
connection-timeout-ms: 3000
socket-timeout-ms: 3600000
2.10.4. System Configuration Files
Configuration of the core system’s behavior via JSON files.
The yuuvis® Momentum service architecture makes each service retrieve configuration files from a central location managed by the configservice
. In addition to the profiles in YAML format, there are system configuration files in JSON format that can be used to adjust the core system’s behavior according to the customer’s needs.
Available Files
The list of system configuration JSON files and affected services. Click a file name to open a more detailed description and find available parameters.
systemHookConfiguration.json
- Configuration of system hooks, split in AMQP hooks and webhooks.
- Referenced by Services
-
authentication,api,commander
- Storage Location
-
-
global configuration file: Git system directory
-
app-specific configuration files (as of 2022 Summer): Git apps/<app name>/system directory
-
- Parameters
-
Parameter Type Description amqp
List of mappings in JSON format.
List of single AMQP Hook configurations each of them defined via following parameters. Read by API gateway and
commander
service.As of version 2021 Summer, placeholders can be used as provided by spring. They can reference values in the system environment including configuration files and command line arguments. The placeholders will be replaced by the referenced values of the environment variable during the starting process of the corresponding service. The syntax follows the spring placeholders: ${<reference>}.
bulkSize
integer
Maximum bulk size for a message.
enable
boolean
Specifies whether this configuration is active/enabled (
true
) or inactive/disabled (false
).password
string
Password for the AMQP server.
predicate
string
Condition that specifies when the AMQP hook is used. supported scripting languages: SpEL (Spring Expression Language) and JavaScript.
All properties that are available in the corresponding hook’s JSON request body can be referenced. Additionally, the tenant can always be referenced via
options['tenant']
.queue
string
Name of the queue to which the messages are written.
Only one messaging queue can be used. The messaging queue specified for the first defined AMQP hook will apply to all following AMQP hook definitions as well. The messaging system needs to support AMQP 1.0.
type
string
Defines the processing step during which the AMQP hook will be triggered.
url
string
AMQP server endpoint, e.g. 127.0.0.1:5672
user
string
Username for the AMQP server.
lifecycle
List of mappings in JSON format.
List of single lifecycle hook configurations each of them defined via following parameters. Read by
registry
service.If multiple lifecycle hooks are registered, the predicate is applied to the original predicate target for each of them and in the order of definition.
enable
boolean
Specifies whether this configuration is active/enabled (
true
) or inactive/disabled (false
).predicate
string
Condition that specifies when the webhook is used. Supported scripting languages: SpEL (Spring Expression Language) and JavaScript.
All properties that are available in the corresponding webhook’s JSON request body can be referenced. Additionally, the tenant can always be referenced via
options['tenant']
.type
string
Defines the processing step during which the webhook will be triggered. Only
dms.request.objects.upsert.database-before
available.tagname
string
The name of a tag matching the conventions for tagging.
If the corresponding tag
-
is already assigned, its
state
is replaced by the value specified viatagstate
parameter. -
is not yet assigned, it is added with the
state
value specified viatagstate
parameter.
tagstate
int
The value is used for the tag`s
state
.webhooks
List of mappings in JSON format.
List of single Webhook configurations each of them defined via following parameters. Read by
authentication
service and API gateway.If multiple Webhooks are registered for the same Webhook type, the predicate is applied to the original predicate target for each of them and in the order of definition.
enable
boolean
Specifies whether this configuration is active/enabled (
true
) or inactive/disabled (false
).predicate
string
Condition that specifies when the webhook is used. Supported scripting languages: SpEL (Spring Expression Language) and JavaScript.
All properties that are available in the corresponding webhook’s JSON request body can be referenced. Additionally, the tenant can always be referenced via
options['tenant']
.type
string
Defines the processing step during which the webhook will be triggered.
url
string
Endpoint to be called by the webhook if the predicate matches.
-
- Configuration File Management
-
It is possible to configure multiple system hooks having the same type. They are considered one after the other beginning from the top of the configuration file. If app-specific
systemHookConfiguration.json
files are specified (possible as of 2022 Summer), they are considered after the global configuration file and in alphabetical order.As of 2022 Summer, the
systemHookConfiguration.json
configuration files should be retrieved and updated via the yuuvis® Momentum endpoints listed below. The changes are applied immediately after a successful update of the configuration.-
GET /api/system/systemhooks
- Retrieve the globalsystemHookConfiguration.json
. -
POST /api/system/systemhooks
- Update the globalsystemHookConfiguration.json
. -
POST /api/system/systemhooks/validate
- Validate the globalsystemHookConfiguration.json
. -
GET /api/system/apps/{app}/systemhooks
- Retrieve the app-specificsystemHookConfiguration.json
. -
POST /api/system/apps/{app}/systemhooks
- Update the app-specificsystemHookConfiguration.json
. -
POST /api/system/tenants/{tenant}/apps/validate
- Validate the app-specificsystemHookConfiguration.json
.
-
- Example
-
The following example configures an AMQP hook, a lifecycle hook and a webhook.
-
The AMQP hook applies to object imports and checks the contentStreams for the presence of a range attribute. If the range attribute is detected, the AMQP hook recognizes the imported content to be a compound document and initiates asynchronous text extraction of all parts of the content.
-
The lifecycle hook adds a tag with the configured
name
andstate
to the created or updated DMS objects that match its predicate. -
The example webhook is triggered at every login and retrieves the roles of the user trying to authenticate.
Example System Hook Configuration{ "systemhooks": { "amqp": [ { "bulkSize": 10, "enable": true, "password": "secret", "predicate": "spel:(contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null && contentStreams[0]['range'].length() > 0) ? true : false", "queue": "lc.textextraction", "type": "object.insert.document", "url": "10.10.6.242:5672", "user": "clouduser" } ], "lifecycle": [ { "type": "dms.request.objects.upsert.database-before", "enable": true, "predicate": "spel:T(java.util.List).of('smallDocument').contains(properties['system:objectTypeId']['value']) && T(java.util.List).of(101).contains(options['action'])", "tagname": "system:ren:text", "tagstate": 1 } ], "webhooks": [ { "enable": true, "predicate": "spel:true", "type": "user.info", "url": "http://organization/api/userinfo/${tenant}/${userId}" } ] } }
-
serviceConfiguration.json
- Activation or deactivation of the contentanalyzer
in total, definition of a specific behavior via conditions.
- Referenced by Services
-
repository
,api
,audit
- Storage Location
-
Git system directory
- Parameters
-
The following parameters are available for the individual services:
Service / Parameter Description contentanalyzer
Section of Parameters determining the default behavior of the content analysis by
repository
service. The analysis of the content and/or mimeType can be requested or not, depending on defined conditions. If a condition matches during an import process, the content and/or mimeType will be analyzed.Within the import request body, this configuration can be overwritten by specifying the options parameters accordingly. The analysis of content and/or mimeType can be requested or suppressed even if the opposite behavior is configured in the file serviceConfiguration.json. ExampleSee default configuration below.
skip
Decides whether the service is used (
false
) or bypassed (true
).analyze
A list of property groups defining a specific behavior of the service depending on a conditions. For each condition, the determination of the mimeType and the text extraction can be activated or deactivated.
predicate
A condition specified in Spring Expression Language (SpEL).
mimetype
Decides whether the mimeType will be determined (
true
) or not determined (false
) if the condition matches.content
Decides whether the synchronous full-text extraction will be determined (
true
) or not determined (false
) if the condition matches.audit
Optional section of parameters determining the behavior of the
audit
service. If not specified, all actions are documented in the individual DMS object’s audit trail.Please be aware that the skipped audit entries are actually NOT CREATED ANYWHERE. The corresponding actions on DMS objects in your system will not be documented at all. Example"audit": { "skipAuditEntryCreation": false, "exclusions": { "actions": [401,301,101] } }
skipAuditEntryCreation
Boolean value that decides whether the creation of all audit entries is skipped (
true
) or not (false
).exclusions
A section of properties that can be used to specify events that should not be documented in the audit trail.
actions
A list of Integer action codes. The corresponding actions are not documented in the audit trail.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"services": {
"contentanalyzer": {
"analyze": [
{
"predicate": "spel:(properties != null && properties['Name'] != null && properties['Name']['value'] == 'disable') ? true : false",
"mimetype": true,
"content": false
},
{
"predicate": "spel:(contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null && contentStreams[0]['range'].length() > 0) ? true : false",
"mimetype": false,
"content": false
}
]
}
}
}
interceptorConfiguration.json
- Configuration of interceptors.
- Storage Location
-
Git system directory
- Parameters
-
The following parameters are available for the interceptor configuration:
Parameter Type Required Description type
String
yes
The type of the interceptor. It defines the position in the process flow where the interceptor can step in.
predicate
String
yes
The condition that triggers the redirection of the process flow in order to include the project-specific process extension. The string can provide the condition either in Spring Expression Language (SpEL) or Javascript. Thus, the string always has to start with a prefix spel: for SpEL or js: for Javascript.
url
String
yes
HTTP address of an external endpoint defining the project-specific process extension. Dynamic components (properties of the processed object) can be included in curly brackets.
useDiscovery
Boolean
no
Decides whether to resolve the url string at the Discovery-Service or not. If not specified, a default value is set.
- Interceptor Configuration Example
-
The following example configures an interceptor that will be trigger by every update of a content (action code 301). At the take-off point after the
repository
service, the enriched request body is passed to the external endpoint specified by url.To activate this configuration, the
repository
service needs to be restarted.Example interceptorConfiguration.json.1 2 3 4 5 6 7 8 9 10
{ "interceptors": [ { "type": "dms.request.objects.upsert.database-before", "predicate": "spel:options['action']==301", "url": "http://exampleinterceptorcontentupdate/api/dms/objects/upsert", "useDiscovery": true } ] }
Configuration in Kubernetes
Configuration during Installation
You can set the configuration parameter values in advance during installation.
The configuration parameters are set in the file values.yaml
of the yuuvis
Helm chart. Modify a value of the listed parameters or add one of the available parameters listed in the above linked fact sheet of the corresponding system configuration file with your desired value to overwrite its default value.
In order to add an interceptor configuration, add a section interceptorConfiguration
to the file values.yaml
and specify your desired parameters. Add an entry interceptorConfiguration.json
to the systemconfigmap.yaml
in the yuuvis/templates
folder and reference your section interceptorConfiguration
in values.yaml
.
During the deployment, the settings defined in the file values.yaml
will be written into the system configuration files that are read by the services when they are started.
Changing Configuration of a Running System
For changes on a running system, you need to access your Git server.
Navigate to the system directory of the configuration git repositories' appropriate branch and find a list of the configuration files including the above listed profiles. Open the file, modify it, and check in your changes.
After the modification of a system configuration file you need to restart the services that reference the file in order to apply the changes.
2.10.5. Service-specific Configurations
Configuration parameters for specific core services.
The yuuvis® Momentum configuration files for the operation in the Kubernetes cluster are stored on the Git Server configured in the system. In order to change the configuration of a service, you need to access the Git repository.
Configuration of 'api' Gateway
Parameters in Profile-related Configuration Files
The following Parameters can be set in any YAML configuration file that is activated via profile.
Parameter | Description | |
---|---|---|
|
As of 2023 Autumn. Allows to add custom endpoints to the API provided via The It ist NOT possible to overwrite existing endpoints of the Example
Considering the example configuration, a call |
|
|
Required. Custom endpoint URL that will be available via |
|
|
Optional. Comma-separated list of HTTP methods. If configured, only the calls of specified HTTP methods are allowed for the specific If not configured, calls of all HTTP methods are allowed. |
|
|
Required. URL of the custom service within the cluster. Requests to the configured
|
Configuration of 'archive' Service
Parameters application-storage.yml
:
-
storage.repositories
-
storage.profiles
Configuration of 'audit' Service
Service-specific Parameters
Parameter | Type | Default value | Description | ||
---|---|---|---|---|---|
|
Integer |
-1 |
Controls the automated recalculation of the storage metric. If the value is -1, there is no automated recalculation. It has to be triggered via the If any value > 0 is configured, it is considered as time in seconds between two automated recalculation processes. As soon as the specified time is passed after the previous recalculation process, a new recalculation process is triggered.
|
||
|
Integer |
3600 |
Controls the behavior of the storage metric recalculation processing in fail situations like, e.g., an unavailable service. The configured value is considered as maximum time in seconds that the process waits for progress in the database. The database reports a progress after the recalculation for one tenant is done. If the database does not report ongoing progress for a time period that exceeds the configured value, the recalculation is restarted. |
Parameters in Profile-related Configuration Files
The following parameters are referenced from the application-dbs.yml
configuration file:
-
storage
Parameters in Service Configuration File
The audit
section in the serviceConfiguration.json
file can be used to skip the creation of audit entries for specific actions or for all actions.
Configuration of 'authentication' Service
Parameters application-oauth2.yml
:
-
keycloak.host
-
authentication.oauth2.tenants
Parameters in authentication-prod.yml
:
-
routing.defaultEntryPoint
-
management.endpoints
-
management.endpoint
-
authorization.accesses
Running Multiple Instances
As the number of users increases, more instances may be started for the authentication
service to maintain performance. To ensure that the session status of logged-in users is available to all instances, it is stored centrally in a Redis database. This way, users do not have to log in again after a temporary system failure. Their respective service state is stored in a Redis database, and is retrieved by the system after all instances are restarted. The users' session states remain in the Redis database until the sessions have expired or are removed by the users' logging off. If an instance of the authentication
service is unavailable for any reason, an instance running in parallel can take over without the user having to log in again. In this way, the authentication
service is both fail-safe and scalable.
For example, instance 2 can be restarted using the following command:
kubectl -n yuuvis scale deploy authentication --replicas=2
Configuration steps for versions 2022 Spring - 2023 Autumn.
To allow the storage of individual user session states in the designated Redis database, follow these steps to modify the authentication
service configuration:
-
Extend the
authentication-prod.yml
configuration file by the following lines:spring.session.store-type: redis management.health.redis.enabled: true
-
Add the redis profile to the
authentication
service:-
Run the command:
kubectl -n yuuvis edit deploy authentication
-
Extend the
SPRING_PROFILES_ACTIVE
environment variable with redis.
-
-
Restart all instances of the
authentication
service.-
For example, instance 2 can be restarted using the following command:
kubectl -n yuuvis scale deploy authentication --replicas=2
-
Embedding in an External Web Page as iframe
-
Create an Ingress for HTTPS that enables access to all resources for the tenant selection page via Content-Security-Policy-Header.
nginx.ingress.kubernetes.io/configuration-snippet: | add_header Content-Security-Policy "frame-ancestors 'self' http://portal.org/ http://portal.org:*/; style-src 'self' 'unsafe-inline' https://unpkg.com/ https://fonts.googleapis.com/; font-src 'self' 'unsafe-inline' https://fonts.gstatic.com/;" always;
-
Replace
portal.org
by your custom URL of the external web page. -
The tenant selection page loads further resources from link:https://unpkg.com/ and link:https://fonts.googleapis.com/.
-
For embedding a client application, further configuration might be necessary.
-
-
Configure your identity provider for the access via iframe (Example: Keycloak iframe configuration).
-
Configure the following parameters in the
authentication-prod.yml
configuration file:server.servlet.session.cookie.same-site: 'None' server.servlet.session.cookie.secure: true
-
Refresh the
configservice
. -
Restart the
authentication
service.
Configuration of 'configservice'
Open description of deprecated version 2021 Autumn…
The configservice
can retrieve the cached version of configuration files even if the git is temporarily not accessible. Thus, during a downtime of the git server, GET requests to the configservice
will be successful whereas requests for storing resources will not be successful. The behavior is controlled via the boolean value of the the service-internal parameter fail-if-git-not-available in case the git server is temporarily not accessible.
Value for 'fail-if-git-not-available' | Behavior of 'configservice' during temporary downtime of the git server |
---|---|
|
Retrieval of cached resource files during git server downtime is enabled. |
|
Any request for a resource file via |
Per default, the configservice
uses the persistent volume at /tmp/configservice
for initialization during a restart. Alternatively, the configservice
can delete and recreate the directory /tmp/configservice
by cloning the remote resources during the initialization. This behavior can be applied by one of the following configurations:
-
Set
resume-from-local-git: false
in theapplication-prod.yml
configuration file. -
Set the environment variable
RESUME-FROM-LOCAL-GIT=false
in the Kubernetes deployment of theconfigservice
(default istrue
).
Configuration of 'repository' Service
Parameters in 'application-storage.yml'
-
storage.default-rendition-repository
(as of 2021 Winter) -
storage.repositories
-
storage.profiles
Find details in the application-storage.yml
description.
Parameters in 'serviceConfiguration.json'
Parameters in the serviceConfiguration.json
configuration file can be used to change the default behavior of the content and/or mime type analysis. The analysis can be requested or not, depending on the defined conditions. If a condition matches during an import process, the content and/or mime type will be analyzed.
Within each import request body, this configuration can be overwritten by specifying the options parameters accordingly. The analysis of content and/or mime type can be requested or suppressed even if the opposite behavior is configured in the file serviceConfiguration.json .
|
Furthermore, it is possible to set the extraction.maxTextLengthInKB
and mimetype.extension.redetection
parameters in a service-specific YAML configuration file for the repository
service as described in the next section.
Parameters in any YAML configuration file
Parameters in any configuration file read by the repository
service (application-storage.yml
or repository-prod.yml
), for example.
To ensure downward compatibility with configurations older than 2024 Summer, the repository
service reads the contentanalyzer-prod.yml
configuration file as well.
Parameter | Type | Description | Default | ||
---|---|---|---|---|---|
|
Long |
Specifies the time limit for the partial upload of a large binary content file in days. Each upload process that exceeds the configured time is removed from the
|
2 |
||
|
boolean |
If you need text extraction for large binary content files of Microsoft Office file types, the
|
|
||
|
integer |
Limit for the length of extracted full-text. If an extraction process reaches the limit, it is stopped and the full-text created till then is stored.
|
2048 |
||
|
comma-separated list of mime types |
The standard calculation is based on the analysis of the binary content itself. In case a determined mime type is wrong, it is possible to reanalyze the file considering the file ending. The mime types for which this second analysis step should be triggered are listed here. |
|
Configuration of 'system' Service
Parameters in the system-prod.yml
configuration file:
-
schema.changed.observers
-
schema.tenant.properties.limit
-
schema.global.properties.limit
2.10.6. Logging Configuration
Logs provide information on processes within individual instances of services that are running in the yuuvis® Momentum cluster. Their outputs are managed and provided via Kubernetes. The log level can be configured in order to show more or less process details. The configuration can be adjusted during the installation process, but also for systems that are already in operation.
Hierarchical Configuration
The logging can be configured hierarchically by means of the underlying java package structure. In this description, the placeholder <packageName>
is used.
-
If it is replaced by a specific class (e.g.,
com.os.services.package.subpackage.MyFirstExampleClass
), only the configuration for the logging provided by this class is affected. -
If it is replaced by a package name at a higher hierarchical level (e.g.,
com.os.services
), all classes included in the package are affected.
Configuration Possibilities
Service Deployment during Installation
In the individual service configuration YAML files, the log level can be configured during installation. The desired log level can be specified in the value for the JAVA_OPTS
parameter via -D
as shown in the example code block below.
spec.template.spec.containers:
- env:
- name: JAVA_OPTS
value: -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Dlogging.level.com.os.services=DEBUG
To specify multiple logging configurations, separate them with a space as shown in the following example:
spec.template.spec.containers:
- env:
- name: JAVA_OPTS
value: -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -Dlogging.level.com.os.services.package.subpackage.MyFirstExampleClass=DEBUG -Dlogging.level.com.os.services.package.subpackage.MySecondExampleClass=DEBUG
Configuration Files of Running Systems
The logging configuration for yuuvis® Momentum systems that are already in operation can be adjusted via profile-specific configuration files.
Specify the log level in the <serviceName>-prod.yml
configuration file in order to configure it for the service that reads the file. The following line, e.g., activates the DEBUG
log level:
logging.level.com.os.services: DEBUG
The target service has to be refreshed or restarted in order to activate the new logging configuration.
Endpoints '//manage/loggers/*'
The logger management endpoints are accessible only for users with specific authorization as defined in the authentication-prod.yml
file and controlled by the authentication
service.
-
Retrieving Information on Loggers
It is possible to retrieve an overview of all loggers that are defined for a specific service via the GET endpoint
http://<ip>:<port>/manage/loggers
. For each logger, the current log level is displayed as shown in the example response body.Example response body{ "levels": [ "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" ], "loggers": { "ROOT": { "configuredLevel": "WARN", "effectiveLevel": "WARN" }, "application": { "configuredLevel": "WARN", "effectiveLevel": "WARN" }, "auditEntryAggregator": { "configuredLevel": null, "effectiveLevel": "WARN" } } }
-
Updating Log Levels
In order to set a log level at runtime, it can be specified in JSON format as shown in the example below and sent as request body to the POST endpoint
http://<ip>:<port>/manage/loggers/<packageName>
.Example request body{"configuredLevel":"DEBUG"}
The change applies immediately to the service instance running on the target port. After a restart of this service, the log level is reset to the value configured in a configuration file as described before.
2.11. API
The API gateway is the core service that provides all public REST endpoints of yuuvis® Momentum core.
2.11.1. DMS Endpoints
Manage DMS objects in yuuvis® Momentum or retrieve structural information for the tenant that are relevant for all its users.
In the default configuration, any logged-in user has access to the endpoints. However, the creation, retrieval, update and deletion of DMS objects require corresponding roles.
As of version 2022 Autumn, some processes that lead to an update of the index of the search engine can be called with the query parameter waitForSearchConsistency
.
Apps Information
GET /api/dms/apps
- Retrieve all applications for the tenant.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves all apps available in the tenant the currently logged-in user belongs to.
- Response Example
-
{ "acl" : { }, "client" : { }, "clientsystem" : { }, "email" : { }, "invoice" : { }, "training" : { } }
Product Information
GET /api/dms/info
- Retrieves installed product version.
- As of Version
-
2022 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Successful authentication
- Description
-
Retrieves information on the installed product version.
- Request Example
-
/api/dms/info
- Response Example
-
{ { { "info": { "productLine": "yuuvis Momentum", "systemVersion": "yuuvis Momentum - 2021 Winter", "dmsVersion": "4.10.0-SNAPSHOT" } } } }
Basic CRUD Operations
POST /api/dms/objects
- Store one or more new DMS objects
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
action
create
- Description
-
To import one or more DMS objects send the request with metadata and content as multipart request body. The response is a JSON structure containing the metadata of all objects created.
Available content stream properties are listed here.
If even one object could not be imported, the whole request fails.
As of 2022 Autumn, the optional query parameter
waitForSearchConsistency
can be added to the request URL. If not specified, the default valuefalse
is used. - Request Header
-
Content-Type: multipart/form-data
- Request Example
-
The request example represents the complete multipart for the import of an e-mail. In addition to the metadata and the e-mail content, a text rendition is also imported.
POST /api/dms/objects HTTP/1.1 Accept: application/json, application/*+json Content-Type: multipart/form-data;boundary=Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH User-Agent: Java/1.8.0_60 Connection: keep-alive Content-Length: 83258 Host: 127.0.0.1:7400 --Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH Content-Disposition: form-data; name="data" Content-Type: application/json;charset=UTF-8 { "objects": [{ "properties": { "system:objectTypeId": { "value": "appEmail:email" }, "from": { "value": "Garco Meissler <garco@example.de>" }, "to": { "value": "Dudreas Annkel <dudreas@example.de>" }, "cc": { "value": "Kruedeas Anger <kruedeas@example.de>" }, "subject": { "value": "Bewerbungsunterlagen" } }, "contentStreams": [{ "mimeType": "message/rfc822", "fileName": "upload.eml", "cid": "cid_63apple" }], "renditions": [{ "mimeType": "text/plain", "kind": "text", "contentStream": { "length": 39939, "mimeType": "text/plain", "fileName": "content.txt", "cid": "rendition_0" } }], "options": { "synchronousContentAnalysis": true } }] } --Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH Content-Disposition: form-data; name="cid_63apple"; filename="upload.eml" Content-ID: cid_63apple Content-Type: message/rfc822 From: Garco Meissler <garco@example.de> To: Dudreas Annkel <dudreas@example.de> Cc: Kruedeas Anger <kruedeas@example.de> Message-ID: <12716821.1.1500391295036.JavaMail.meissler@APGMEISSLER> Subject: =?UTF-8?Q?Bewerbungsunterlagen?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_0_16468615.1500391295024" ------=_Part_0_16468615.1500391295024 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ei= rmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam volu= ptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita k= asd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lore= ... en, no sea takimata sanctus est Lore ------=_Part_0_16468615.1500391295024-- --Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH Content-Disposition: form-data; name="rendition_0"; filename="content.txt" Content-ID: rendition_0 Content-Type: text/plain Content-Length: 39939 Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua... --Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH
data
The metadata is passed in JSON format in the data part of the multipart request body.
cid_63apple
The e-mail content is referenced by a content ID ("cid": "cid_63apple") in the contentStreams part of the metadata.
This content ID appears again in the multipart request body below and represents the e-mail content.
rendition_0
The text rendition is represented by a contentStream object in the renditions part of the metadata.
This contentStream object references to a content part of the multipart request body with Content-ID: rendition_0.
options
Optional arguments for steering the processing engine dynamically.
-
synchronousContentAnalysis
: true|false (default value: true) Skip synchronous processing of the content (no full-text extraction) in the content analyzer service.to disable the content analyzer service in general, use the "skip":"true" parameter in the JSON configuration file (Git for configuration, …/system/serviceConfiguration.json) for the "contentanalyzer" service.
-
- Result Example
-
The result is a JSON structure containing the metadata of the e-mail object created.
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-26T15:21:170Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>"] }, "appEmail:subject": { "value": "Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }] }
PATCH /api/dms/objects
- Patch-update metadata of multiple objects by ID
- As of Version
-
2021 Autumn
- Request Method
-
PATCH
- Response Format
-
JSON
- Required Permission
-
action
write
andread
- Request Header
-
Content-Type: application/json
- Description
-
Updates metadata in multiple objects specified by ID in the JSON request body.
Each
objectId
must not be referenced more than once per request body. And each entry in the objects list must contain thesystem:objectId
property with a valid ID.The number of objects that can be updated via this endpoint is limited to 100.
Changes only those properties that are part of the request body. Properties that are missing in the request body are not changed by the update. A property value can be removed by sending null as the new value.
Most system properties cannot be updated by users. They are updated automatically by the repository if necessary. If the request metadata contains these system properties, their values must match the values of the current version.
For example, you could add the
system:versionNumber
system property with the value of the current version to the request metadata. Usually, the update attempt will be successful. However, if another update has changed the object in the meantime, which means that thesystem:versionNumber
has been increased, your update attempt will fail.Up to 2023 Autumn: Even if only one object could not be updated, the entire request fails.
As of 2023 Winter, the optional boolean query parameter
greedy
is available. It allows to continue the request to update as many objects as possible (find details below). The result has always the HTTP status code 207 and a JSON response body containing all requested objects. Theoptions
section of each individual object containssystem:response
, which documents the success/failure viahttpStatusCode
,serviceErrorCode
(if available) andmessage
. Additionally, for the successfully updated objects, the full set of metadata is provided.Optional query parameters:
Parameter Type Description waitForSearchConsistency
boolean
As of 2022 Autumn. Find a detailed description here. If not specified, the default value
true
is used.greedy
boolean
As of 2023 Winter. Allows to continue the request to update as many objects as possible.
-
If
greedy
isfalse
(default), the entire request fails if at least one object could not be updated. -
If
greedy
istrue
, the request is executed on all listed objects on which the update is possible.
-
- Request Example
-
Consider the request body below with (A)
greedy=false
and (B)greedy=true
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "appEmail:subject": { "value": "new subject" } }, "properties": { "system:objectId": { "value": "invalid" }, "appEmail:subject": { "value": "new subject" } } } ] }
- Response Example
-
In the example response body above, one object is invalid. Thus, the result depends on the value of the
greedy
query parameter.(A) Response for
greedy=false
:{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "appEmail:subject": { "value": "new subject" } }, "options": { "system:response": { "httpStatusCode": 422, "serviceErrorCode": 0, "message": "Not updated. Process stopped due to conflicts with other objects in the batch." } } }, { "properties": { "system:objectId": { "value": "invalid" }, "appEmail:subject": { "value": "new subject" } }, "options": { "system:response": { "httpStatusCode": 404, "serviceErrorCode": 2811, "message": "Object not found. Objectid: invalid" } } } ] }
(B) Response body for
greedy=true
:{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-30T11:53:227Z" }, "system:versionNumber": { "value": 3 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:subject": { "value": "new subject" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" } ], "options": { "system:response": { "httpStatusCode": 200, "message": "Object updated." } } }, { "properties": { "system:objectId": { "value": "invalid" }, "appEmail:subject": { "value": "new subject" } }, "options": { "system:response": { "httpStatusCode": 404, "serviceErrorCode": 2811, "message": "Object not found. Objectid: invalid" } } } ] }
Further examples for
system:response
:Example 1: successfully processed sub-request"system:response": { "httpStatusCode": 200, "message": "Object updated." }
Example 2: failed sub-request"system:response": { "httpStatusCode": 404, "serviceErrorCode": 2811, "message": "Object not found. Objectid: invalidId" }
Example 3: failed sub-request"system:response": { "httpStatusCode": 403, "serviceErrorCode": 2810, "message": "Insufficient permissions to perform a 'WRITE' action. IDs: cdc7095f-a5ce-486d-92a7-6d0955d969ee" }
Example 4: failed sub-request"system:response": { "httpStatusCode": 422, "serviceErrorCode": 2607, "message": "Illegal property. An object of type 'appEmail:email' cannot have a property named 'syfdstem:rmExpirationDate'." }
Example 5: failed sub-request ('greedy=false')"system:response": { "httpStatusCode": 422, "serviceErrorCode": 0, "message": "Not updated. Process stopped due to conflicts with other objects in the batch." }
- Deprecated Response Example
-
Deprecated as of 2023 Winter.
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2021-03-12T11:53:227Z" }, "system:versionNumber": { "value": 3 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:subject": { "value": "again updated Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }, { "properties": { "system:objectId": { "value": "cdc7106f-a5ce-597d-92a7-1d1166d171ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "tenTenant1:personalfile" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2021-01-26T15:21:130Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2021-03-12T11:53:227Z" }, "system:versionNumber": { "value": 5 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "08a46960dbb5c546" }, "tenTenant1:department": { "value": "dev" }, "tenTenant1:team": { "value": "frontend" }, "tenTenant1:recruitment": { "value": "2021-02-01T08:00:000Z" } } }] }
DELETE /api/dms/objects
- Delete multiple objects by ID
- As of Version
-
2021 Winter
- Request Method
-
DELETE
- Response Format
-
JSON
- Required Permission
-
action
delete
andread
- Request Header
-
Content-Type: application/json
- Description
-
Deletes multiple objects specified by ID in the JSON request body.
The number of objects that can be deleted simultaneously via this endpoint is limited to 100.
If other properties beside
system:objectId
are specified in the request body, they are ignored. Especially, the result list of a search response can thus directly be sent as request body to delete all included objects.The individual deletion sub-processes follow the procedure described for the
DELETE /api/dms/objects/{objectId}
endpoint.As of 2023 Summer, the optional query parameter
waitForSearchConsistency
can be added to the request URL. If not specified, the default valuetrue
is used.As of version 2023 Spring, the optional boolean query parameter
greedy
(defaultfalse
) is available.-
If
greedy=false
, the entire request fails as soon as one of the referenced objects cannot be found or cannot be deleted. -
If
greedy=true
, the deletion process is continued by deleting as many referenced objects as possible. __
A proper response of the endpoint is structured as follows:
-
The HTTP status code is always 207.
-
The JSON response body contains the DMS objects (completed as far as possible) that were referenced by objectId in the request body.
-
Each DMS object has an options section containing the system:deletionResult with httpStatusCode, serviceErrorCode and message for the individual deletion process as displayed in the example response below.
-
Meaning of the individual values for
httpStatusCode
:-
200 OK
- The object was deleted. -
403 Forbidden
- Insufficient permissions for the object. -
404 Not Found
- The object ID was not found. -
409 Conflict
- The deletion is not allowed as it is against the rules (e.g., non-empty folder or document under retention). -
422 Unprocessable Entity
- Other objects within the request could not be deleted andgreedy=false
.
-
-
- Request Example
-
/api/dms/objects?greedy=false
The object IDs of the objects to be deleted are passed in the request body in JSON format.
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" } } }, { "properties": { "system:objectId": { "value": "903f2ae8-2cfc-476c-8386-55c6811e41da" } } }, { "properties": { "system:objectId": { "value": "invalid" } } }, { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" } } }] }
- Response Example
-
HTTP status code 207
As
greedy=false
was set, the last object was not deleted because other objects within the request could not be deleted.{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:traceId": { "value": "1234567887654321" }, "system:objectTypeId": { "value": "appFolder:akte4" }, "system:lastModificationDate": { "value": "2023-02-14T14:53:11.690Z" }, "system:versionNumber": { "value": 1 }, "appFolder:title": { "value": "folderwithcontent" }, "system:baseTypeId": { "value": "system:folder" }, "system:tenant": { "value": "tenant1" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2023-02-14T14:53:11.690Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" } }, "options": { "system:deletionResult": { "httpStatusCode": 409, "serviceErrorCode": 2800, "message": "A non-empty folder cannot be deleted." } } }, { "properties": { "system:objectId": { "value": "903f2ae8-2cfc-476c-8386-55c6811e41da" }, "system:traceId": { "value": "1234567887654321" }, "system:objectTypeId": { "value": "appFolder:akte4" }, "system:lastModificationDate": { "value": "2023-02-14T14:53:11.690Z" }, "system:versionNumber": { "value": 1 }, "appFolder:title": { "value": "undeletable" }, "system:baseTypeId": { "value": "system:folder" }, "system:tenant": { "value": "tenant1" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2023-02-14T14:53:11.690Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" } }, "options": { "system:deletionResult": { "httpStatusCode": 403, "serviceErrorCode": 2810, "message": "Insufficient permissions to perform an 'DELETE' action. IDs: 7b7616c0-c03d-47ee-9664-4b6d9e5ca8a1" } } }, { "properties": { "system:objectId": { "value": "invalidId" } }, "options": { "system:deletionResult": { "httpStatusCode": 404, "serviceErrorCode": 2811, "message": "Object not found. Objectid: invalidId" } } }, { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:traceId": { "value": "1234567887654321" }, "system:objectTypeId": { "value": "appFolder:akte4" }, "system:lastModificationDate": { "value": "2023-02-14T14:53:11.690Z" }, "system:versionNumber": { "value": 1 }, "appFolder:title": { "value": "deletablefolder" }, "system:baseTypeId": { "value": "system:folder" }, "system:tenant": { "value": "tenant1" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2023-02-14T14:53:11.690Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" } }, "options": { "system:deletionResult": { "httpStatusCode": 422, "serviceErrorCode": 0, "message": "Not deleted. Process stopped due to conflicts with other objects in the batch." } } } ] }
POST /api/dms/objects/search
- Search for objects by search query
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
action
read
- Description
-
To query DMS objects, send the request with the search query as request body.
The search query is passed in the request body in JSON format. The query language based on CMIS serves to standardize DMS requests to the yuuvis® API system.
Each search request for DMS objects always returns an array of DMS objects called
objects
, even if the result set is only a single object. I.e,. if a single object is requested, the result is a single-element array, given the object exists. Otherwise, the result is an empty array. The result contains only objects that are visible with aread
permission.If not otherwise specified in the query statement, the result list is ordered by the
system:creationDate
object property.The parameter
maxItems
defines the maximum number of entries in the hit list, while skipCount defines the number of entries to be skipped in the beginning of the result list. This allows for a client-side implementation of paging. - Request Header
-
Content-Type: application/json
- Request Example
-
The search query is passed in the request body in JSON format
{ "query": { "statement": "SELECT * FROM system:object", "skipCount": 0, "maxItems": 50 } }
- Response Example
-
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-26T15:21:170Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>"] }, "appEmail:subject": { "value": "Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }, { "properties": { "system:objectId": { "value": "903f2ae8-2cfc-476c-8386-55c6811e41da" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-02-02T15:14:09.380Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-02-02T15:17:16.670Z" }, "system:versionNumber": { "value": 3 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "7603680281439810506" }, "appEmail:from": { "value": "Ram Evalow <evalow@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:subject": { "value": "Der Fischer und seine Seele" }, "appEmail:attachmentcount": { "value": 2 }, "appEmail:attachmentnames": { "value": ["Der_Fischer_und_seine_Seele.pdf", "blackhair_nixe.jpg"] } }, "contentStreams": [{ "contentStreamId": "B3172D83-BDB5-11E8-B133-074F092B56CB", "length": 431397, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "11857B6FAD61E41AFB3E7398BA1BA4BFB6B0A5422762FF41A0907BC0BFF7748F", "repositoryId": "repo252" }] }], "numItems": 2, "hasMoreItems": false, "totalNumItems": 2 }
Property Description objects
array of DMS objects
properties
metadata fields, basic parameters and system fields of an object
GET /api/dms/objects/{objectId}
- Retrieve object metadata by ID
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
action
read
- Description
-
To retrieve the metadata of a DMS object, send the request with the ID of the DMS object as
objectId
.Exclusively for this endpoint, you can use the
includePermissions
query parameter to define, whether the information on permissions is part of the result (true
) or not (false
). Default value isfalse
.As of 2022 Summer, retentions are considered for the display of the available permissions. Thus, if the requested object is under retention, the
delete
permission is not available and thewrite
permission can only be made available for metadata. - Request Example
-
Example (A)
/api/dms/objects/cdc7095f-a5ce-486d-92a7-6d0955d969ee
Example (B)
/api/dms/objects/cdc7095f-a5ce-486d-92a7-6d0955d969ff?includePermissions=true
- Result Example
-
Example (A)
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-26T15:21:170Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>"] }, "appEmail:subject": { "value": "Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }] }
Example(B)
{ "objects": [ { "properties": { "system:traceId": { "value": "97a35859dbb4c436" }, "system:objectTypeId": { "value": "appMyapp:mydocumenttype" }, "system:secondaryObjectTypeIds": { "value": [ "system:rmDestructionRetention" ] }, "appMyapp:name": { "value": "testdocument" }, "system:versionNumber": { "value": 1 }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:rmExpirationDate": { "value": "2042-03-16T17:44:54.410Z" }, "system:creationDate": { "value": "2022-03-16T13:03:52.720Z" }, "system:lastModificationDate": { "value": "2022-03-16T13:03:52.720Z" }, "system:baseTypeId": { "value": "system:document" }, "system:tenant": { "value": "tenant1" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ff" } }, "contentStreams": [ { "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A8", "archivePath": "default/DOCUMENT/00/A9/9/", "length": 23, "mimeType": "text/plain", "fileName": "myfilename.txt", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B856", "repositoryId": "repo252es" } ], "permissions": { "read": [ "metadata", "content" ], "create": [ "metadata", "content" ], "write": [ "metadata" ] } } ] }
POST /api/dms/objects/{objectId}
- Update object metadata by ID
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
action
write
andread
- Request Header
-
Content-Type: application/json
- Description
-
To update the metadata of a DMS object, send the request with the new metadata as request body and the ID of the DMS object as
objectId
.If a property is missing in the new metadata, it will be removed from the object. An expection are system properties. Most system properties cannot be updated by users. They are updated automatically by the repository if necessary. If the new metadata contains these system properties, their values must match the values of the current version. This can be used to ensure object consistency in case of overlapping update requests.
As of 2022 Autumn, the optional query parameter
waitForSearchConsistency
can be added to the request URL. If not specified, the default valuetrue
is used.To update individual properties, retrieve the current metadata using the
GET /api/dms/objects/{objectId}
endpoint. In the result, edit only those properties that need to be updated and then post the entire result using this endpoint. Due to the mentioned special behavior of some system properties this update attempt will fail, if another update on this object has happened in the meantime. In this case, at least the propertysystem:versionNumber
of the current version would have changed and does not match thesystem:versionNumber
of the request metadata anymore. - Request Example
-
The new metadata is passed in the request body in JSON format.
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-26T15:21:170Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>", "Vils Normum <Normum@example.de>"] }, "appEmail:subject": { "value": "Updated Bewerbungsunterlagen" }, "table": { "columnNames": ["iColumn1", "iColumn2", "iColumn3"], "value": [["something", "to know", true],["more", "infos", false]] } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }] }
- Response Example
-
The result is a JSON structure containing the updated metadata of the object identified by
objectId
.{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-29T13:13:113Z" }, "system:versionNumber": { "value": 2 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>", "Vils Normum <Normum@example.de>"] }, "appEmail:subject": { "value": "Updated Bewerbungsunterlagen" }, "table": { "columnNames": ["iColumn1", "iColumn2", "iColumn3"], "value": [["something", "to know", true],["more", "infos", false]] } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }] }
POST /api/dms/objects/{objectId}
- Multipart Endpoint: Update metadata and content.
- As of Version
-
2024 Spring
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
action
write
andread
- Description
-
Updates metadata and content of an existing DMS object. The request contains the new metadata and content as multipart request body. The response is a JSON structure containing the metadata of the updated object.
Available content stream properties are listed here.
If the request is successfully processed (metadata and content are replaced), a new audit entry 302 (OBJECT_METADATA_DOCUMENT_CHANGED) is created.
The binary content remains unchanged in the following cases. Consequently, an audit entry 300 is created:
-
Only metadata are specified in the multipart request and the
contentStreams
section is missing. -
The
contentStreams
section exists and contains only values that equal the previous object version, but does not contain acid
.
Tags without the
resistant
suffix are removed from the object. However, it is possible to reassign them with newstate
and/ortraceId
if specified in the metadata section. -
- Request Header
-
Content-Type: multipart/form-data
- Request Example
- Result Example
PATCH /api/dms/objects/{objectId}
- Patch-Update object metadata by ID
- As of Version
-
2019 Winter
- Request Method
-
PATCH
- Response Format
-
JSON
- Required Permission
-
action
write
andread
- Request Header
-
Content-Type: application/json
- Description
-
To update the metadata of a DMS object, send the request with the new metadata as request body and the ID of the DMS object as
objectId
.Changes only those properties that are part of the request body. Properties that are missing in the request body are not changed by the update. A property value can be removed by sending null as the new value.
Most system properties cannot be updated by users. They are updated automatically by the repository if necessary. If the request metadata contains these system properties, their values must match the values of the current version.
For example, you could add the system property
system:versionNumber
with the value of the current version to the request metadata. Usually, the update attempt will be successful. However, if another update has changed the object in the meantime, which means that thesystem:versionNumber
has been increased, your update attempt will fail.As of 2022 Autumn, the optional query parameter
waitForSearchConsistency
can be added to the request URL. If not specified, the default valuetrue
is used. - Request Example
-
The new metadata is passed in the request body in JSON format.
{ "objects": [{ "properties": { "appEmail:subject": { "value": "again updated Bewerbungsunterlagen" }, "appEmail:cc": { "value": null } } }] }
- Result Example
-
The result is a JSON structure containing the updated metadata of the object identified by
objectId
.{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-30T11:53:227Z" }, "system:versionNumber": { "value": 3 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:subject": { "value": "again updated Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }] }
DELETE /api/dms/objects/{objectId}
- Delete object by ID
- As of Version
-
1.0
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
action
delete
andread
- Description
-
Deletes the object specified by
objectId
.All old versions of the object are deleted as well.
The assigned binary content files are only deleted from the repository if no other object or object version refers to them.
In the audit trail, the entries 202 and 200 are created. All previous audit entries for the deleted object remain in the database and can still be retrieved via search.
A folder object can only be deleted if it has no child objects, means if there are no objects retrievable via yuuvis® Momentum API that have the specified objectId as value for the
system:parentId
property.Meaning of the response status codes:
HTTP status code Meaning 200 OK
The DMS object with the ID objectId has been deleted
403 Forbidden
Insufficient permissions to perform a delete action.
404 Not Found
The DMS object with the ID objectId can not be found.
409 Conflict
The DMS object with the ID objectId could not be deleted due to retention.
- Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da
- Response Example
-
no response body
GET /api/dms/objects/{objectId}/contents/file
- Retrieve document content by ID
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
binary data
- Required Permission
-
action
read
- Description
-
To get the content file related to a DMS object, send the request with the ID of the DMS object as
objectId
. - Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/contents/file
POST /api/dms/objects/{objectId}/contents/file
- Update document content by ID
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
action
write
andread
- Description
-
To update the content file of a DMS object, send the request with the new content file as binary in the request body and the ID of the DMS object as
objectId
.A new object version will be created. The corresponding Content Stream Properties are automatically updated.
The new binary content file is stored in the repository specified in the
X-OS-REPOSITORY-ID
request header. If the header is missing, the default repository is used that is configured in theapplication-storage.yml
configuration file.If tags are assigned to the object, they will be reassigned to the new object version only if they are specified as resistant tags.
As of 2022 Autumn, the optional query parameter waitForSearchConsistency can be added to the request URL. If not specified, the default value true is used.
- Request Header
-
Content-Type: application/octet-stream. Any content-type is accepted.
Content-Disposition: attachment; filename=<filename>; filename*=<filename-encoded>. To set the filename of the new content file. The parameters "filename" and "filename*" differ only in that "filename*" uses the encoding defined in RFC 5987. When both "filename" and "filename*" are present in a single header field value, "filename*" is preferred over "filename".
- Request Example
-
The new content file is passed as binary in the request body.
- Response Example
-
The result is a JSON structure containing the updated metadata of the object identified by
objectId
.{ "objects": [ { "properties": { "system:objectId": { "value": "6200fcc9-d6b4-43c0-82e7-ac1ed2fa8350" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:secondaryObjectTypeIds": { "value": [ "system:rmDestructionRetention" ] }, "system:createdBy": { "value": "root" }, "system:creationDate": { "value": "2018-09-10T14:35:36.657Z" }, "system:lastModifiedBy": { "value": "root" }, "system:lastModificationDate": { "value": "2018-09-10T15:03:17.099Z" }, "system:versionNumber": { "value": 3 }, "system:tenant": { "value": "default" }, "system:traceId": { "value": "-7589750308987031207" }, "system:contentStreamLength": { "value": 3726 }, "enaio:contentStreamMimeType": { "value": "message/rfc822" }, "system:contentStreamFileName": { "value": "upload.bin" }, "system:contentStreamId": { "value": "A5CC29D5-B50A-11E8-882D-F90E0E895BD7" }, "system:contentStreamRepositoryId": { "value": "repo242" }, "system:digest": { "value": "4163C826122B64A199D270998C11176F7B8CF3FD71CD4B7C234448740F360CF0" }, "Name": { "value": "Menschenskinder" } }, "contentStreams": [ { "length": 3726, "mimeType": "message/rfc822", "fileName": "upload.bin", "digest": "4163C826122B64A199D270998C11176F7B8CF3FD71CD4B7C234448740F360CF0", "contentStreamId": "A5CC29D5-B50A-11E8-882D-F90E0E895BD7", "repositoryId": "repo242" } ], "renditions": [ { "mimeType": "text/plain", "kind": "text", "contentStream": { "length": 445, "mimeType": "text/plain", "fileName": "content.txt" } } ] } ] }
DELETE /api/dms/objects/{objectId}/contents/file
- Delete a document content by ID
- As of Version
-
2023 Summer
- Request Method
-
DELETE
- Response Format
-
JSON
- Required Permission
-
action
write
andread
The process is internally handled like a content update and therefore does NOT require a delete
permission. - Description
-
Removes the binary content file from the DMS object specified by
objectId
.A new object version without the
contentStreams
properties section will be created. For the previous version(s), the corresponding binary content file remains. To the object’s audit trail, an entry with action 201 and detail OBJECT_CONTENT_DELETED will be added.In addition to the above mentioned permissions, the DMS object has to match following requirements:
-
The object is NOT under retention.
-
The object has a binary content file.
-
Neither the object type of the object nor one of the assigned secondary object types requires a binary content file.
As the process is internally handled like a content update, the corresponding webhook entry points are passed.
The result is a JSON structure containing the updated metadata of the object identified by
objectId
. -
- Request Example
-
DELETE /api/dms/objects/6200fcc9-d6b4-43c0-82e7-ac1ed2fa8350/contents/file
- Response Example
-
Response Body
{ "objects": [ { "properties": { "system:objectId": { "value": "6200fcc9-d6b4-43c0-82e7-ac1ed2fa8350" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "document" }, "system:secondaryObjectTypeIds": { "value": [ "system:rmDestructionRetention" ] }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-09-10T14:35:36.657Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-09-10T15:03:17.099Z" }, "system:versionNumber": { "value": 3 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "7589750308987031207" }, "Name": { "value": "Menschenskinder" } } } ] }
GET /api/dms/objects/{objectId}/contents/renditions/text
- Retrieve text rendition of content by ID
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
plain text
- Required Permission
-
action
read
- Description
-
To return the content file’s full-text rendition of the DMS object, send the request with the ID of the DMS object as
objectId
.If no full-text rendition is stored in the Elsticsearch index for the specified object, the request results in error "404 - not found."
If a content file is imported having one of the supported formats and containing readable text, a full-text rendition will be created and stored in the Elasticsearch index. The full-text rendition can be overwritten via
POST /api/dms/objects/{objectId}/contents/renditions/text
.A
read
permission is required (otherwise results in error "404 - not found"). - Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/contents/renditions/text
- Result Example
-
test-test-get-rendition-text
POST /api/dms/objects/{objectId}/contents/renditions/text
- Update text rendition by ID
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
action
write
andread
- Request Header
-
Content-Type: text/plain
- Description
-
Updates the full-text rendition related to a DMS object identified by
objectId
.If a content file is imported having one of the text rendition compatible formats and containing readable text, a full-text rendition will be created and stored in the Elasticsearch index.
The endpoint posts the plain text passed in the request body to the text rendition property in the Elasticsearch index replacing the current value if already filled before.
As of 2022 Autumn, the optional query parameter
waitForSearchConsistency
can be added to the request URL. If not specified, the default valuetrue
is used.As of 2022 Winter, an audit entry with action code 306 is written to the object’s audit trail.
A dbs-reindex
Command via Commander Service will undo all text rendition updates.Meaning of HTTP status codes:
HTTP status code Meaning 200
Successful, text rendition of specified object was updated.
404
Not successful, specified objectId does not exist or user has no write permission.
422
Not successful, text rendition was not updated.
- Request Example
-
/api/dms/objects/100a1bc1-2def-100a-1234-56b789c01de/contents/renditions/text
Request Bodytest-test-post-rendition-text
- Response Example
-
200
no response body
GET /api/dms/objects/{objectId}/contents/renditions/pdf
- Retrieve PDF rendition of content by ID
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
PDF
- Required Permission
-
action
read
- Description
-
To return the content file’s PDF rendition of the DMS document object, send the request with the ID of the DMS object as
objectId
.If the specified objectId does not exist, the call results in the error
404 - Not Found
. Further errors are triggered by referencing an object without a content file or with a not convertible content file.Please note that the rendition is not an exact representation of the original file. Deviations to the original file may arise and are NOT considered as bugs in our software.
- Response Header
-
Content-Type: application/pdf
- Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/contents/renditions/pdf
- Response Example
-
Response body with PDF document.
GET /api/dms/objects/{objectId}/contents/renditions/slide
- Retrieve slide rendition of content by ID
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
PNG
- Required Permission
-
action
read
- Description
-
Retrieves the slide rendition of the binary content file that is assigned to the DMS object specified by
objectId
.A PNG image with 256 px is returned in the response body.
The supported formats of binary content files as well as details on calculation and storage are listed here: Supported Formats
Please note that the rendition is not an exact representation of the original file. Deviations to the original file may arise and are NOT considered as bugs in our software.
- Response Header
-
Content-Type: image/png
- Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/contents/renditions/slide
- Response Example
-
Response body with PNG file.
GET /api/dms/objects/{objectId}/history
- Retrieve the audit entries for the specified object.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
successful authentication
- Description
-
To retrieve the history entries of a DMS object, send the request with the ID of the DMS object as
objectId
.Meaning of action field values: Audit Trail
By default, the last 50 entries are returned. You can control the history entries returned by using the following query parameters
Parameter Description size
defines the number of returned history entries
page
defines on which page the result list of history entries should be started (one page = 50 entries)
For example, to get 50 history entries from 101 to 150 returned use
size=50
andpage=2
. - Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/history
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/history?size=50&page=2
- Response Example
-
{ "objects": [{ "properties": { "system:objectId": { "value": 213518578 }, "system:objectTypeId": { "value": "system:audit" }, "system:baseTypeId": { "value": "item" }, "system:createdBy": { "value": "1EF9EB6E7F2F41D69D5408609CFF5FFD" }, "system:tenant": { "value": "default" }, "system:creationDate": { "value": "2018-05-18T13:25:25.450Z" }, "description": { "value": "" }, "action": { "value": 401 }, "detail": { "value": "GET_METADATA" }, "referredObjectId": { "value": "df398a31-3ed3-4fe6-a744-a0d0f90b8678" }, "traceid": { "value": "0a53668f42b6691a" }, "system:versionNumber": { "value": 1 } } }, { "properties": { "system:objectId": { "value": 213509340 }, "system:objectTypeId": { "value": "system:audit" }, "system:baseTypeId": { "value": "item" }, "system:createdBy": { "value": "1EF9EB6E7F2F41D69D5408609CFF5FFD" }, "system:tenant": { "value": "default" }, "system:creationDate": { "value": "2018-05-18T01:45:44.040Z" }, "description": { "value": "" }, "action": { "value": 101 }, "detail": { "value": "CREATE_METADATA_WITH_CONTENT" }, "referredObjectId": { "value": "df398a31-3ed3-4fe6-a744-a0d0f90b8678" }, "traceid": { "value": "43d141cec4ea8a58" }, "system:versionNumber": { "value": 1 } } }] }
GET /api/dms/objects/{objectId}/actions/validate/digest
- Validate the specified object’s content.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
action
read
- Description
-
To validate the content digest of a DMS object, send the request with the ID of the DMS object as
objectId
. The content digest is calculated anew and compared with the value generated and stored in the metadata upon import.Meaning of the response status codes:
HTTP status code Meaning 200 OK
The value of the content digest stored in the metadata is still correct.
404 Not Found
The DMS object with the ID objectId can not be found.
409 Conflict
The calculated content digest does not match the value stored in the metadata.
- Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/actions/validate/digest
POST /api/dms/objects/{objectId}/actions/move/contents/repositories/{repositoryId}
- Move the content of an object to a different repository.
- As of Version
-
2019 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
action
write
andread
- Description
-
Moves the binary content file assigned to the object specified by
objectId
to the target repository specified byrepositoryId
.The corresponding binary content file is referenced in the
contentStreams
section of the object via the properties repositoryId andcontentStreamId
. The binary content file could be referenced in multiple object versions and even in other objects. In case the corresponding binary content file is moved, therepositoryId
andcontentStreamId
properties in thecontentStreams
section are updated in all those objects and object versions. No new object version will be created.An audit entry will be created only for the current version of the object specified by
objectId
in the request URL. - Request Example
-
POST api/dms/objects/00250915-fb6e-4165-bc05-93a02590f5de/actions/move/contents/repositories/repo252
- Response Example
-
The result is a JSON structure containing the updated metadata of the object identified by
objectId
.{ "objects": [{ "properties": { "system:traceId": { "value": "6ff928e56f8f8efe" }, "system:objectTypeId": { "value": "document" }, "system:versionNumber": { "value": 1 }, "Name": { "value": "Beat 2014-06.pdf_075.pdf" }, "system:createdBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate": { "value": "2018-11-30T14:47:40.250Z" }, "system:lastModificationDate": { "value": "2018-11-30T14:47:40.250Z" }, "system:baseTypeId": { "value": "system:document" }, "system:tenant": { "value": "default" }, "system:lastModifiedBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:objectId": { "value": "00250915-fb6e-4165-bc05-93a02590f5de" } }, "contentStreams": [{ "contentStreamId": "DB886B37-FEEF-11E9-BCEC-3FAD551A2B8A", "archivePath": "default/DOCUMENT/B8/86/B/", "length": 86171, "mimeType": "application/pdf", "fileName": "Beat 2014-06.pdf_075.pdf", "digest": "2714F996A45F41439F625160167B4DE5BDE604F560FCABF8C242567CDFDC733A", "repositoryId": "repo252" }] }] }
Operations for Partial Upload
POST /api/dms/uploads
- Initialize an upload.
- As of Version
-
2024 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
successful authentication
- Description
-
Initializes the import of a large content file in multiple pieces. The response body contains the
uploadId
that has to be referred to by the individual upload of each piece that belongs to the same binary content file.After each processing step of the upload, a maximum time of 2 days (default configuration) inactivity is accepted before the process and all its pieces are automatically deleted.
- Request Example
-
POST /api/ms/uploads
- Response Example
-
{ "uploadId": "MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5" }
PUT /api/dms/uploads/{uploadId}/parts/{partNumber}
- Upload a piece of content.
- As of Version
-
2024 Summer
- Request Method
-
PUT
- Response Format
-
HTTP status code
- Required Permission
-
successful authentication
- Description
-
Uploads the binary file (NO multipart) in the request body as a piece that belongs to the upload process specified by
uploadId
. Specify the index number (starting with 1) of the piece as value forpartNumber
.After each processing step of the upload, a maximum time of 2 days (default configuration) inactivity is accepted before the process and all its pieces are automatically deleted.
- Request Example
-
PUT /api/dms/uploads/MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5/parts/1
- Response Example
-
200 OK
POST /api/dms/uploads/{uploadId}
- Finalize an upload.
- As of Version
-
2024 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
successful authentication
- Description
-
Finalizes the upload process specified by
uploadId
. All pieces of the binary content imported viaPOST /api/dms/uploads/{uploadId}
are concatenated to one content file ordered by theirpartNumber
. After the successful call, no more sub-uploads of individual pieces are possible.Finalizing the upload process is the last processing step for the partial import. However, it is still required to create a DMS object referring to that content within 2 days (default configuration). Otherwise, the upload with all its pieces will be deleted.
Optional query parameters:
Parameter Type Description numberOfParts
Integer
Specify the total number of pieces that is expected for the upload process to be completed. The value is used for validation. The request fails if the specified number is not equal to the actual number of successful sub-uploads.
- Request Example
-
PUT /api/dms/uploads/MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5?numberOfParts=3
- Response Example
-
200 OK
POST /api/dms/uploads/{uploadId}/objects
- Create a DMS object with uploaded content.
- As of Version
-
2024 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
action
create
- Request Header
-
Content-Type: application/json
- Description
-
Creates a new DMS object with the metadata specified in the JSON request body and stores the binary content file that has already been temporarily uploaded via the partial upload process specified by
uploadId
. The upload has to be finalized viaPOST /api/dms/uploads/{uploadId}
first.The request body can be a JSON structure or a multipart without binary content section as accepted also by
POST /api/dms/objects
. The previously uploaded content is identified viauploadId
and NOT viacontentStreams
properties in the request body. However, thecontentanalyzer
service is SKIPPED. Thus, if you need proper values in thecontentStreams
section forfileName
andmimeType
, you need to set them in the JSON request body. - Request Example
-
POST /api/dms/uploads/MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5/objects
Example request body for the creation of a DMS object after partial upload{ "objects": [{ "properties": { "system:objectTypeId": { "value": "system:document" }, "customproperty": { "value": "myvalue" } }, "contentStreams": [{ "mimeType": "application/pdf", "fileName": "myfilename.pdf" }] }] }
- Response Example
-
Response Body
{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "customproperty": { "value": "myvalue" }, "system:objectTypeId": { "value": "system:document" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2024-05-27T12:46:02.650Z" }, "system:lastModifiedBy": { "value": "0ade86f3-fcd1-4149-a556-fac2e94dc578" }, "system:lastModificationDate": { "value": "2024-05-27T12:46:02.650Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" } }, "contentStreams": [ { "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "archivePath": "tenant1/2024/05/27/", "length": 300000, "mimeType": "application/pdf", "fileName": "myfilename.pdf", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" } ] } ] }
DELETE /api/dms/uploads/{uploadId}
- Delete all pieces of an upload.
- As of Version
-
2024 Summer
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
successful authentication
- Description
-
Deletes all pieces of the content file that are already uploaded with the specified
uploadId
viaPOST /api/dms/uploads/{uploadId}
.Each upload process is automatically removed 2 days after the last processing step (default configuration).
- Request Example
-
DELETE /api/dms/uploads/MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5
- Response Example
-
200 OK
GET /api/dms/uploads
- Retrieve an overview of uploads.
- As of Version
-
2024 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
successful authentication
- Description
-
Retrieves an overview of all running partial upload processes within the tenant with their already imported pieces indicated by
partNumber
.Running processes in this case are those that were initialized via
POST /api/dms/uploads
and not yet finalized viaPOST /api/dms/uploads/{uploadId}
or deleted viaDELETE /api/dms/uploads/{uploadId}
.Each upload process is automatically removed after 2 days (default configuration).
The value for
serviceInstanceUrls
is always replaced bynull
in the response body. Its actual value ensures internally that the processing of all pieces of the same content are directed to the samerepository
service instance. - Request Example
-
GET /api/dms/uploads
- Response Example
-
Response Body
{ "uploads": { "MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5": { "uploadId": "MP_a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5", "parts": { "1": { "partNumber": 1, "length": 100000, "digest": "112376DC30C3F19290F518623C67FBBAC8D62A52916F0C5C0D9843DBC9F29EDA" }, "2": { "partNumber": 2, "length": 100000, "digest": "37B86BDF23559429C5EFF873255CBC64F33CC77E4FAAEB3F17A45B77B9BD0D14" }, "3": { "partNumber": 3, "length": 100000, "digest": "7DE8022F6664A3A4C18A4FE501034871567070043600DF37FAC925A080E561F5" } }, "finished": false, "serviceInstanceUrl": null, "lastUpdated": 1716813572968 } } }
Operations on specific Versions
GET /api/dms/objects/{objectId}/versions
- Retrieve object metadata by ID (all versions)
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
action
read
- Description
-
To retrieve the metadata of all versions of a DMS object, send the request with the ID of the DMS object as
objectId
.A
read
permission on the active version is required. - Request Example
-
/api/dms/objects/cdc7095f-a5ce-486d-92a7-6d0955d969ee/versions
- Result Example
-
The result is a list with at least one metadata record in JSON format:
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-26T15:21:170Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>"] }, "appEmail:subject": { "value": "Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }, { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-29T13:13:113Z" }, "system:versionNumber": { "value": 2 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>", "Vils Normum <Normum@example.de>"] }, "appEmail:subject": { "value": "Updated Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }, { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-30T11:53:227Z" }, "system:versionNumber": { "value": 3 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:subject": { "value": "again updated Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }] }
GET /api/dms/objects/{objectId}/versions/{versionNr}
- Retrieve object metadata by ID (specified version)
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
action
read
- Description
-
To retrieve the metadata of a specific version of a DMS object, send the request with the ID of the DMS object as
objectId
and the version number asversionNr
.A
read
permission on the active version is required. - Request Example
-
/api/dms/objects/cdc7095f-a5ce-486d-92a7-6d0955d969ee/versions/1
- Result Example
-
The result is a list with at least one metadata record in JSON format:
{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-26T15:21:170Z" }, "system:versionNumber": { "value": 1 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>"] }, "appEmail:subject": { "value": "Bewerbungsunterlagen" } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }] }
GET /api/dms/objects/{objectId}/versions/{versionNr}/contents/file
- Retrieve object content by ID (specified version)
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
binary data
- Required Permission
-
action
read
- Description
-
To get the content file related to a specific version of a DMS object, send the request with the ID of the DMS object as
objectId
and the version number asversionNr
.A
read
permission on the active version is required. - Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/versions/2/contents/file
GET /api/dms/objects/{objectId}/versions/{versionNr}/contents/renditions/pdf
- Retrieve PDF rendition by ID (specified version)
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
PDF
- Required Permission
-
action
read
- Description
-
Returns the content file’s PDF rendition of the DMS document object version specified by
objectId
andversionNr
.If the specified
objectId
does not exist, the call results in the error404 - Not Found
. Further errors are triggered by referencing an object without a content file or with a non-convertible content file.The endpoint accepts the target file types listet here.
- Response Header
-
Content-Type: application/pdf
- Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/versions/2/contents/renditions/pdf
- Response Example
-
Response body with PDF document.
GET /api/dms/objects/{objectId}/versions/{versionNr}/contents/renditions/slide
- Retrieve slide rendition by ID (specified version)
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
PNG
- Required Permission
-
action
read
- Description
-
Retrieves the slide rendition of the binary content file that is assigned to the DMS object specified by
objectId
andversionNr
.A PNG image with 256 px is returned in the response body.
The supported formats of binary content files as well as details on calculation and storage are listed here: Supported Formats
Please note that the rendition is not an exact representation of the original file. Deviations to the original file may arise and are NOT considered as bugs in our software.
- Response Header
-
Content-Type: image/png
- Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/versions/3/contents/renditions/slide
- Response Example
-
Response body with PNG file.
POST /api/dms/objects/{objectId}/versions/{versionNr}/actions/restore
- Restore the specified object version.
- As of Version
-
2022 Spring
- Request Method
-
POST
- Required Permission
-
action
write
on the current version of the object - Description
-
Restores the old version of an object specified by
objectId
andversionNr
.The following requirements have to be matched by the object version specified by
versionNr
:-
It has to exist and must not be the current version.
-
It has to be valid according to the current schema. E.g., if one of its properties is not part of the current schema anymore, the restoring process will fail.
-
If the current object version has been assigned a
system:rmExpirationDate
, the specified old object version must have the samesystem:rmExpirationDate
. -
If the current object version has a binary content file AND a
system:rmExpirationDate
that is not yet expired, the specified old object version must have the same binary content file AND the samesystem:rmExpirationDate
.
Internally, the data of the old object version are used to update the current object version. Thus, a new object version is created that has the data of the specified old object version except for
system:versionNumber
,system:lastModifiedBy
,system:lastModificationDate
andsystem:traceId
. Those properties describe the restoring action itself.If tags are assigned to the current object before the restoring action, only those tags with a name ending with the suffix
:resistant
are transferred to the new object version.A new entry in the object’s audit trail is created. For the
detail
property, the valueOBJECT_RESTORED_FROM_VERSION
is set.As of 2022 Summer: Optionally, the boolean query parameter
restoreParentId
can be appended to the request URL. This parameter is relevant for objects with asystem:parentId
property that indicates the object is considered as a child object of a folder object. The old version of the child object to be restored might have a different value for thesystem:parentId
property. Thus, you might want to keep the current value for thesystem:parentId
property of the child object even after restoring an old version.-
If
restoreParentId=true
(default), thesystem:parentId
value of the respective old object version is used. -
If
restoreParentId=false
, thesystem:parentId
value of the current version is used after restoring the respective old object version.
As of 2022 Autumn, the optional query parameter
waitForSearchConsistency
can be added to the request URL. If not specified, the default valuetrue
is used. -
- Request Example
-
/api/dms/objects/950f1e3a-829b-473d-97c5-9ea0a94706f6/versions/2/actions/restore
- Response Example
-
{ "objects": [{ "properties": { "system:objectId": { "value": "950f1e3a-829b-473d-97c5-9ea0a94706f6" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appEmail:email" }, "system:createdBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:creationDate": { "value": "2018-01-26T15:21:170Z" }, "system:lastModifiedBy": { "value": "0d7fd0be-6a0b-4d3b-933c-25e0c4c5d794" }, "system:lastModificationDate": { "value": "2018-01-26T15:21:170Z" }, "system:versionNumber": { "value": 4 }, "system:tenant": { "value": "tenant1" }, "system:traceId": { "value": "97a35859dbb4c435" }, "appEmail:from": { "value": "Garco Meissler <garco@example.de>" }, "appEmail:to": { "value": ["Dudreas Annkel <dudreas@example.de>"] }, "appEmail:cc": { "value": ["Kruedeas Anger <kruedeas@example.de>", "Vils Normum <Normum@example.de>"] }, "appEmail:subject": { "value": "Updated Bewerbungsunterlagen" }, "table": { "columnNames": ["iColumn1", "iColumn2", "iColumn3"], "value": [["something", "to know", true],["more", "infos", false]] } }, "contentStreams": [{ "contentStreamId": "2B797243-A1F5-11EA-A814-9FABD98CE7A7", "length": 173413, "mimeType": "message/rfc822", "fileName": "upload.eml", "digest": "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855", "repositoryId": "repo252" }] }] }
DELETE /api/dms/objects/{objectId}/versions/{versionNr}
- Delete the specified object version.
- As of Version
-
1.0
- Request Method
-
DELETE
- Required Permission
-
action
delete
andread
- Description
-
To delete a specific version of an object, send the request with the ID of the object as
objectId
and the version number asversionNr
.Deleting the active version is not possible via this endpoint.
Meaning of the response status codes:
HTTP status code Meaning 200 OK
The DMS object with the ID objectId has been deleted
404 Not Found
The DMS object with the ID objectId can not be found.
A
delete
permission on the active version of the object is required. - Request Example
-
/api/dms/objects/950f1e3a-829b-473d-97c5-9ea0a94706f6/versions/2
GET /api/dms/objects/{objectId}/versions/{versionNr}/actions/validate/digest
- Validate the specified object’s content.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
action
read
- Description
-
To validate the content digest of a specific version of a DMS object, send the request with the ID of the DMS object as
objectId
and the version number asversionNr
. The content digest is calculated and compared with the value stored in the metadata.A
read
permission on the active version is required.Meaning of the response status codes:
HTTP status code Meaning 200 OK
The value of the content digest stored in the metadata is still correct.
404 Not Found
The DMS object with the ID
objectId
can not be found.409 Conflict
The calculated content digest does not match the value stored in the metadata.
- Request Example
-
/api/dms/objects/903f2ae8-2cfc-476c-8386-55c6811e41da/versions/1/actions/validate/digest
POST /api/dms/objects/{objectId}/version/{versionNr}/actions/move/contents/repositories/{repositoryid}
- Move the content of an object version to a different repository.
- As of Version
-
2019 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
action
write
andread
- Description
-
Moves the binary content file assigned to the selected version of the object specified by
objectId
to the target repository specified byrepositoryId
.The corresponding binary content file is referenced in the
contentStreams
section of the object version via the propertiesrepositoryId
andcontentStreamId
. The binary content file could be referenced in multiple object versions and even in other objects. In case the corresponding binary content file is moved, therepositoryId
andcontentStreamId
properties in thecontentStreams
section are updated in all those objects and object versions. No new object version will be created.An audit entry will be created only for version specified by versionNr of the object specified by
objectId
in the request URL. - Request Example
-
POST api/dms/objects/00250915-fb6e-4165-bc05-93a02590f5de/versions/1/actions/move/contents/repositories/repo252
- Response Example
-
The result is a JSON structure containing the updated metadata of the object identified by
objectId
.{ "objects": [{ "properties": { "system:traceId": { "value": "6ff928e56f8f8efe" }, "system:objectTypeId": { "value": "document" }, "system:versionNumber": { "value": 1 }, "Name": { "value": "Beat 2014-06.pdf_075.pdf" }, "system:createdBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:creationDate": { "value": "2018-11-30T14:47:40.250Z" }, "system:lastModificationDate": { "value": "2018-11-30T14:47:40.250Z" }, "system:baseTypeId": { "value": "system:document" }, "system:tenant": { "value": "default" }, "system:lastModifiedBy": { "value": "275c826c-6a61-4e89-9512-8d935a1631e5" }, "system:objectId": { "value": "00250915-fb6e-4165-bc05-93a02590f5de" } }, "contentStreams": [{ "contentStreamId": "DB886B37-FEEF-11E9-BCEC-3FAD551A2B8A", "archivePath": "default/DOCUMENT/B8/86/B/", "length": 86171, "mimeType": "application/pdf", "fileName": "Beat 2014-06.pdf_075.pdf", "digest": "2714F996A45F41439F625160167B4DE5BDE604F560FCABF8C242567CDFDC733A", "repositoryId": "repo252" }] }] }
Schema Retrieval - Object Type Information
GET /api/dms/schema/native
- Retrieve applied tenant schema in XML/JSON format.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
XML / JSON
- Description
-
Get the applied schema which belongs to the requesting user. It contains all available types: system types, global types and tenant-specific types.
The structure is the same as in the source schemas that are maintained via the admin endpoints and the system endpoints.
- Request Example
-
/api/dms/schema/native
- Result Example
-
xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/"> <version>1</version> <lastModificationDate>2019-03-25T10:25:46.212Z</lastModificationDate> <propertyIdDefinition> <id>system:objectId</id> <description>Id of the object</description> <propertyType>id</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyIdDefinition> <propertyIdDefinition> <id>system:baseTypeId</id> <description>Id of the base object-type for the object</description> <propertyType>id</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyIdDefinition> ... <propertyStringDefinition> <id>appEmail:from</id> <description>field for the e-mail sender</description> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> ... <propertyStringDefinition> <id>tenNyc999:myname</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> <propertyDateTimeDefinition> <id>tenNyc999:mydate</id> <propertyType>datetime</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyDateTimeDefinition> ... <typeDocumentDefinition> <id>system:document</id> <localNamespace>urn:optimal-systems.de:dmscloud:system</localNamespace> <description>decribes the base document type</description> <baseId>system:document</baseId> <propertyReference>system:objectId</propertyReference> <propertyReference>system:baseTypeId</propertyReference> ... <contentStreamAllowed>allowed</contentStreamAllowed> </typeDocumentDefinition> <typeDocumentDefinition> <id>appEmail:email</id> <baseId>system:document</baseId> <propertyReference>appEmail:from</propertyReference> ... <contentStreamAllowed>required</contentStreamAllowed> <secondaryObjectTypeId>system:rmDestructionRetention</secondaryObjectTypeId> </typeDocumentDefinition> ... <typeDocumentDefinition> <id>tenNyc999:mydocument</id> <baseId>system:document</baseId> <propertyReference>tenNyc999:myname</propertyReference> <propertyReference>tenNyc999:mydate</propertyReference> <contentStreamAllowed>required</contentStreamAllowed> </typeDocumentDefinition> ... <typeSecondaryDefinition> <id>system:secondary</id> <localNamespace>urn:optimal-systems.de:dmscloud:system</localNamespace> <description>decribes the base secondary type</description> <baseId>system:secondary</baseId> </typeSecondaryDefinition> <typeSecondaryDefinition> <id>system:rmDestructionRetention</id> <localNamespace>urn:optimal-systems.de:dmscloud:system</localNamespace> <baseId>system:secondary</baseId> <propertyReference>system:rmExpirationDate</propertyReference> <propertyReference>system:rmStartOfRetention</propertyReference> <propertyReference>system:rmDestructionDate</propertyReference> </typeSecondaryDefinition> </schema>
json{ "version": 1, "lastModificationDate": "2019-03-25T10:25:46.212Z", "propertyDefinition": [ { "id": "system:objectId", "description": "Id of the object", "propertyType": "id", "cardinality": "single", "required": false }, { "id": "system:baseTypeId", "description": "Id of the base object-type for the object", "propertyType": "id", "cardinality": "single", "required": false }, ... { "id": "appEmail:from", "description": "field for the e-mail sender", "propertyType": "string", "cardinality": "single", "required": false }, ... { "id": "tenNyc999:myname", "propertyType": "string", "cardinality": "single", "required": false }, { "id": "tenNyc999:mydate", "propertyType": "datetime", "cardinality": "single", "required": false } ], "typeDocumentDefinition": [ { "id": "system:document", "localNamespace": "urn:optimal-systems.de:dmscloud:system", "description": "decribes the base document type", "baseId": "system:document", "propertyReference": [ { "value": "system:objectId" }, { "value": "system:baseTypeId" }, ... ], "contentStreamAllowed": "allowed" }, { "id": "appEmail:email", "baseId": "system:document", "propertyReference": [ { "value": "appEmail:from" }, ... ], "contentStreamAllowed": "required", "secondaryObjectTypeId": [ "system:rmDestructionRetention" ] }, ... { "id": "tenNyc999:mydocument", "baseId": "system:document", "propertyReference": [ { "value": "tenNyc999:myname" }, { "value": "tenNyc999:mydate" } ], "contentStreamAllowed": "required" } ], "typeSecondaryDefinition": [ { "id": "system:secondary", "localNamespace": "urn:optimal-systems.de:dmscloud:system", "description": "decribes the base secondary type", "baseId": "system:secondary", "propertyReference": [] }, { "id": "system:rmDestructionRetention", "localNamespace": "urn:optimal-systems.de:dmscloud:system", "baseId": "system:secondary", "propertyReference": [ { "value": "system:rmExpirationDate" }, { "value": "system:rmStartOfRetention" }, { "value": "system:rmDestructionDate" } ] } ] }
GET /api/dms/schema
- Retrieve applied tenant schema in JSON format.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Get the applied tenant schema. It contains all available types: system types, global types and tenant-specific types.
This is similar to the "Retrieve applied tenant schema" endpoint (
GET /api/dms/schema/native
). The resulting schema contains the same types, but it is structured in a different way. - Request Example
-
/api/dms/schema
- Response Example
-
{ "lastModificationDate": "2020-02-27T19:12:47.677+01:00", "objectTypes": [ { "id": "system:document", "localName": "system:document", "localNamespace": "urn:optimal-systems.de:dmscloud:system", "displayName": "system:document", "baseId": "document", "description": "decribes the base document type", "creatable": false, "contentStreamAllowed": "allowed", "fulltextIndexed": true, "fields": [ { "id": "system:objectId", "localName": "system:objectId", "displayName": "system:objectId", "description": "Id of the object", "propertyType": "string", "cardinality": "single", "updatability": "readonly", "required": false }, { "id": "system:baseTypeId", "localName": "system:baseTypeId", "displayName": "system:baseTypeId", "description": "Id of the base object-type for the object", "propertyType": "string", "cardinality": "single", "updatability": "readonly", "required": false }, ... ] }, { "id" : "appEmail:email", "localName" : "appEmail:email", "displayName" : "appEmail:email", "baseId" : "document", "creatable" : true, "contentStreamAllowed" : "required", "fulltextIndexed" : true, "fields": [ ... { "id" : "appEmail:from", "localName" : "appEmail:from", "displayName" : "appEmail:from", "description" : "field for the e-mail sender", "propertyType" : "string", "cardinality" : "single", "updatability" : "readwrite", "required" : false }, ... ] }, ... { "id" : "tenNyc999:mydocument", "localName" : "tenNyc999:mydocument", "displayName" : "tenNyc999:mydocument", "baseId" : "document", "creatable" : true, "contentStreamAllowed" : "required", "fulltextIndexed" : true, "fields": [ { "id" : "tenNyc999:myname", "localName" : "tenNyc999:myname", "displayName" : "tenNyc999:myname", "propertyType" : "string", "cardinality" : "single", "updatability" : "readwrite", "required" : false }, { "id" : "tenNyc999:mydate", "localName" : "tenNyc999:mydate", "displayName" : "tenNyc999:mydate", "propertyType" : "datetime", "cardinality" : "single", "updatability" : "readwrite", "required" : false } ] } ] }
GET /api/dms/schema/objecttype/{localname}
- Retrieve an object type’s definition by its local name.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the definition of the object type identified by its
localname
. The definition contains attributes of the object type and definitions of all its fields. - Request Example
-
/api/dms/schema/objecttype/email
- Response Example
-
{ "id": "email", "localName": "email", "displayName": "email", "baseId": "document", "creatable": true, "contentStreamAllowed": "required", "fulltextIndexed": true, "fields": [ { "id": "system:objectId", "localName": "system:objectId", "displayName": "system:objectId", "description": "Id of the object", "propertyType": "string", "cardinality": "single", "updatability": "readonly", "required": false }, { "id": "system:baseTypeId", "localName": "system:baseTypeId", "displayName": "system:baseTypeId", "description": "Id of the base object-type for the object", "propertyType": "string", "cardinality": "single", "updatability": "readonly", "required": false }, { "id": "system:objectTypeId", "localName": "system:objectTypeId", "displayName": "system:objectTypeId", "description": "Id of the object’s type", "propertyType": "string", "cardinality": "single", "updatability": "readonly", "required": false }, { "id": "system:secondaryObjectTypeIds", "localName": "system:secondaryObjectTypeIds", "displayName": "system:secondaryObjectTypeIds", "description": "Ids of the object’s secondary types.", "propertyType": "string", "cardinality": "multi", "updatability": "readonly", "required": false }, { "id": "system:createdBy", "localName": "system:createdBy", "displayName": "system:createdBy", "description": "User who created the object", "propertyType": "string", "cardinality": "single", "updatability": "readonly", "required": false }, { "id": "system:creationDate", "localName": "system:creationDate", "displayName": "system:creationDate", "description": "DateTime when the object was created", "propertyType": "datetime", "cardinality": "single", "updatability": "readonly", "required": false }, { "id": "system:lastModifiedBy", "localName": "system:lastModifiedBy", "displayName": "system:lastModifiedBy", "description": "User who last modified the object", "propertyType": "string", "cardinality": "single", "updatability": "readonly", "required": false }, { "id": "system:lastModificationDate", "localName": "system:lastModificationDate", "displayName": "system:lastModificationDate", "description": "DateTime when the object was last modified", "propertyType": "datetime", "cardinality": "single", "updatability": "readonly", "required": false }, { "id": "system:versionNumber", "localName": "system:versionNumber", "displayName": "system:versionNumber", "description": "The version number of the object", "propertyType": "integer", "cardinality": "single", "updatability": "readonly", "required": true }, ... { "id": "from", "localName": "from", "displayName": "from", "description": "system-wide field for the e-mail sender", "propertyType": "string", "cardinality": "single", "updatability": "readwrite", "required": false }, { "id": "to", "localName": "to", "displayName": "to", "description": "system-wide field for the e-mail recipients", "propertyType": "string", "cardinality": "multi", "updatability": "readwrite", "required": false }, { "id": "cc", "localName": "cc", "displayName": "cc", "description": "system-wide field for the e-mail cc", "propertyType": "string", "cardinality": "multi", "updatability": "readwrite", "required": false }, { "id": "bcc", "localName": "bcc", "displayName": "bcc", "description": "system-wide field for the e-mail bcc", "propertyType": "string", "cardinality": "multi", "updatability": "readwrite", "required": false }, { "id": "subject", "localName": "subject", "displayName": "subject", "description": "system-wide field for the e-mail subject", "propertyType": "string", "cardinality": "single", "updatability": "readwrite", "required": false }, ... ] }
2.11.2. Resources Endpoints within the Tenant
Operations on resources that affect only the currently active tenant.
Metrics
GET /api/admin/metrics/{metric}
- Retrieve a metric for the active tenant.
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and if the specified access condition is matched. - Description
-
Retrieve the specified metric for the currently active tenant.
Following values are available for the metric path parameter:
-
storage
- The endpoint retrieves the dynamically calculated binary storage used by the currently active tenant. -
objectCount
(as of 2023 Summer) - The endpoint retrieves the number of DMS objects within the currently active tenant.
-
- Request Examples
-
(A)
/api/admin/metrics/storage
(B)
/api/admin/metrics/objectCount
- Response Examples
-
(A)
{ "objects": [ { "properties": { "system:tenant": { "value": "testyuuvis" } }, "options": { "storageUsed": { "humanReadable": "121 MB", "value": 127508469 } } } ], "numItems": 1, "hasMoreItems": false, "totalNumItems": 1 }
(B)
{ "objects": [{ "properties": { "system:tenant": { "value": "testyuuvis" } }, "options": { "objectCount": { "totalFolderCount": 97, "totalObjectCount": 1733 } } } ], "numItems": 1, "hasMoreItems": false, "totalNumItems": 1 }
DELETE /api/admin/metrics/{metric}
- Reset a metric for the active tenant.
- As of Version
-
2023 Spring
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Reset the specified metric for the currently active tenant.
Not available for the storage metric. Use
DELETE /api/system/metrics/{metric}
instead.
Role Set Management
GET /api/admin/permissions
- Retrieve the tenant role set for the active tenant.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
XML
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
To retrieve the role set of the tenant in XML format. The tenant belongs to the user calling this endpoint.
- Request Example
-
/api/admin/permissions
- Response Example
-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/"> <role> <name>ReadDeleteEmail</name> <permission> <action>read</action> <action>delete</action> <condition>system:objectTypeId = 'email:email'</condition> </permission> </role> <role> <name>ReadDocument</name> <permission> <action>read</action> <condition>system:objectTypeId = 'document'</condition> </permission> </role> <role> <name>ReadEmailAndDocument</name> <permission> <action>read</action> <condition>system:objectTypeId in ('email:email', 'document')</condition> </permission> </role> <role> <name>DeleteDocument</name> <permission> <action>delete</action> <condition>system:objectTypeId in ('document')</condition> </permission> </role> <role> <name>AdminRole</name> <permission> <action>read</action> <action>delete</action> </permission> </role> </roleSet>
POST /api/admin/permissions
- Update the tenant role set for the active tenant if valid.
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
To update the role set of the tenant, there are two possibilities to send the new role set: as binary in the request body or as multipart request with part name file. The tenant for which the role set will be updated belongs to the user calling this endpoint.
If the validation process fails, the role set will not be updated and the response contains at least one error message. If the new role set is valid, the role set will be updated and the response contains an empty list
validationErrors
. - Request Header
-
Content-Type: application/xml
- Response Example
-
The result is a JSON structure containing a
validationErrors
list, which could be an empty list.200 - no validation errors, the role set has been updated{ "validationErrors": [] }
422 - there were validation errors, the role set was not updated{ "validationErrors": [ { "message": "Unable to unmarshal schema. [line: 14][column: 13] cvc-complex-type.2.4.a: Ungültiger Content wurde beginnend mit Element 'condition' gefunden. '{\"http://optimal-systems.org/ns/dmscloud/roleset/\":action}' wird erwartet." } ] }
POST /api/admin/permissions/validate
- Validate a role set for the active tenant.
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
To validate the role set of the tenant, there are two possibilities to send the new role set: as binary in the request body or as multipart request with part name file. The tenant for which the role set will be updated belongs to the user calling this endpoint.
If the validation process fails, the response contains at least one error message. If the new role set is valid, the response contains an empty list
validationErrors
. - Request Header
-
Content-Type: application/xml
- Response Example
-
The result is a JSON structure containing a
validationErrors
list, which could be an empty list.200 - the role set is valid, no validation errors{ "validationErrors": [] }
422 - there were validation errors{ "validationErrors": [ { "message": "Unable to unmarshal schema. [line: 14][column: 13] cvc-complex-type.2.4.a: Ungültiger Content wurde beginnend mit Element 'condition' gefunden. '{\"http://optimal-systems.org/ns/dmscloud/roleset/\":action}' wird erwartet." } ] }
Tenant Schema Management
GET /api/admin/schema
- Retrieve the tenant schema for the active tenant.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
XML, JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
To retrieve the schema of the tenant in XML or JSON format. The tenant belongs to the user calling this endpoint.
- Request Example
-
/api/admin/schema
- Response Example
-
<schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://optimal-systems.org/ns/dmscloud/schema/v5.0/ dmsCloud-schema.xsd"> <propertyStringDefinition> <id>from</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>true</required> </propertyStringDefinition> <propertyStringDefinition> <id>to</id> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>true</required> </propertyStringDefinition> <propertyStringDefinition> <id>subject</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>true</required> <defaultValue>hello</defaultValue> <maxLength>20</maxLength> <minLength>4</minLength> </propertyStringDefinition> <propertyDateTimeDefinition> <id>received</id> <propertyType>datetime</propertyType> <cardinality>single</cardinality> <required>true</required> </propertyDateTimeDefinition> <typeDocumentDefinition> <id>email</id> <baseId>system:document</baseId> <propertyReference>from</propertyReference> <propertyReference>to</propertyReference> <propertyReference>received</propertyReference> <contentStreamAllowed>required</contentStreamAllowed> </typeDocumentDefinition> </schema>
POST /api/admin/schema
- Update the tenant schema for the active tenant if valid.
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Update the tenant schema for the tenant which the requesting user belongs to. The new schema is passed in the request body in XML format and is validated before the update is executed. Thus, it is not possible to introduce an invalid schema via this endpoint.
For details and examples regarding request and response please visit schema.
- Request Headers
-
Content-Type: application/xml
POST /api/admin/schema/validate
- Validate a schema for the active tenant.
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Validate the XML file passed in the request body for the usability as tenant schema for the tenant which the requesting user belongs to. The currently used tenant schema is NOT updated.
For details and examples regarding request and response please visit schema.
- Request Headers
-
Content-Type: application/xml
2.11.3. Cross-Tenant Resources Endpoints
Global Endpoints
Operations on the resources that affect all tenants in the system.
Metrics
GET /api/system/metrics/{metric}
- Retrieve a metric for all tenants.
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Retrieve the specified metric for all tenants.
Following values are available for the metric path parameter:
-
storage
- The endpoint retrieves the dynamically calculated binary storage individually used by tenants.
-
- Request Example
-
/api/system/metrics/storage
- Response Example
-
{ "objects": [ { "properties": { "system:tenant": { "value": "tenant1" } }, "options": { "storageUsed": { "humanReadable": "121 MB", "value": 127508469 } } }, { "properties": { "system:tenant": { "value": "yuuvistest" } }, "options": { "storageUsed": { "humanReadable": "12 GB", "value": 13518072956 } } }, { "properties": { "system:tenant": { "value": "testyuuvis" } }, "options": { "storageUsed": { "humanReadable": "164 MB", "value": 172295598 } } }, { "properties": { "system:tenant": { "value": "exampletenant" } }, "options": { "storageUsed": { "humanReadable": "456 KB", "value": 467485 } } }, { "properties": { "system:tenant": { "value": "mytenant" } }, "options": { "storageUsed": { "humanReadable": "0 bytes", "value": 0 } } } ], "numItems": 5, "hasMoreItems": false, "totalNumItems": 5 }
DELETE /api/system/metrics/{metric}
- Reset a metric for all tenants.
- As of Version
-
2023 Spring
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Reset the specified metric for all tenants.
Following values are available for the metric path parameter:
-
storage
- Recalculate the binary storage individually used by tenants. The processing is managed by theaudit
Service and can be adjusted and even automated via its service configuration.High Database WorkloadWe do not recommend a regular usage of this endpoint. Each call triggers a recalculation of the storage metric for all tenants. During the processing time, no storage metric can be retrieved.
- Request Example
-
/api/system/metrics/storage
- Result Example
-
200 OK
Role Set
GET /api/system/permissions
- Retrieve the global role set XML/JSON.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
XML/JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to retrieve the global permissions file of the yuuvis® system.
- Request Headers
-
Accept: [application/xml; application/json]
- Response Example
-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/"> <role> <name>ReadDeleteEmail</name> <permission> <action>read</action> <action>delete</action> <condition>system:objectTypeId = 'email:email'</condition> </permission> </role> <role> <name>ReadDocument</name> <permission> <action>read</action> <condition>system:objectTypeId = 'document'</condition> </permission> </role> <role> <name>ReadEmailAndDocument</name> <permission> <action>read</action> <condition>system:objectTypeId in ('email:email', 'document')</condition> </permission> </role> <role> <name>DeleteDocument</name> <permission> <action>delete</action> <condition>system:objectTypeId in ('document')</condition> </permission> </role> <role> <name>AdminRole</name> <permission> <action>read</action> <action>delete</action> </permission> </role> </roleSet>
POST /api/system/permissions
- Update the global role set.
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to update the global permissions file of the yuuvis® system. Similar to other schema update endpoints in yuuvis®, this infers a schema validation and returns its result to the user, performing the update only after successful validation.
- Request Headers
-
Content-Type: application/xml
- Request Example
-
/api/system/permissions
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/"> <role> <name>ReadDeleteEmail</name> <permission> <action>read</action> <action>delete</action> <condition>system:objectTypeId = 'email:email'</condition> </permission> </role> <role> <name>ReadDocument</name> <permission> <action>read</action> <condition>system:objectTypeId = 'document'</condition> </permission> </role> <role> <name>ReadEmailAndDocument</name> <permission> <action>read</action> <condition>system:objectTypeId in ('email:email', 'document')</condition> </permission> </role> <role> <name>DeleteDocument</name> <permission> <action>delete</action> <condition>system:objectTypeId in ('document')</condition> </permission> </role> <role> <name>AdminRole</name> <permission> <action>read</action> <action>create</action> <action>delete</action> </permission> </role> </roleSet>
- Response Example
-
The result is a JSON structure containing a
validationErrors
list, which could be an empty list.200 - no validation errors, the role set has been updated{ "validationErrors": [] }
422 - there were validation errors, the role set was not updated{ "validationErrors": [ { "message": "Unable to unmarshal schema. [line: 14][column: 13] cvc-complex-type.2.4.a: Invalid content was found starting with element 'condition'. One of '{\"http://optimal-systems.org/ns/dmscloud/roleset/\":action}' is expected." } ] }
POST /api/system/permissions/validate
- Validate the global role set.
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to validate a permissions file to determine its fitness to become the new global permissions file of the yuuvis® system.
- Request Headers
-
Content-Type: application/xml
- Request Example
-
/api/system/permissions/validate
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/"> <role> <name>ReadDeleteEmail</name> <permission> <action>read</action> <action>delete</action> <condition>system:objectTypeId = 'email:email'</condition> </permission> </role> <role> <name>ReadDocument</name> <permission> <action>read</action> <condition>system:objectTypeId = 'document'</condition> </permission> </role> <role> <name>ReadEmailAndDocument</name> <permission> <action>read</action> <condition>system:objectTypeId in ('email:email', 'document')</condition> </permission> </role> <role> <name>DeleteDocument</name> <permission> <action>delete</action> <condition>system:objectTypeId in ('document')</condition> </permission> </role> <role> <name>AdminRole</name> <permission> <action>read</action> <action>create</action> <action>delete</action> </permission> </role> </roleSet>
- Response Example
-
The result is a JSON structure containing a validationErrors list, which could be an empty list.
200 - no validation errors, the role set has been updated{ "validationErrors": [] }
422 - there were validation errors, the role set was not updated{ "validationErrors": [ { "message": "Unable to unmarshal schema. [line: 14][column: 13] cvc-complex-type.2.4.a: Invalid content was found starting with element 'condition'. One of '{\"http://optimal-systems.org/ns/dmscloud/roleset/\":action}' is expected." } ] }
Schema
GET /api/system/schema
- Retrieve the global schema XML/JSON.
- As of Version
-
1.0
- Request Method
-
GET
- Response Format
-
XML, JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to retrieve the global schema of the yuuvis® system.
- Request Headers
-
Accept: [application/xml; application/json]
- Response Example
-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/"> <version>4</version> <lastModificationDate>2019-09-12T16:53:49.644Z</lastModificationDate> <propertyDateTimeDefinition> <id>date</id> <propertyType>datetime</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyDateTimeDefinition> <propertyStringDefinition> <id>Name</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> <typeDocumentDefinition> <id>document</id> <baseId>system:document</baseId> <propertyReference>Name</propertyReference> <propertyReference>date</propertyReference> <contentStreamAllowed>required</contentStreamAllowed> <secondaryObjectTypeId>system:rmDestructionRetention</secondaryObjectTypeId> </typeDocumentDefinition> </schema>
POST /api/system/schema
- Update the global schema.
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to update the global schema of the yuuvis® system. Similar to other schema update endpoints in yuuvis®, this infers a schema validation and returns its result to the user, performing the schema update only after successful validation.
- Request Headers
-
Content-Type: application/xml
- Response Example
-
The result is a JSON structure containing a
validationErrors
list, which could be an empty list.200 - no validation errors{ "validationErrors": [] }
422 - there were validation errors{ "validationErrors": [ { "message": "Ambiguous ids. There are 2 property type definitions with the id 'from'.", "serviceErrorCode": 2110 }, { "message": "Wrong base id. The base id of the system:document type definition 'email' must be 'system:document', but it is 'system:folder'.", "serviceErrorCode": 2131 }, { "message": "Invalid property reference 'fromm' in type definition 'email'.", "serviceErrorCode": 2132 }, { "message": "Invalid secondary object type reference 'appAcl:aclowner' in type definition 'email'.", "serviceErrorCode": 2135 } ] }
POST /api/system/schema/validate
- Validate the global schema.
- As of Version
-
1.0
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to validate a schema file for fitness for being the new global schema of the yuuvis® system.
- Request Headers
-
Content-Type: application/xml
- Response Example
-
The result is a JSON structure containing a
validationErrors
list, which could be an empty list.200 - no validation errors, the schema has been updated{ "validationErrors": [] }
422 - there were validation errors, the schema was not updated{ "validationErrors": [ { "message": "Ambiguous ids. There are 2 property type definitions with the id 'from'.", "serviceErrorCode": 2110 }, { "message": "Wrong base id. The base id of the system:document type definition 'email' must be 'system:document', but it is 'system:folder'.", "serviceErrorCode": 2131 }, { "message": "Invalid property reference 'fromm' in type definition 'email'.", "serviceErrorCode": 2132 }, { "message": "Invalid secondary object type reference 'appAcl:aclowner' in type definition 'email'.", "serviceErrorCode": 2135 } ] }
System Hooks
GET /api/system/systemhooks
- Retrieve the global system hook configuration.
- As of Version
-
2022 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Retrieves the global system hook configuration.
The content of the global
systemHookConfiguration.json
configuration file is returned. The configured system hooks are available in all tenants. - Request Headers
-
Accept: [application/json]
- Request Example
-
/api/system/systemhooks
- Response Example
-
{ "systemhooks": { "amqp": [ { "bulkSize": 10, "enable": true, "password": "secret", "predicate": "spel:(contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null && contentStreams[0]['range'].length() > 0) ? true : false", "queue": "lc.textextraction", "type": "object.insert.document", "url": "10.10.6.243:5674", "user": "clouduser" } ], "webhooks": [ { "enable": true, "predicate": "spel:true", "type": "user.info", "url": "http://organization/api/userinfo/${tenant}/${userId}" } ] } }
POST /api/system/systemhooks
- Update the global system hook configuration.
- As of Version
-
2022 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Updates the global system hook configuration.
The content of the global
systemHookConfiguration.json
configuration file is replaced by the configuration specified in the JSON request body. Its structure is validated and has to match the structure described here. Especially, the type of each defined AMQP hook and webhook has to be valid.The configured system hooks are available in all tenants.
The changes are applied immediately after a successful update of the configuration.
- Request Headers
-
Content-Type: [application/json]
- Request Example
-
/api/system/systemhooks
Request Body{ "systemhooks": { "amqp": [ { "bulkSize": 10, "enable": true, "password": "secret", "predicate": "spel:(contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null && contentStreams[0]['range'].length() > 0) ? true : false", "queue": "lc.textextraction", "type": "object.insert.document", "url": "10.10.6.243:5674", "user": "clouduser" } ], "webhooks": [ { "enable": true, "predicate": "spel:true", "type": "user.info", "url": "http://organization/api/userinfo/${tenant}/${userId}" } ] } }
- Response Example
-
200 OK
POST /api/system/systemhooks/validate
- Validate the global system hook configuration.
- As of Version
-
2022 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Validates the global system hook configuration.
The content of the global
systemHookConfiguration.json
configuration file to be validated is specified in the JSON request body. Its structure is validated and has to match the structure described here. Especially, the type of each defined AMQP hook and webhook has to be valid.To apply a valid global system hook configuration, use the endpoint
POST /api/system/systemhooks
. - Request Headers
-
Content-Type: [application/json]
- Request Example
-
/api/system/systemhooks
{ "systemhooks": { "amqp": [ { "bulkSize": 10, "enable": true, "password": "secret", "predicate": "spel:(contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null && contentStreams[0]['range'].length() > 0) ? true : false", "queue": "lc.textextraction", "type": "object.insert.document", "url": "10.10.6.243:5674", "user": "clouduser" } ], "webhooks": [ { "enable": true, "predicate": "spel:true", "type": "user.info", "url": "http://organization/api/userinfo/${tenant}/${userId}" } ] } }
- Response Example
-
200 OK
Tracing Endpoints
GET /api/system/calls
- Retrieve active DMS calls.
- As of Version
-
2020 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to determine all active DMS calls (
/api/dms
) of the yuuvis® system. - Request Headers
-
Accept: [application/json]
- Request Example
-
/api/system/calls
- Response Example
-
Each request always returns an array, even if the result set is a single active call. If no active call exists, the response is an empty array.
[ { "traceid": "5709116f3fb6c00a", "type": "READ", "tenant": "default", "method": "GET", "request": "/api/dms/objects/440992a0-905c-441a-8724-1ba9beb79e1b/contents/renditions/text", "starttime": 1597926536580 } ]
GET /api/system/calls/{traceid}
- Retrieve active DMS call for the specified traceid.
- As of Version
-
2020 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to determine all active DMS calls (
/api/dms
) of the yuuvis® system with the giventraceid
. - Request Headers
-
Accept: [application/json]
- Request Example
-
/api/system/calls/5709116F3FB6C00A
- Response Example
-
Each request always returns an array, even if the result set is a single active call. If no active call exists, the response is an empty array.
[ { "traceid": "5709116F3FB6C00A", "type": "READ", "tenant": "default", "method": "GET", "request": "/api/dms/objects/440992a0-905c-441a-8724-1ba9beb79e1b/contents/renditions/text", "starttime": 1597926536580 } ]
App Endpoints
GET /api/system/apps
- Retrieve all applications
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Retrieves all existing apps in the system.
- Response Example
-
{ "acl" : { }, "client" : { }, "clientsystem" : { }, "email" : { }, "invoice" : { }, "training" : { } }
GET /api/system/apps/{app}/permissions
- Retrieve an application role set.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
XML/JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to retrieve the global application permissions file of the yuuvis® system specified by the app URL parameter.
- Request Headers
-
Accept: [application/xml; application/json]
- Response Example
-
Response Body
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/"> <role> <name>ReadDeleteEmail</name> <permission> <action>read</action> <action>delete</action> <condition>system:objectTypeId = 'email:email'</condition> </permission> </role> <role> <name>ReadDocument</name> <permission> <action>read</action> <condition>system:objectTypeId = 'document'</condition> </permission> </role> <role> <name>ReadEmailAndDocument</name> <permission> <action>read</action> <condition>system:objectTypeId in ('email:email', 'document')</condition> </permission> </role> <role> <name>DeleteDocument</name> <permission> <action>delete</action> <condition>system:objectTypeId in ('document')</condition> </permission> </role> <role> <name>AdminRole</name> <permission> <action>read</action> <action>delete</action> </permission> </role> </roleSet>
POST /api/system/apps/{app}/permissions
- Update an application role set.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
XML/JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to update the global application permissions file of the yuuvis® system specified by the app URL parameter. Similar to other schema update endpoints in yuuvis®, this infers a schema validation and returns its result to the user, performing the update only after successful validation.
App names must match a specific regular expression and are limited in their length.
- Request Headers
-
Accept: [application/xml; application/json]
- Request Example
-
Request Body
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/"> <role> <name>ReadDeleteEmail</name> <permission> <action>read</action> <action>delete</action> <condition>system:objectTypeId = 'email:email'</condition> </permission> </role> <role> <name>ReadDocument</name> <permission> <action>read</action> <condition>system:objectTypeId = 'document'</condition> </permission> </role> <role> <name>ReadEmailAndDocument</name> <permission> <action>read</action> <condition>system:objectTypeId in ('email:email', 'document')</condition> </permission> </role> <role> <name>DeleteDocument</name> <permission> <action>delete</action> <condition>system:objectTypeId in ('document')</condition> </permission> </role> <role> <name>AdminRole</name> <permission> <action>read</action> <action>delete</action> </permission> </role> </roleSet>
- Response Example
-
The result is a JSON structure containing a validationErrors list, which could be an empty list.
200 - no validation errors, the role set was updated{ "validationErrors": [] }
422 - there were validation errors, the role set was not updated{ "validationErrors": [ { "message": "Unable to unmarshal schema. [line: 14][column: 13] cvc-complex-type.2.4.a: Ungültiger Content wurde beginnend mit Element 'condition' gefunden. '{\"http://optimal-systems.org/ns/dmscloud/roleset/\":action}' wird erwartet." } ] }
POST /api/system/apps/{app}/permissions/validate
- Validate an application role set.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
XML/JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to validate the global application permissions file of the yuuvis® system specified by the app URL parameter.
App names must match a specific regular expression and are limited in their length.
- Request Headers
-
Accept: [application/xml; application/json]
- Request Example
-
Request Body
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/"> <role> <name>ReadDeleteEmail</name> <permission> <action>read</action> <action>delete</action> <condition>system:objectTypeId = 'email:email'</condition> </permission> </role> <role> <name>ReadDocument</name> <permission> <action>read</action> <condition>system:objectTypeId = 'document'</condition> </permission> </role> <role> <name>ReadEmailAndDocument</name> <permission> <action>read</action> <condition>system:objectTypeId in ('email:email', 'document')</condition> </permission> </role> <role> <name>DeleteDocument</name> <permission> <action>delete</action> <condition>system:objectTypeId in ('document')</condition> </permission> </role> <role> <name>AdminRole</name> <permission> <action>read</action> <action>delete</action> </permission> </role> </roleSet>
- Response Example
-
The result is a JSON structure containing a
validationErrors
list, which could be an empty list.200 - no validation errors, the role set was updated{ "validationErrors": [] }
422 - there were validation errors, the role set was not updated{ "validationErrors": [ { "message": "Unable to unmarshal schema. [line: 14][column: 13] cvc-complex-type.2.4.a: Ungültiger Content wurde beginnend mit Element 'condition' gefunden. '{\"http://optimal-systems.org/ns/dmscloud/roleset/\":action}' wird erwartet." } ] }
GET /api/system/apps/{app}/schema
- Retrieve an application schema.
- As of Version
-
2019 Winter
- Request Method
-
GET
- Response Format
-
XML, JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to retrieve the application schema matching with the
app
path parameter. - Request Headers
-
accept: [application/xml; application/json]
- Response Example
-
The result is a JSON/XML structure containing the application schema
Response Body<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/"> <version>2</version> <lastModificationDate>2020-02-17T22:22:40.532Z</lastModificationDate> <propertyStringDefinition> <id>from</id> <description>system-wide field for the e-mail sender</description> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> <classification>email</classification> </propertyStringDefinition> <propertyStringDefinition> <id>to</id> <description>system-wide field for the e-mail recipients</description> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>false</required> <classification>email</classification> </propertyStringDefinition> <propertyStringDefinition> <id>cc</id> <description>system-wide field for the e-mail cc</description> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>false</required> <classification>email</classification> </propertyStringDefinition> <propertyStringDefinition> <id>bcc</id> <description>system-wide field for the e-mail bcc</description> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>false</required> <fulltextIndexed>false</fulltextIndexed> </propertyStringDefinition> <propertyStringDefinition> <id>subject</id> <description>system-wide field for the e-mail subject</description> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> <defaultValue>Krähenschädel</defaultValue> </propertyStringDefinition> <propertyIntegerDefinition> <id>attachmentcount</id> <description>system-wide field for the e-mail attachment count</description> <propertyType>integer</propertyType> <cardinality>single</cardinality> <required>false</required> <defaultValue>0</defaultValue> </propertyIntegerDefinition> <propertyStringDefinition> <id>attachmentnames</id> <description>system-wide field for the e-mail attachment names</description> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>false</required> </propertyStringDefinition> <propertyTableDefinition> <id>meta</id> <description>Additional data</description> <propertyType>table</propertyType> <cardinality>single</cardinality> <required>false</required> <propertyStringDefinition> <id>key</id> <description>Key of this additional data entry.</description> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> <propertyStringDefinition> <id>value</id> <description>Value of this additional data entry.</description> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> </propertyTableDefinition> <propertyStringDefinition> <id>messageid</id> <description>system-wide field for the e-mail message id</description> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> <propertyDateTimeDefinition> <id>received</id> <description>system-wide field for the e-mail received</description> <propertyType>datetime</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyDateTimeDefinition> <propertyStringDefinition> <id>exchangeid</id> <description>system-wide field for the e-mail exchange id</description> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>false</required> </propertyStringDefinition> <typeDocumentDefinition> <id>email</id> <baseId>system:document</baseId> <propertyReference>from</propertyReference> <propertyReference>to</propertyReference> <propertyReference>cc</propertyReference> <propertyReference>bcc</propertyReference> <propertyReference>subject</propertyReference> <propertyReference>attachmentcount</propertyReference> <propertyReference>attachmentnames</propertyReference> <propertyReference>meta</propertyReference> <propertyReference>messageid</propertyReference> <propertyReference>received</propertyReference> <propertyReference>exchangeid</propertyReference> <contentStreamAllowed>required</contentStreamAllowed> <secondaryObjectTypeId>appAcl:aclowner</secondaryObjectTypeId> </typeDocumentDefinition> </schema>
POST /api/system/apps/{app}/schema
- Update the schema of the specified application.
- As of Version
-
2019 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to update the application schema matching with the
app
path parameter. Similar to other schema update endpoints in yuuvis®, this infers a schema validation and returns its result to the user, performing the schema update only after successful validation.App names must match a specific regular expression and are limited in their length.
- Request Headers
-
Content-Type: application/xml
- Response Example
-
The result is a JSON structure containing a
validationErrors
list, which could be an empty list.200 - no validation errors, the schema has been updated{ "validationErrors": [] }
422 - there were validation errors, the schema was not updated{ "validationErrors": [ { "message": "Wrong base id. The base id of the system:document type definition 'appEmail:email' must be 'system:document', but it is 'system:folder'.", "serviceErrorCode": 2131 }, { "message": "Invalid property reference 'fromm' in type definition 'appEmail:email'.", "serviceErrorCode": 2132 }, { "message": "Invalid property reference 'ccd' in type definition 'appEmail:email'.", "serviceErrorCode": 2132 } ] }
POST /api/system/apps/{app}/schema/validate
- Validate the schema of the specified application.
- As of Version
-
2019 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
This endpoint is used to validate a schema file to be used for the application matching with the
app
path parameter. The result is returned to the user.App names must match a specific regular expression and are limited in their length.
- Request Headers
-
Content-Type: application/xml
- Response Example
-
The result is a JSON structure containing a
validationErrors
list, which could be an empty list.200 - no validation errors, the schema has been updated{ "validationErrors": [] }
422 - there were validation errors, the schema was not updated{ "validationErrors": [ { "message": "Wrong base id. The base id of the system:document type definition 'appEmail:email' must be 'system:document', but it is 'system:folder'.", "serviceErrorCode": 2131 }, { "message": "Invalid property reference 'fromm' in type definition 'appEmail:email'.", "serviceErrorCode": 2132 }, { "message": "Invalid property reference 'ccd' in type definition 'appEmail:email'.", "serviceErrorCode": 2132 } ] }
GET /api/system/apps/{app}/systemhooks
- Retrieve the system hook configuration of the specified application.
- As of Version
-
2022 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Retrieves the app-specific system hook configuration for the app specified in the request URL.
The content of the app-specific
systemHookConfiguration.json
configuration file is returned. The configured System Hooks are available only for the concrete App. Note: The app-specific system hooks are available only in tenants where the corresponding app is enabled.An error with status code 404 is thrown if the specified app does not exist or no system hooks are configured for the specified app.
- Request Headers
-
Accept: [application/json]
- Request Example
-
/api/system/apps/myapp/systemhooks
- Response Example
-
Response Body
{ "systemhooks": { "amqp": [], "webhooks": [ { "enable": true, "predicate": "spel:T(java.util.List).of(300).contains(options['action'])", "type": "dms.request.objects.upsert.storage-before", "url": "http://examplewebhook/api/dms/request/objects/update/metadata", "useDiscovery": true } ] } }
POST /api/system/apps/{app}/systemhooks
- Update the system hook configuration of the specified application.
- As of Version
-
2022 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Updates the app-specific system hook configuration for the app specified in the request URL.
The content of the app-specific systemHookConfiguration.json configuration file is replaced by the configuration specified in the request body. Its structure is validated and has to match the structure described here. Especially, the type of each defined AMQP hook and webhook has to be valid.
It is not allowed to configure an app-specific webhook with the user.info type. The configured system hooks are available only for the specified app.
The app-specific system hooks are available only in tenants in which the corresponding app is enabled. If the specified app does not exist, it is created.
App names must match a specific regular expression and are limited in their length.
The changes are applied immediately after a successful update of the configuration.
- Request Headers
-
Content-Type: [application/json]
- Request Example
-
/api/system/apps/myapp/systemhooks
Request Example{ "systemhooks": { "amqp": [], "webhooks": [ { "enable": true, "predicate": "spel:T(java.util.List).of(300).contains(options['action'])", "type": "dms.request.objects.upsert.storage-before", "url": "http://examplewebhook/api/dms/request/objects/update/metadata", "useDiscovery": true } ] } }
- Response Example
-
200 OK
POST /api/system/apps/{app}/systemhooks/validate
- Validate the system hook configuration of the specified application.
- As of Version
-
2022 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Validates the app-specific system hook configuration for the app specified in the request URL.
The content of the app-specific
systemHookConfiguration.json
configuration file to be validated is specified in the JSON request body. Its structure is validated and has to match the structure described here. Especially, the type of each defined AMQP hook and webhook has to be valid.It is not allowed to configure an app-specific webhook with the user.info type. App names must match a specific regular expression and are limited in their length.
To apply a valid app-specific system hook configuration, use the endpoint
POST /api/system/apps/{app}/systemhooks
. - Request Headers
-
Content-Type: [application/json]
- Request Example
-
/api/system/apps/myapp/systemhooks/validate
Request Body{ "systemhooks": { "amqp": [], "webhooks": [ { "enable": true, "predicate": "spel:T(java.util.List).of(300).contains(options['action'])", "type": "dms.request.objects.upsert.storage-before", "url": "http://examplewebhook/api/dms/request/objects/update/metadata", "useDiscovery": true } ] } }
- Response Example
-
200 OK
Tenant Endpoints
Operations on the resources of any tenant in the system.
Apps
GET /api/system/tenants/{tenant}/apps
- Retrieve tenant app set.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
XML
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Retrieves the app set for the specified tenant.
The content of the corresponding app set configuration file
apps.xml
is returned. Not-listed apps are disabled.If the file does not exist, the error code 404 will be returned.
- Request Headers
-
Accept: [application/xml]
- Request Example
-
/api/system/tenants/mytenant/apps
- Response Example
-
App set of the specified tenant mytenant in the response body.
Response Body: example apps.xml<?xml version="1.0" encoding="utf-8"?> <apps xmlns="http://optimal-systems.org/ns/yuuvis/apps/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://optimal-systems.org/ns/yuuvis/apps/ yuuvis-core-apps.xsd"> <app> <name>clientsystem</name> <state>enabled</state> </app> <app> <name>client</name> <state>enabled</state> </app> <app> <name>email</name> <state>disabled</state> </app> <app> <name>acl</name> <state>disabled</state> </app> </apps>
POST api/system/tenants/{tenant}/apps
- Update tenant app set.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Updates the app set for the specified tenant.
The request body contains the XML configuration to be stored as app set for the tenant in the corresponding
apps.xml
file.The call infers a validation and returns its result to the user, performing the update only after successful validation.
App names must match a specific regular expression and are limited in their length.
- Request Headers
-
Content-Type: application/xml
- Request Example
-
XML configuration in the request body.
Request Body<?xml version="1.0" encoding="utf-8"?> <apps xmlns="http://optimal-systems.org/ns/yuuvis/apps/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://optimal-systems.org/ns/yuuvis/apps/ yuuvis-core-apps.xsd"> <app> <name>clientsystem</name> <state>enabled</state> </app> <app> <name>client</name> <state>enabled</state> </app> <app> <name>email</name> <state>disabled</state> </app> <app> <name>acl</name> <state>disabled</state> </app> </apps>
- Response Example
-
(1) Successful update: The result is a JSON structure containing a validationErrors list, which could be an empty list.
200 – no validation errors, the apps for the tenant have been updated{ "validationErrors": [] }
(2) Unsuccessful: Example error message.
422 – validation errors, the apps have not been updated{ "validationErrors": [ { "message": "Unable to disable app 'client' and enable app 'invoice'. There are references from the schema of app 'invoice' to the schema of app 'client'." } ] }
POST /api/system/tenants/{tenant}/apps/validate
- Validate tenant app set.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Validates the app set for the specified tenant.
The request body contains the XML configuration to be validated as app set for the tenant.
The validation of the app set considers dependencies between different app and tenant schemata via property references or secondary object type references. If the schema of an app is referenced by the global or the corresponding tenant schema, the app cannot be disabled for the specified tenant. For instance if the app invoice depends on the app client, it is not possible to enable invoice and disable client.
There is no validation for the existence of apps with the specified names.
- Request Headers
-
Content-Type: application/xml
- Request Example
-
XML configuration in the response body.
<?xml version="1.0" encoding="utf-8"?> <apps xmlns="http://optimal-systems.org/ns/yuuvis/apps/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://optimal-systems.org/ns/yuuvis/apps/ yuuvis-core-apps.xsd"> <app> <name>clientsystem</name> <state>enabled</state> </app> <app> <name>client</name> <state>enabled</state> </app> <app> <name>email</name> <state>disabled</state> </app> <app> <name>acl</name> <state>disabled</state> </app> </apps>
- Response Example
-
(1) Successful update: The result is a JSON structure containing a validationErrors list, which could be an empty list.
200 – no validation errors, the role set has been updated
{ "validationErrors": [] }
(2) Unsuccessful: Example error message.
422 – validation errors, the role set has not been updated
{ "validationErrors": [ { "message": "Unable to disable app 'client' and enable app 'invoice'. There are references from the schema of app 'invoice' to the schema of app 'client'." } ] }
Metrics
GET /api/system/tenants/{tenant}/metrics/{metric}
- Retrieve a tenant metric.
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and if the specified access condition is matched. - Description
-
Retrieve the specified metric for the specified tenant.
Following values are available for the metric path parameter:
-
storage
- The endpoint retrieves the dynamically calculated binary storage used by the specified tenant. -
objectCount
(as of 2023 Summer) - The endpoint retrieves the number of DMS objects within the specified tenant.
-
- Request Examples
-
(A)
/api/system/tenants/yuuvistest/metrics/storage
(B)
/api/system/tenants/yuuvistest/metrics/objectCount
- Response Examples
-
(A)
{ "objects": [ { "properties": { "system:tenant": { "value": "yuuvistest" } }, "options": { "storageUsed": { "humanReadable": "121 MB", "value": 127508469 } } } ], "numItems": 1, "hasMoreItems": false, "totalNumItems": 1 }
(B){ "objects": [{ "properties": { "system:tenant": { "value": "yuuvistest" } }, "options": { "objectCount": { "totalFolderCount": 97, "totalObjectCount": 1733 } } } ], "numItems": 1, "hasMoreItems": false, "totalNumItems": 1 }
DELETE /api/system/tenants/{tenant}/metrics/{metric}
- Reset a tenant metric.
- As of Version
-
2023 Spring
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Reset the specified metric for the specified tenant.
Not available for the
storage
metric. UseDELETE /api/system/metrics/{metric}
instead.
Role Set
GET /api/system/tenants/{tenant}/permissions
- Retrieve a tenant role set.
- As of Version
-
2022 Autumn
- Request Method
-
GET
- Response Format
-
XML
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Retrieves the tenant-specific role set for the tenant specified in the request URL.
The content of the tenant-specific role set is returned. The configured roles are available only for the concrete tenant.
- Request Headers
-
Accept: [application/xml]
- Request Example
-
/api/system/tenants/mytenant/permissions
- Response Example
POST /api/system/tenants/{tenant}/permissions
- Update a tenant role set.
- As of Version
-
2022 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Updates the tenant-specific role set for the tenant specified in the request URL.
The content of the tenant-specific role set is replaced by the configuration specified in the request body. The configured roles are available only for the concrete tenant.
- Request Headers
-
Content-Type: application/xml
- Request Example
-
/api/system/tenants/mytenant/permissions
body see
POST /api/system/permissions
- Response Example
POST /api/system/tenants/{tenant}/permissions/validate
- Validate a tenant role set.
- As of Version
-
2022 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Validates the tenant-specific role set for the tenant specified in the request URL.
The content of the tenant-specific role set to be validated is specified in the JSON request body. To apply the configuration, use the endpoint
POST /api/system/tenants/{tenant}/permissions
. - Request Headers
-
Content-Type: application/xml
- Request Example
-
/api/system/tenants/mytenant/permissions
- Response Example
Schema
GET /api/system/tenants/{tenant}/schema
- Retrieve the schema of the specified tenant.
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
XML, JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Retrieves the tenant schema that is stored for the tenant matching the
tenant
path parameter.The schema is provided in an XML or JSON structure in the response body.
- Request Headers
-
Accept:[application/xml; application/json]
- Response Example
-
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/"> <version>1</version> <lastModificationDate>2019-03-25T10:25:46.212Z</lastModificationDate <propertyStringDefinition> <id>from</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>true</required> </propertyStringDefinition> <propertyStringDefinition> <id>to</id> <propertyType>string</propertyType> <cardinality>multi</cardinality> <required>true</required> </propertyStringDefinition> <propertyStringDefinition> <id>subject</id> <propertyType>string</propertyType> <cardinality>single</cardinality> <required>true</required> <maxLength>60</maxLength> </propertyStringDefinition> <propertyDateTimeDefinition> <id>received</id> <propertyType>datetime</propertyType> <cardinality>single</cardinality> <required>true</required> </propertyDateTimeDefinition> <typeDocumentDefinition> <id>email</id> <baseId>system:document</baseId> <propertyReference>from</propertyReference> <propertyReference>to</propertyReference> <propertyReference>received</propertyReference> <contentStreamAllowed>required</contentStreamAllowed> </typeDocumentDefinition> </schema>
POST /api/system/tenants/{tenant}/schema
- Update the schema of the specified tenant.
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Updates the tenant schema stored for the tenant specified by the
tenant
path parameter.The new schema is passed in the request body in XML format and is validated before the update is executed. Thus, it is not possible to introduce an invalid schema via this endpoint.
For details and examples regarding request and response please visit Schema - Defining Object Types.
- Request Headers
-
Content-Type: application/xml
POST /api/system/tenants/{tenant}/schema/validate
- Validate the schema of the specified tenant.
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. - Description
-
Validate the XML file passed in the request body for the usability as tenant schema for the tenant specified by the
tenant
path parameter.The currently used tenant schema is NOT updated.
For details and examples regarding request and response please visit schema.
- Request Headers
-
Content-Type: application/xml
2.11.4. Endpoints for PDF/A-3 Renditions
Endpoints Available on Request
These rendition endpoints are offered in a separate API as an extra service and are available only on request. This API is not included in yuuvis® Momentum installations.
|
POST /api/renditions/pdf?level=pdfa3
- Create and retrieve a PDF/A-3 rendition for an e-mail.
Endpoint Available on Request
This endpoint is offered in a separate API that is available only on request. It is not included in yuuvis® Momentum installations.
|
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
PDF/A-3
- Description
-
To return the PDF/A-3 rendition of the e-mail object, send the request with the e-mail file as binary in the request body.
The endpoint URL contains the specification of the
level
parameter set to the value topdfa3
. Other values for thelevel
parameter are not accepted.Synchronously converts all convertible parts of an e-mail including its first order attachments into the format PDF/A-3. The original e-mail itself will be included as a PDF attachment as well.
Requires an e-mail object. A successful POST returns the HTTP status code 200 together with the PDF/A-3 document in the body.
The endpoint accepts the following e-mail attachment file types for the conversion into PDF/A-3 document pages:
Types Extension Note Portable Document Format
pdf
As of 2021 Autumn: ZIP Archive File Format
zip
The content files of the zip archive will be converted individually and included into the PDF/A-3 file in the order of their sorting in the archive.
The files inside the zip archive have to meet at least one of the following conditions:
-
All files have the same convertible file type.
-
All files are image files of supported types as listed below. Different types are allowed within one zip archive.
The content files of a zip archive will not be converted if at least one zip archive is among them as well.
Microsoft Office and Excel file types
MS Office Word 97-2016
doc, docx
MS Office PowerPoint 97-2016
ppt, pptx
MS Office Excel 97-2016
xls, xlsx
OpenDocument Text
odt
OpenDocument Presentation
odp
OpenDocument Spreadsheet
ods
Visio Drawing File
vsd, vsdx
limited range of functions
Image File Types
Tagged Image File Format
tiff, tif
Portable Bitmap Image
pbm
Bitmap Image File
bmp
Graphical Interchange Format File
gif
JPEG Image
Exchangeable image file format (JPEG)
jpg, jng, jpeg
Portable Network Graphic
png
Weppy Image Format (Lossy Compression)
webp
As of 2021 Autumn: High Efficiency Image File Format (HEIF)
heif, heic
Response HTTP status codes:
HTTP status code Meaning 200
Successful, converted document provided in the response body
413
Document file too large
415
Document format not supported
422
Timeout
422
Document could not be converted
422
Invalid input parameters
-
- Request Header
-
Content-Type: message/rfc822 or application/vnd.ms-outlook
Content-Disposition: attachment; filename=<filename>; filename*=<filename-encoded>.
To set the filename of the new content file. The parameters "filename" and "filename*" differ only in that "filename*" uses the encoding defined in RFC 5987. When both "filename" and "filename*" are present in a single header field value, "filename*" is preferred over "filename".
- Request Example
-
The e-mail file is passed as binary in the request body.
- Result Example
-
HTTP status code:
200
Response body with PDF/A-3 document.
2.12. Cluster-Internal API
Endpoints of services for interactions within the cluster.
2.12.1. '/manage/*' Endpoints
Use monitoring and maintenance endpoints of a service running in your yuuvis® Momentum cluster.
The core services offer /manage/* endpoints to retrieve service-specific operational information, reload configurations or execute other maintenance operations. These endpoints are intended to be called by other services within the cluster. Most services use the functionality of the Spring Boot Actuator. However, for some services, the basic behavior is adjusted or extended.
The /manage/*
endpoints provided by the authentication
Service are available via a separate port which is protected from external access. Even if they are exposed for access without a specific authorization in the authentication-prod.yml file, they are accessible only for services inside the Kubernetes cluster. In order to call these endpoints, the ancillary Kubernetes Service authentication-manage-service controls the separate port. Thus, the endpoints are called via /authentication-manage/manage/*
.
GET <service>/manage/health
- Check a service’s status.
- Usage
-
Check the current status of a service running in your yuuvis® Momentum cluster.
- Services
-
Available for all services including additional services. The JSON structure always contains at least the "status" key with the value being either "UP" or "DOWN".
POST <service>/manage/refresh
- Reload a service’s configuration.
- Usage
-
Reload configurations for the specified service without a service restart.
- Services with adjusted behavior
-
-
authentication
service (as of version 2022 Autumn)See endpoint
GET /authentication-internal/manage/refreshTenants
. -
configservice
A refresh leads to a synchronization of local resources and the git server in addition to the regular synchronization cycle.
-
2.12.2. Endpoints of 'authentication' Service
GET /authentication-internal/session/invalidateAll/{userId}
- Invalidate all user sessions
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2022 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Invalidates all active sessions of the user specified by
userId
.If the request was successfully processed, the response body is empty. The response does not inform about the number of invalidated sessions for the specified user. Especially, if the specified user has no active sessions, the endpoint does not invalidate any session but still confirms that the request was successfully processed.
In case an error occurs, the request body contains details.
- Request Example
-
curl http://authentication-internal/session/invalidateAll/406b5a28-7a8b-4c36-a569-df7bff480375
- Response Example
-
200 OK
GET /authentication-internal/session/updateUserAttributesCache/{tenant}/{userId}
- Retrieve user attributes from cache or add them to cache.
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2023 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Stores the user attributes for the requested user specified by
tenant
anduserId
in a Redis cache.The parameter
authorization.cacheUserAttributes
inauthentication-prod.yml
has to be set totrue
. This means that authorities information (andabac
information if available) are not stored in the JWT but in a Redis cache instead to reduce the header size of cluster-internal HTTP requests.If
authorization.cacheUserAttributes
isfalse
(default), the user attributes are retrieved without storing them in a cache.The
authentication
service retrieves the user’s attributes-
either from the Redis cache or,
-
if not available in the cache, via
GET user.info
webhook and stores them in the cache.
If the request was successfully processed, the user’s attributes are returned in JSON format in the response body.
-
- Request Example
-
curl http://authentication-internal/session/updateUserAttributeCache/yuuvistest/406b5a28-7a8b-4c36-a569-df7bff480375
- Response Example
-
200 OK
Response Body{ "username": "mustermann", "id": "406b5a28-7a8b-4c36-a569-df7bff480375", "credentialsNonExpired": true, "accountNonExpired": true, "accountNonLocked": true, "enabled": true, "tenant": "yuuvistest", "authorities": [ "TENANT_ADMIN", "SYSTEM_INTEGRATOR", "ACCESS_MAILBOXES" ], "abac": { "mailGroups": [ "mailbox_sales", "mailbox_pm" ], "sap_permissions": [ "sap_read", "sap_write" ] } }
GET /authentication-internal/jwt/verify
- Validate the internal JWT
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
Authorization
- Description
-
Validates the internal JSON Web Token (JWT) that is assigned to an HTTP request.
If the signature of the JWT matches its header and payload, the validation will be successful and the response body contains
true
. If the validation fails, the response body containsfalse
.In order to activate the validation, manual configuration is required.
- Request Example
-
curl http://authentication-internal/jwt/verify
- Response Example
-
true
GET /authentication-internal/jwt/token
- Retrieve an internal JWT
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2022 Autumn
- Request Method
-
GET
- Response Format
-
text/plain;charset=utf-8
- Request Header
-
Authorization with internal Bearer token
- Description
-
Requests an internal JSON Web Token (JWT) that can be used by a service account to access internal endpoints of services running within the yuuvis® Momentum cluster.
The endpoint requires either basic authentication (Example A) or a token provided by the identity provider (Example B) retrieved via its OIDC interface.
- Request Example
-
Example A
curl -H "Authorization: Basic dXNyOnB3ZA==" -H "X-ID-TENANT-NAME: tenant" http://authentication-internal/jwt/token
Example B
curl -H "Authorization: Bearer eyJhbGci..." -H "X-ID-TENANT-NAME: tenant" http://authentication-internal/jwt/token
- Response Example
-
Bearer eyJraWQiOiJqd3Qtc2lnbmluZy1rZXkiLCJhbGciOiJSUzI1NiJ9.eyJzd...
GET /authentication-internal/manage/refreshTenants
- Refresh the tenant configuration
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2022 Autumn
- Request Method
-
GET
- Response Format
-
HTTP status code
- Request Header
-
Authorization with internal Bearer token
- Description
-
The endpoint
/authentication-internal/manage/refreshTenants
can be used to activate changes in the tenant configuration instead of the conventional refresh endpoint. Only changes in theauthentication.oauth2.tenants
list in the application-oauth2.yml configuration file are considered. Thus, the creation or modification of tenants can be carried out much faster.Tenants that were removed from the configuration are NOT automatically deleted. - Request Example
-
curl http://authentication-internal/manage/refreshTenants
- Response Example
-
200 OK
2.12.3. Endpoints of 'configservice'
POST /configservice/manage/refresh
- Synchronize local resources and the git server in addition to the regular synchronization cycle.
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2022 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
successful authentication
- Description
-
Synchronizes the local resources of the
configservice
running on the specified port and the remote resources on the git server.This synchronization is additional and independent of the automated synchronization every 5 minutes.
The endpoint is a standard Spring Boot Actuator endpoint.
- Request Example
-
http://10.11.8.276:7281/manage/refresh
- Response Example
-
200 OK
POST /configservice/api/resources/{resourceName}/path/{pathName}
- Update a global configuration file.
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- HTTP Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
successful authentication
- Description
-
Updates the global configuration file specified by
resourceName
in Git at the path specified bypathName
.In the value for
pathName
, use|
characters instead of/
or\
characters.The previous file is replaced by the new file in the request body.
To apply the new configuration, after the successful update, all services that reference the contained configuration parameters have to be refreshed/restarted.
- Request Example
-
The following example request updates the
application-oauth2.yml
configuration file in order to introduce new tenants.After successful resource update, the following endpoints have to be called to apply the new configuration:
cURL example for unix bashcurl -s -i -k -X POST --url "http://configservice.yuuvis/api/resources/application-oauth2.yml/path/|" \ -H "Content-Type: multipart/form-data; boundary=--------------------------522935013788975240240820" \ --data-binary '----------------------------522935013788975240240820 Content-Disposition: form-data; name="resource"; filename="" Content-Type: application/json keycloak.host: 192.168.62.151:30111 authentication.oauth2.tenants: - name: yuuvistest clientId: yuuvis-authentication-service clientSecret: dbdf4856-3c86-4e5f-aca7-96f3d93d35b4 userAuthorizationUri: https://${keycloak.host}/auth/realms/yuuvistest/protocol/openid-connect/auth accessTokenUri: https://${keycloak.host}/auth/realms/yuuvistest/protocol/openid-connect/token userInfoUri: https://${keycloak.host}/auth/realms/yuuvistest/protocol/openid-connect/userinfo endSessionUri: https://${keycloak.host}/auth/realms/yuuvistest/protocol/openid-connect/logout userNameExtractionPattern: $.sub scope: openid - name: testyuuvis clientId: yuuvis-authentication-service clientSecret: 61048b73-8cd7-4682-b78c-786c5dc8a2a1 userAuthorizationUri: https://${keycloak.host}/auth/realms/testyuuvis/protocol/openid-connect/auth accessTokenUri: https://${keycloak.host}/auth/realms/testyuuvis/protocol/openid-connect/token userInfoUri: https://${keycloak.host}/auth/realms/testyuuvis/protocol/openid-connect/userinfo endSessionUri: https://${keycloak.host}/auth/realms/testyuuvis/protocol/openid-connect/logout userNameExtractionPattern: $.sub scope: openid # configuration for the yuuvis organization service keycloak.server: https://keycloak-https.infrastructure/auth keycloak.admin.username: keycloak keycloak.admin.password: changeme ----------------------------522935013788975240240820--'
- Response Example
-
200 OK
no response body
2.12.4. Endpoints of 'search' Service
POST /search/api/search/dsl/check
- Retrieve the object types that are available for all available actions on DMS objects for the currently logged-in user.
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2021 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the object types that are available for all available
actions
on DMS objects for the currently logged-in user. Available actions arecreate
,write
,read
anddelete
(see role set documentation).The response body is a JSON structure listing the object types grouped in instantiable object types (including folder and document object types) and secondary object types for each action. Every missing
action
in the response map indicates a prohibited action for this user.The list of available object types might contain types that are forbidden under specific conditions defined in the role set. If a role contains a permission for the specified action
that is limited by a condition, this condition can reference type-specific metadata properties. In this case, the entire condition is always evaluated astrue
. - Request Example
-
https://<host>/search/api/search/dsl/check
- Response Example
-
{ "CREATE": { "secondaryObjectTypeIds": [], "objectTypeIds": [] }, "WRITE": { "secondaryObjectTypeIds": [ "system:rmDestructionRetention", "appClient:clientdefaults" ], "objectTypeIds": [ "email:email", "appEmail:email" ] }, "READ": { "secondaryObjectTypeIds": [ "system:rmDestructionRetention", "appClient:clientdefaults" ], "objectTypeIds": [ "email:email", "appEmail:email", "document:invoice" ] } }
POST /search/api/search/dsl/check/{action}
- Retrieves the object types that are available for the specified action
on DMS objects for the currently logged-in user.
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2021 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the object types that are available for the specified
action
on DMS objects for the currently logged-in user. Available options arecreate
,write
,read
anddelete
(see role set documentation).The response body is a JSON structure listing the object types grouped in instantiable object types (including folder and document object types) and secondary object types. An empty response map indicates a prohibited
action
for this user.The list of available object types might contain types that are forbidden under specific conditions defined in the role set. If a role contains a permission for the specified action
that is limited by a condition, this condition can reference type-specific metadata properties. In this case, the entire condition is always evaluated astrue
. - Request Example
-
https://<host>/search/api/search/dsl/check/create
- Response Example
-
{ "CREATE": { "secondaryObjectTypeIds": [ "system:rmDestructionRetention", "appClient:clientdefaults" ], "objectTypeIds": [ "email:email". "appEmail:email" ] } }
2.12.5. Endpoints of 'audit' Service
POST /audit/api/dms/objects/custom
- Store a custom audit entry.
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
- As of Version
-
2022 Spring
- Request Method
-
POST
- Request Headers
-
-
Required headers:
-
Content-Type: application/json
-
Authorization: Bearer eyJraW…
Contains the internal token (JWT) that the custom service receives from the corresponding caller.
-
-
Optional header:
-
x-b3-traceid: 6494b222b4a0c111
Contains the traceId if the custom service receives it from the corresponding caller.
-
-
- Response Format
-
HTTP status code
- Specific Error Codes
-
see Error Handling
- Required Permission
-
successful authentication
- Description
-
Stores a custom audit entry specified in the JSON request body.
This internal endpoint of the
audit
Service can be called by custom services running inside the yuuvis® Momentum cluster in order to allow for the creation of custom audit entries.The following values are stored in the corresponding database table:
Column Field value determined by Comment objectid
database
referredobjectid
request body, property
referredObjectId
Required.
Specifies the
system:objectId
of the DMS object for which the audit entry is stored.creationdate
database
createdby
JWT
tenant
JWT
action
-
The value 10000 is always set.
traceid
x-b3-traceid request header if available. If not specified, a null value is set.
detail
request body, property detail
versionnumber
request body, property
system:versionNumber
Required.
Specifies the DMS object version for which the audit entry is stored.
subaction
request body, property
subaction
Can be used to store any integer that can be used to differentiate between multiple types of custom audit entries.
As every audit entry, a custom audit entry can be retrieved via the endpoint
GET /api/dms/objects/{objectId}/history
. - Request Example
-
{ "objects": [ { "properties": { "detail": { "value": "custom details" }, "subaction": { "value": 4321 }, "referredObjectId": { "value": "a7facd2f-0354-490f-8eb3-59a47649492c" }, "system:versionNumber": { "value": 2 } } } ] }
- Response Example
-
200 OK
2.13. Infrastructure
2.13.1. Database Schema
yuuvis® Momentum core uses multiple database tables that are structured as described below. The specification of the data type enables the appropriate handling of the data columns.
The individual databases have to be configured in the application-dbs.yml
configuration file. The supported database providers are listed in the yuuvis® Momentum Requirements section.
General Description
Each database for yuuvis® Momentum core consists of the following five tables:
-
dmsobject
-
dmsobject_oldversions
-
auditentry
-
DATABASECHANGELOG
-
DATABASECHANGELOGLOCK
Please note that these five tables contain only metadata, but no content data.
Table 'dmsobject'
This table contains the metadata for the current version of each object stored in yuuvis® Momentum. The data types apply to the database types postgresql and cockroachdb. Due to the use of JSON for some columns, the table structure can be kept slim. The table contains the following columns:
Column |
Description |
Data Type (max. length) |
|
Corresponds to the general object property |
uuid |
|
Corresponds to the general object property |
int |
|
Corresponds to the general object property |
varchar(36) |
|
Corresponds to the general object property |
varchar(1024) |
|
Corresponds to the general object property |
varchar(256) |
|
Corresponds to the general object property |
varchar(256) |
|
Corresponds to the general object property |
timestamptz |
|
Corresponds to the general object property |
timestamptz |
|
Stores all properties and their values that are assigned to the object based on its object type. |
json |
|
Corresponds to the general object property |
varchar(256) |
|
varchar(64) |
|
|
Stores all properties and their values that describe available renditions for the object. |
json |
|
Corresponds to the content stream property |
bigint |
|
Corresponds to the content stream property |
varchar(128) |
|
Corresponds to the content stream property |
varchar(1024) |
|
Corresponds to the content stream property |
varchar(64) |
|
Corresponds to the content stream property |
varchar(1024) |
|
Corresponds to the content stream property |
varchar(64) |
|
json |
|
|
int |
|
|
Corresponds to the content stream property |
varchar(2048) |
|
Corresponds to the general object property |
varchar(64) |
|
||
|
Corresponds to the content stream property |
varchar(2048) |
|
Corresponds to the general object property |
json |
|
Flags the object to be invisible for users after a deletion request until the deletion process is completed. |
boolean |
Table 'dmsobject_oldversions'
This table contains the same columns as the dmsobject
table, but WITHOUT the last two columns tags
and deleted
. These two columns correspond to properties that are only available for the current version of objects.
Table 'auditentry'
Each action applied to an object is documented in the object’s audit trail. This information is managed using the auditentry
table. The data types apply to the database types postgresql
and cockroachdb
. This table contains the following columns:
Column |
Description |
Data Type (max. length) |
|
Identifies the audit entry. |
bigint; primarykey |
|
Identifies the object for which the entry was written. Corresponds to the general object property |
varchar(36) |
|
Unique date and time of the audit entry creation to ensure traceability. |
timestamptz |
|
ID of the user who requested the action for which the audit entry is created. |
varchar(256) |
|
Identifies the tenant the user specified in |
varchar(256) |
|
Three digit long history code indicating how the object was imported, deleted, updated, or retrieved. |
int |
|
Unique ID to ensure traceability. |
varchar(64) |
|
Description of the history code. |
varchar(256) |
|
The number of the object version to be requested. |
int; required |
|
int |
An example history entry can be found here.
Tables 'DATABASECHANGELOG' and 'DATABASECHANGELOGLOCK'
The DATABASECHANGELOG and DATABASECHANGELOGLOCK tables are automatically generated and used by Liquibase. More information is available in the corresponding documentation provided by Liquibase.
2.13.2. Search Engine
yuuvis® Momentum requires a high-performant search engine, such as Elasticsearch in combination with the IntraFind Linguistics Plug-in and the ICU Analysis Plug-in.
As all our tests are performed with Elasticsearch and the plug-ins mentioned above, the following search behavior description applies to our standard Elasticsearch infrastructure.
General Notes regarding Search Behavior
Paging
Paging is used to retrieve a section of a long result list. Those sections are considered as pages. The number of results per page as well as the first result to be included can be specified in each search request in yuuvis® Momentum. >> Search Query Language
In order to ensure high performance, yuuvis® Momentum does not support the usage of a cursor in search requests. This can have an effect on the paging behavior in following situation:
-
the total number of results is larger than the number of displayed results per page AND
-
some objects matching the query condition are created/updated/deleted before the user retrieves another page of results.
Since the retrieval of another page means a new search request, the total result list is different. Thus, the requested page might contain unexpected results, e.g., results that were already displayed in on the previous page.
Applying a new Configuration
If you changed the index configuration, all objects that are imported afterwards will be indexed as defined by the new configuration. All objects that are already in the system remain unchanged and can be searched as before the configuration update. If you need all objects indexed with refer to the new configuration, you need a reindexing.
The operation itself is slow and requires a lot of resources, as it essentially creates a copy of the original Elasticsearch index within the same Elasticsearch cluster, to make sure enough storage space is available and to optionally create more data nodes which can be shut down after the operation.
An Elasticsearch reindex entails the creation of a new Momentum-capable index, the migration of Elasticsearch data from the original index into said new index, and finally the removal of the old index. These steps are achieved by interaction with the Elasticsearch API, which is exposed by Elasticsearch through port 9200 on selected master nodes. It is highly recommended to create an Elasticsearch snapshot using the same API before attempting the reindex.
Below, you can find a detailed overview of the CURL commands needed to successfully perform a reindex in yuuvis® Momentum. Note that all commands assume you have port-forwarded the ElasticSearch API to \http:\\localhost:9200
.
- Creating a Momentum-Capable Elasticsearch Index
-
Two steps are required to create an Elasticsearch index that can interact with yuuvis® Momentum:
-
Creation of a new Elasticsearch index:
A new index needs to be created to match the specifications of the new requirements.
CURL command & more information
Create a new Index with a unique name.
The creation of the new Elasticsearch index allows for the optimization of the working index for the current storage requirements. Indices work best when storing around 10 GB, and should contain no more than 50 GB of data.
For a cluster than contains 50 GB of Elasticsearch data, a high-performance index might look something like this:
CURL commandcurl -X PUT "localhost:9200/yuuvis_2?pretty" -H 'Content-Type: application/json' -d' { "settings": { "index": { "number_of_shards": 5, "number_of_replicas": 1 } } } '
Make sure to change the index parameters to suit your storage and reliability requirements.
-
Applying yuuvis® Momentum Elasticsearch Index Mapping and Settings:
The yuuvis® Momentum services require Elasticsearch to use a custom mapping. Using Elasticsearch’s automatic mapping algorithm for reindexing renders the new index unusable for the yuuvis® Momentum system.
CURL command & more information
To get a compatible mapping, retrieve the original Elasticsearch index’s mapping by using the Get mapping API:
CURL commandcurl -X GET "localhost:9200/yuuvis/_mapping"
Then apply the extracted mapping the new index
CURL command mappingcurl -X PUT "localhost:9200/yuuvis_2/_mapping?pretty" -H 'Content-Type: application/json' -d' { "dynamic_templates" : [ { "keyword" : { "match" : "key_*", "mapping" : { "type" : "keyword" } } }, { "text" : { "match" : "txt_*", "mapping" : { "type" : "text" } } }, { "string" : { "match" : "str_*", "mapping" : { "fields" : { "raw" : { "type" : "keyword" } }, "type" : "text" } } }, { "number" : { "match" : "num_*", "mapping" : { "type" : "long" } } }, { "double" : { "match" : "dbl_*", "match_mapping_type" : "double", "mapping" : { "type" : "double" } } }, { "object" : { "match" : "obj_*", "match_mapping_type" : "object", "mapping" : { "type" : "object" } } }, { "date" : { "match" : "dte_*", "match_mapping_type" : "date", "mapping" : { "format" : "date_optional_time", "type" : "date" } } }, { "boolean" : { "match" : "bol_*", "match_mapping_type" : "boolean", "mapping" : { "type" : "boolean" } } }, { "table" : { "match" : "tab_*", "mapping" : { "type" : "nested" } } }, { "rawtable" : { "match" : "rtb_*", "mapping" : { "fields" : { "raw" : { "type" : "keyword" } }, "type" : "text" } } }, { "locationpath" : { "match" : "locationpath", "match_mapping_type" : "string", "match_pattern" : "regex", "mapping" : { "analyzer" : "paths", "type" : "string" } } }, { "typepath" : { "match" : "typepath", "match_mapping_type" : "string", "match_pattern" : "regex", "mapping" : { "analyzer" : "paths", "type" : "string" } } }, { "contentidx" : { "match" : "contentidx", "match_mapping_type" : "string", "mapping" : { "term_vector" : "no", "type" : "text" } } }, { "contentfile" : { "match" : "contentfile", "match_mapping_type" : "string", "mapping" : { "term_vector" : "no", "type" : "text" } } } ], "properties" : { "contentfile" : { "type" : "text" }, "contentidx" : { "type" : "text" }, "dte_date" : { "type" : "date", "format" : "date_optional_time" }, "dte_system:creationdate" : { "type" : "date", "format" : "date_optional_time" }, "dte_system:lastmodificationdate" : { "type" : "date", "format" : "date_optional_time" }, "num_appbillion:index" : { "type" : "long" }, "num_system:contentstreamlength" : { "type" : "long" }, "num_system:versionnumber" : { "type" : "long" }, "str_appbillion:bmstring1" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_appbillion:bmstring2" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_name" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:basetypeid" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:contentid" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:contentstreamfilename" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:contentstreamid" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:contentstreammimetype" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:contentstreammimetypegroup" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:contentstreamrepositoryid" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:createdby" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:digest" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:lastmodifiedby" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:objecttype" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:objecttypeid" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:secondaryobjecttypeids" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:tenant" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } }, "str_system:traceid" : { "type" : "text", "fields" : { "raw" : { "type" : "keyword" } } } } } '
Optionally, you can also base the new index' settings on the original configuration:
CURL command settingscurl -X PUT "localhost:9200/yuuvis_2/_settings?pretty" -H 'Content-Type: application/json' -d' { "index": { "codec": "best_compression", "number_of_shards": "80", "max_result_window": "2147483647", "analysis": { "filter": [], "analyzer": { "default_search": { "useExactTerms": "false", "prefix_length": "0", "languages": ["de","en"], "type": "intrafind_search", "excessiveSplitting": "false", "stopwords": ["",""] }, "default": { "useExactTerms": "false", "prefix_length": "0", "languages": ["de","en"], "type": "intrafind_index", "excessiveSplitting": "false", "stopwords": ["",""] }, "paths": { "prefix_length": "0", "tokenizer": "path_hierarchy" } }, "number_of_replicas": "1" } } } '
-
- Migrating the Data to the new Index
-
Once a compatible index has been created, the reindex operation can be triggered through the Elasticsearch API.
CURL command & more information
The reindex operation itself provides a few options for configuration. For large data volumes especially, we employ parameters that increase stability and performance of the operation, such as the slices parameter for automatic parallelization of the reindex.
CURL command reindex operationcurl -X POST "localhost:9200/_reindex?pretty&slices=20&wait_for_completion=false&refresh" -H 'Content-Type: application/json' -d' { "source": { "index": "yuuvis_1" }, "dest": { "index": "yuuvis_2" }, "conflicts": "proceed" } '
After the reindex is completed, the new index must be activated by reassigning the
yuuvis
alias.CURL command & more information
The new index needs to inherit the yuuvis alias from the original index, meaning that the yuuvis alias must be deleted from the original index beforehand.
CURL command reindex operationcurl -X DELETE "localhost:9200/yuuvis_1/_alias/yuuvis?pretty" curl -X POST "localhost:9200/_aliases?pretty" -H 'Content-Type: application/json' -d' { "actions": [ { "add": { "index": "yuuvis_2", "alias": "yuuvis" } } ] } '
- Deleting the Original Index
-
To free up space in the Elasticsearch cluster, it is sensible to remove the original index after verifying the yuuvis® Momentum system has accepted the new index.
CURL command & more information
Make sure that the yuuvis® Momentum system still functions properly and contains all expected data before proceeding with the deletion of the original index.
CURL commandcurl -X DELETE "localhost:9200/yuuvis_1"
Notes on IntraFind Linguistics Plug-in
The plug-in offers semantic and linguistic text analysis features as well as powerful query operators.
Supported Languages
With the standard installation of yuuvis® Momentum, the plug-in supports a selection of languages as shown in the table below. ONE of them at time can be used with the standard license. Per default, German is activated. An alternative language can be activated instead of German. To activate more than one language, a license extension is required.
Per default, the core system is configured to support German and English language-specific analysis. Alternative languages to be used instead can be configured in the application-es.yml
configuration file. If you want to apply configuration changes to a system already in operation, please note the general remarks above.
Language | ISO 639-1 | Supported in default analyzer configuration | Intrafind license in standard installations | |
---|---|---|---|---|
Activated in standard license |
Configurable alternative languages |
|||
English |
|
+ |
- |
+ |
French |
|
- |
- |
+ |
German |
|
+ |
+ |
+ |
Italian |
|
- |
- |
+ |
Spanish |
|
- |
- |
+ |
A variety of further languages can be supported by the plug-in. Please contact IntraFind to get detailed information. You need to obtain a corresponding license on your own responsibility.
Language-specific Examples
Japanese
- Standard Analysis
-
If the Elasticsearch standard analyzer is configured to support language-specific full-text analysis for Japanese, Tokenization and Keyword Analysis are supported.
E.g., "春夏秋冬" will be analyzed as [春, 夏, 秋, 冬], and then can be searched by 春 or 夏 or 秋 or 冬.
Most punctuation marks are removed. Upper case is changed into lower case. For "夏見、おはよう", e.g., 夏見 will be recognized as a searchable keyword.
- With Japanese IntraFind Linguistics Plug-in License
-
If a license enabling the plug-in’s functionality for Japanese is additionally activated, Japanese words can be extracted from phrases but not all.
E.g., for "寿司がおいしいね", 寿司 will be recognized as a searchable keyword.
2.13.3. Identity Provider
Identity providers such as Keycloak can be connected to yuuvis® API for authentication using Connect/OAuth2 via the authentication-service.
Keycloak is the recommended identity provider for yuuvis® Momentum and is consistently used for testing. In principle, any identity provider supporting OAuth2 can be used in the same way.
Keycloak
As standard, the installation is done by means of a Helm chart. Two demonstration tenants are created and configured automatically. Further tenants for productive use have to be added and configured manually.
The manual installation and configuration of Keycloak for yuuvis® Momentum API are broadly described here.
After installation, Keycloak provides two administrative services, one for system administrators and one for users.
-
In order to create and administrate realms and user accounts, Keycloak provides the Admin Console. Roles can be defined and assigned in the Admin Console as well. An administrator login is required.
-
Any user has access to the User Account Service provided by Keycloak. Users can change their credentials and other personal data.
Keycloak Installation
To install Keycloak manually, follow these steps:
-
Download a supported Keycloak version version and extract it to a local directory.
-
Modify the
standalone.xml
configuration file in the\standalone\configuration\
directory:-
Add the following entry to the <interfaces> section:
<interface name="any"> <any-address/> </interface>
-
In the
<socket-binding-group>
section, for the<default-interface>
attribute, enter the following value:any
-
If port 8080 is not available, change the port via the following line in the
<socket-binding-group>
section:<socket-binding name="http" port="${jboss.http.port:8080}"/>
-
-
Start Keycloak via the
\keycloak\bin\standalone.bat
file.The file must be run as an administrator. -
Call the Keycloak Admin Console:
http://localhost:8080/
-
Start by creating an administrator account.
For productive use, it is recommended to connect Keycloak to a different relational database management system (RDBMS) instead of the embedded standard H2. Suggestions for compatible RDBMS are provided by Keycloak. |
Keycloak: Tenant and User
You require a tenant and a user.
Users in Keycloak must also be entered in the yuuvis® Momentum user administration. |
To create tenants and users, follow these steps:
-
Call the Keycloak Admin Console:
http://localhost:8080/auth/admin
-
Create a new tenant in the navigation area via Master > Add realm.
-
Create and save a user for the tenant via Users > Add user.
-
Enter a password in the Credentials tab on the user page, set the Temporary option to Off, and save with Set Password.
Keycloak: Connecting to yuuvis® API
To establish a connection, create a client following these steps:
-
Call the Keycloak Admin Console:
http://localhost:8080/auth/admin
-
Select the tenant and create the new client via Clients > Create.
-
Enter a name in the Client ID field, and enter and save the yuuvis®
authentication
service URL in the Root URL field. -
Configure the following in the Settings tab of the client page:
-
Access Type > confidential
-
Authorization Enabled > ON
-
Valid Redirect URIs > Schema:
http://<authentication-service>/*
All yuuvis® API hosts must be specified according to this schema.
-
-
Save the configuration by clicking Save.
-
Set the required user roles for the yuuvis® API components as simple strings via Roles > Add Roles.
Afterwards, the roles can be activated for the users via Role Mappings > Assigned Roles.
In case of a yuuvis® Momentum system with multiple tenants, the authentication
service has to be registered as a Keycloak client in each corresponding realm.
Connecting yuuvis® authentication-service to SSL-secured Keycloak
-
Export certificate with Firefox:
-
Call the encrypted welcome page of Keycloak in Firefox:
https://localhost:8443/auth/
-
Open the Protection Settings via the shield icon to the left of the address bar.
-
Display the certificate via Security > View Certificates.
-
Export the certificate as
localhost.pem
via the tab Authorities in the certificate manager.
-
-
Alternatively, export certificate with Chrome:
-
Call the encrypted welcome page of Keycloak in Chrome:
https://localhost:8443/auth/
-
Open the Settings via the three dots icon to the right of the address bar.
-
Display the certificate via Privacy and security > Security > Manage certificates.
-
Export the certificate in Base-64 format as
localhost.pem
.
-
-
Import the certificate in the Java Trust Store with the following batch call:
...\service-manager\jdk\bin\keytool ^ -import ^ -trustcacerts ^ -keystore ...\service-manager\jdk\jre\lib\security\cacerts ^ -storepass changeit ^ -noprompt ^ -alias localhost ^ -file ...\path\to\localhost.pem
-
Restart the yuuvis®
authentication
service.
Embedding the Login Page into an iframe
The Keycloak login page can be embedded as an iframe into a second web page if this web page is published on the same host as Keycloak. If the secondary web page is published on a different host, it has to be legitimized in every Keycloak tenant that will use this web page for the login process:
-
Call the Keycloak Admin Console:
http://localhost:8080/auth/admin/
-
Select the tenant and add the host name of the web page via Realm Settings > Security Defenses > Content-Security-Policy > frame-ancestors.
Multiple host names are separated by blank spaces.
Impersonation
In order to allow users with a specific role to log in as any other user, impersonation can be activated in Keycloak. Thus, users with this specific role can use their own password to log in to the account of any other user within their tenant. In Keycloak, the feature is realized via impersonation by means of token exchange.
-
Activating Token Exchange:
-
Open the
StatefulSet
of Keycloak in your Kubernetes cluster for editing by running the command:kubectl -n infrastructure edit statefulset keycloak
-
Extend the containers section as follows:
containers: - args: - -Dkeycloak.profile.feature.token_exchange=enabled - -Dkeycloak.profile.feature.admin_fine_grained_authz=enabled
-
Restart Keycloak.
-
-
Configuring the User Account and Keycloak Clients:
-
Call the Keycloak Admin Console:
http://localhost:8080/auth/admin
-
Select the user you want to grant access to other user accounts and switch to the Role Mappings tab.
-
Display the Client Roles for the realm-management client and assign its impersonation role to the user.
-
In the same realm, select the client admin-cli and switch to the Permissions tab.
-
Flip the Permissions Enabled switch to ON.
-
In the appearing table, click token-exchange in the scope-name column.
-
From the Create Policy selection list in the Apply Policy section, select Role.
-
Name it impersonation-policy.
-
From the Realm Roles selection list, select the administrative role that will enable users to impersonate other users within their tenant. Tick the Required checkbox.
-
From the Clients selection list, select realm-management.
-
From the Client Roles selection list, select impersonation. Tick the Required checkbox.
-
Save the configuration for the policy.
-
Save the configuration for the permission settings.
-
-
Testing Impersonation with cURL.
The following commands use an administrative user root with the password
changeme
belonging to the tenanttenant1
with the impersonation authorization as configured before. This user requests access to the account of the user specified by the IDcc14e5d4-e8da-4108-92ad-c87066aed4c3
.-
Request a token for the administrative user with the impersonation authorization:
curl -k ^ -d "client_id=admin-cli" ^ -d "username=root" ^ -d "password=changeme" ^ -d "grant_type=password" ^ "http://localhost:8080/auth/realms/tenant1/protocol/openid-connect/token"
-
Request a token for the account of the target user where the login is needed. The previously retrieved token of the administrative user is referenced as subject_token whereas the ID of the target user is specified as requested_subject.
curl -k ^ -H "Content-Type: application/x-www-form-urlencoded" ^ -d "client_id=admin-cli" ^ -d "requested_subject=cc14e5d4-e8da-4108-92ad-c87066aed4c3" ^ -d "subject_token=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJueEZ..." ^ --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" ^ "http://localhost:8080/auth/realms/tenant1/protocol/openid-connect/token"
-
The retrieved token can be used by the administrative user root for authentication in yuuvis® Momentum with the account of the target user.
-
The following command retrieves user-specific information on the user who will be logged in with the token specified in the authorization header. Check whether the token retrieved before identifies the desired target user. Thus, in this example, the command should retrieve a data set for the user with ID cc14e5d4-e8da-4108-92ad-c87066aed4c3.
curl -k ^ --request GET ^ --url "http://localhost:8080/auth/realms/tenant1/protocol/openid-connect/userinfo" ^ --header "accept: application/json" ^ --header "authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAi1dXVSZ3daQldhTTJZaXNlZElFXzg..."
Suppressing Duplicate Information on Roles
Per default, the access token generated by Keycloak contains the roles of the currently logged-in user. The authentication
service creates an internal JSON Web Token (JWT) that includes the unchanged Keycloak access token. However, in order to allow a separate role management, the authentication
service requests the roles of the corresponding in a separate request and adds them to the internal JWT in addition to the Keycloak access token. The roles stored in the original Keycloak access token are a duplicate of the information and are always ignored. In order to reduce the size of the JWT, their inclusion in the Keycloak access token can be suppressed by applying the configuration adjustment described below. Thus, for any request to the yuuvis® Momentum API, the request header size is reduced.
-
Call the Keycloak Admin Console:
http://localhost:8080/auth/admin/
with administrator login. -
Select the realm for which the configuration is to be changed.
-
Open the Client Scopes.
-
Open the roles scope.
-
In the Mappers tab, delete the entries realm roles and client.
These configuration steps have to be applied to each realm in each Keycloak instance in which to suppress the inclusion of role information in the Keycloak access token.
Session Management
For each user session, HTTP client and browser set session cookies as described here.
Additionally, the following cookies are set by Keycloak. For more information, please refer to the official Keycloak documentation.
-
AUTH_SESSION_ID_LEGACY
-
AUTH_SESSION_ID
-
KEYCLOAK_IDENTITY_LEGACY
-
KEYCLOAK_IDENTITY
-
KEYCLOAK_PROXY_SESSION_ID
-
KEYCLOAK_SESSION_LEGACY
-
KEYCLOAK_SESSION
2.13.4. Internal Caches
Redis
The core system internally uses Redis to cache processing-related information. If you want to store your own keys in Redis for custom processes, your keys must not match one of the following pre-defined internal keys.
Key name | Comment |
---|---|
|
Locks DMS objects during the processing of update requests. |
|
|
|
During the processing of a folder object deletion, no parallel process can create a new |
|
Ensures that parallel operations do not create circles in the folder hierarchy. |
|
|
|
|
|
|
|
Shares session information for all instances of the |
|
Contains the used storage per tenant in Bytes used for the storage metric. |
|
Contains the upload information for the upload of binary content files in multiple pieces for each tenant. |
|
|
|
Locks DMS objects referring to the same content during a content move request. |
|
Control the visibility of tags via tagging endpoints in combination with |
|
|
|
2.14. Testing
2.14.1. Testing with Postman
Postman is a free API development tool with a multitude of useful functions for automated testing, documentation, and more. Our yuuvis® Postman Collections kick-start you right into the yuuvis® API world.
You need a running and accessible yuuvis® Momentum core installation.
2.15. Maintenance via CLI
The commander
service for yuuvis® allows you as a DevOp to perform low-level maintenance on your core system. You can adjust the differences between the DBMS, Elasticsearch, and your repository. You can access the database and carry out Elasticsearch queries to ,e.g., rebuild the full-text index from the database. The commander
service itself does not support a REST interface of its own, but a connection via Secure Shell (SSH) instead. Thus, the commander
service provides a SSH server at runtime. If you are connected to an SSH client, you can execute predefined commands with self-imposed parameters.
2.15.1. Set Up 'commander' Service
To use the commander
service, an SSH connection is required. The recommended parameters for the configuration of the SSH connection are given in this section.
Port Redirection
The commander
Service starts the SSH server per default on port 8022. If there are pods in the Kubernetes final destination platform, a forwarding has to be started for port 8022.
localhost@root:~$ kubectl port-forward -n sanity commander-0000000000-00000 8022
Connecting to SSH Client
Since the connection has to persist during long-term operations without user interactions, keepalives should be enabled. Furthermore, the commander
output might contain important information and thus should be stored in a file.
Setup under Windows
Under a Windows operating system, the usage of PuTTY is recommended. The screenshot below shows the recommended PuTTY configuration enabling the keepalives on the top, and activating the output in a file below.
Setup under Linux
The standard SSH client can be used. The keepalive function can be activated with the option "ServerAliveInterval 20"
. The output in a file can be achieved by forwarding to the tee
command.
localhost@root:~$ ssh -o "ServerAliveInterval 20" -l root -p 8022 127.0.0.1 2>&1 | tee commander-output.log
2.15.2. Commands
The command help
lists all available commands that are supported by the commander
service.
Information on parameters of individual commands can be displayed via help <command>
.
Maintenance Commands
Check the data stock for consistency or execute global tasks that affect the entire system via commander
functions called with the following commands.
maintain-compare
- Compare the objects stored in the database and Elasticsearch index.
Unforeseen circumstances might occur in any system and might lead to differences between database and Elasticsearch index. For example, a deleted object was correctly removed from the database, but for whatever reason not from the Elasticsearch index. As of yuuvis® Momentum version 2020 Winter, it is possible to check the consistency of the stored objects by means of the maintain-compare
command provided by the commander
service.
While the command runs continuously, the comparison of DMS objects is performed step by step. The objects are grouped by the date of their last modification/creation. For each day between the start date and the end date, the corresponding objects are processed. Then again, each day is split in a variable number of time periods, such that the amount of objects to be compared in each period is approximately equal to the number of fetch-size.
All results are summarized in a file called job-result.json
. In this (ND)JSON structured file, each day is listed separately and contains some general comparison results.
1
2
{"1970-01-01" : {"total":{"missingDb":10,"missingEs":5,"differences":2,"dbHits":20,"esHits":20},"end":"1970-01-02T00:00:00.000Z","start":"1970-01-01T00:00:00.000Z","daily":{"comparison":{"propertyDifferences":2,"missingInDb":10,"missingInEs":5},"splits":1,"esHits":20,"dbHits":20}}}
{"1970-01-02" : {"total":{"missingDb":15,"missingEs":10,"differences":4,"dbHits":40,"esHits":40},"end":"1970-01-03T00:00:00.000Z","start":"1970-01-02T00:00:00.000Z","daily":{"comparison":{"propertyDifferences":2,"missingInDb":5,"missingInEs":5},"splits":1,"esHits":20,"dbHits":20}}}
For every day with differences, there is an additional folder, containing some more detailed information about this day’s differences.
{
"timeRangeSummary": {
"start": "1970-01-01T00:00:00.000Z",
"end": "1970-01-02T00:00:00.000Z",
"comparison": {
"missingInDb": [
"00000000-0000-0000-0000-0000000000000",
"00000000-0000-0000-0000-0000000000001",
"00000000-0000-0000-0000-0000000000002",
"00000000-0000-0000-0000-0000000000003",
"00000000-0000-0000-0000-0000000000004",
"00000000-0000-0000-0000-0000000000005",
"00000000-0000-0000-0000-0000000000006",
"00000000-0000-0000-0000-0000000000007",
"00000000-0000-0000-0000-0000000000008",
"00000000-0000-0000-0000-0000000000009",
"00000000-0000-0000-0000-0000000000010"
],
"missingInEs": [
"00000000-0000-0000-0000-0000000000011",
"00000000-0000-0000-0000-0000000000012",
"00000000-0000-0000-0000-0000000000013",
"00000000-0000-0000-0000-0000000000014",
"00000000-0000-0000-0000-0000000000015",
"00000000-0000-0000-0000-0000000000016"
],
"differences": [
"00000000-0000-0000-0000-0000000000017",
"00000000-0000-0000-0000-0000000000018"
]
}
}
}
After all time periods of a day are processed, the procedure is repeated for the next day until the current date (or the specified end date) is reached. Depending on the number of objects for the tenant, this process can take a long time. While running the task, the process progress is continuously displayed on the command line including an estimated completion time.
After the command finishes, the directory containing all result files is shown.
The following parameters can be given to the maintain-compare
command:
Parameter | Description | Required | Default |
---|---|---|---|
|
Specifes the target tenant. If not specified, the command is executed for all tenants. Example
|
yes |
- |
|
Target directory for result log. Example
|
no |
|
|
Specifies the start date for the comparison in If not specified, the earliest Example
|
no |
|
|
Specifies the end date for the comparison in If not specified, the current date is used as end date. Example
|
no |
|
|
Fetch size, used to split days in time periods. Each period contains approximately as many elements as specified by fetch-size. The value must be at least 1000 and not bigger than 50,000. Example
|
no |
10000 |
|
If the parameter is set, the system:creationDate is used instead of the Example
|
no |
|
|
Specifies the mode of the comparison determining which object properties are included in the comparison. The available modes are listed and described in the table below. Example
|
no |
|
The following modes can be selected for the maintain-compare
command:
Mode | Description |
---|---|
|
The command determines and compares the number of objects modified (or created) on every single day in the specified time range. |
|
The command determines and compares only the system:objectId of all objects that are included in the comparison. |
|
The command determines and compares the following properties of all objects that are included in the comparison:
|
|
The command determines and compares the properties listed for the
|
maintain-delete
- Delete all objects of a specific tenant that are flagged for deletion.
This command may be useful, e.g., if objects have been requested to be deleted, and flagged for deletion, but the deletion itself did not take place due to unforeseen circumstances. Such states can be recognized by the maintain-compare
command. Using the maintain-delete
command will then help to clean up inconsistent object states.
The command runs continuously for a specified amount of time, determines the objects that were flagged for deletion in the Elasticsearch index and deletes them, including all references to the yuuvis® Momentum system that may still exist. Thus, it is ensured all flagged objects are deleted from the Elasticsearch index, and, if necessary, from the database and the repository. In addition, all old versions are deleted too. If no further object is found, the command will stop even if the maximum run time is not yet reached.
The following parameters can be given to the maintain-delete
command:
Parameter | Argument Type | Description | Required | Default |
---|---|---|---|---|
|
string |
Tenant for which flagged objects are to be searched and deleted. Example
|
yes |
- |
|
string |
Target directory for result log. Example
|
no |
- |
|
int |
Fetch size for Elasticsearch requests. Maximum number of objects included in each Elasticsearch request. The value must be at least 1 and not bigger than 10000. Example
|
no |
1000 |
|
int |
The maximum amount of seconds this command is allowed to run before stopping. The value must be at least 1 and not bigger than 86400. Example
|
no |
5 |
|
boolean |
Setting this flag will prevent using a random seed to search for flagged objects. Example
|
no |
|
In the following example, all objects that are flagged for deletion will be deleted. The job will continuously search for the next 100 (see: --fetch-size
) flagged objects and process them, until the maximum running time of 1 hour (see: --running-time
) is reached or no further objects are flagged for deletion.
Lt. Commander>maintain-delete --tenant default --running-time 3600 --fetch-size 100
Running delete job for tenant 'default' for 3600s
Any unexpected results will be continuously displayed while the process is running.
maintain-export
- Export all objects of a specific tenant. For every object a folder is created, containing the object’s metadata in JSON format and its content file if available.
This command may be useful, e.g., if a customer’s contract corresponding to a specific tenant ends. All data stored for this tenant can be exported for further usage in other systems. The export includes the metadata of all objects and the corresponding binary content files. Every object is exported separately. Therefore, a folder structure is created using the tenant name as root level. Each object is created as a folder named according to its system:objectId
, which contains a metadata.json
file and the binary content file if available. To prevent performance issues when browsing those exported items with file explorers, it is possible to specify the maximum number of items within a folder. Considering this limitation, a nesting strategy is used to add more hierarchical (physical) folder levels and reduce the number of elements per folder.
While running the task, the process progress is continuously displayed including an estimated completion time.
Parameter | Argument Type | Description | Required | Default |
---|---|---|---|---|
|
string |
Tenant for which all objects are to be exported. Example
|
yes |
- |
|
int |
Fetch size for database requests. Maximum number of objects included in each database request. The value must be at least 1 and not bigger than 100000. Example
|
no |
1000 |
|
int |
Maximum number of items per folder to prevent performance issues when browsing folders. The value must be at least 1 and not bigger than 10000. Example
|
no |
5000 |
|
string |
Target directory for exported items. Example
|
no |
|
|
string |
Start date. Every item that was created since this date will be exported (e.g., Example
|
no |
|
|
string |
End date. Every item that was created until this date will be exported (e.g. Example
|
no |
|
In the following example, all objects that were stored since 2021-09-01
by any user of tenant default
will be exported. Additionally, only 50 items should be stored in each folder, so a nesting strategy is used.
Lt. Commander>maintain-export --tenant default --start-date 2021-09-01 --folder-size 50
Running export job for tenant 'default' from '2021-09-01T00:00:00.000+02:00' to '2021-09-29T00:00:00.000+02:00'
The result is in a folder structure, similar to the example structure below. Each folder contains the metadata.json
and the binary data (if available).
\---default
+---0
| +---004f0124-51cb-4293-8db8-5f7fa31d3a9c
| +---01b7e555-aa1f-43e4-a27d-901463f26dc3
| +---0482f25b-4946-4b50-8663-993ecfb80b55
| +---04b4ef67-b72d-44c5-bdae-928c21839f1c
| +---051521da-eb3e-479a-89a0-be9c8e26569c
| +---05a70b84-8ce7-4c2e-ac32-af480bd120ce
| +---082d3913-83ca-4d2b-b8ae-53f3086ad6c1
| \---0d98f3b2-718a-4808-b185-c1e4e28ce732
+---1
| +---16a06147-ca6e-4c52-8ce9-8fef91a7f3ec
| \---17cb45fa-d8b8-4df1-b761-87711e615005
+---2
| +---2665cd04-dbb1-4221-8877-53df9ae4d37f
| +---29a6af2f-7265-43c3-94fa-e249a028768f
| +---2ed11958-88ea-4800-82d9-3529a12e31de
| \---2f1d183e-9e93-487b-9a74-98ecd2331b75
+---3
| +---3267cacc-6408-4a3f-909e-3796e43f1b84
| +---3759d0b9-0f8f-4cf8-8bc2-394d7e381e3c
| +---394be944-6237-4090-a4ea-2fc9d48ddde8
| +---3a19a763-9e1a-4264-9e71-c8ae02bad8e7
| +---3dd159bf-90dd-472a-aa84-dcaf6c828e83
| \---3f55c478-a084-4bc1-aa6a-63327b5cebb6
+---4
| +---408bcfeb-48e9-4350-bae5-9378443aef34
| +---4348a318-abea-4d84-a416-f82f8380ef15
| +---43eb7e68-16f1-4a7e-a77b-fdcf7c846315
| +---447b11b5-dd87-4582-9a47-32fce361da88
| \---4a7dcced-2ed8-4041-bf6d-fd5b5c96e959
+---5
| +---546db2d9-8401-45ff-ab10-b002ac440c0e
| +---5d27a0f8-35d0-4cdd-ac30-cbe1e744d924
| \---5d7de05f-e1f9-4639-824e-2ad41d64fe19
+---6
| +---6398f660-443e-4363-a531-9d12c8d62b88
| +---6ddd4241-9d2d-4a0a-b20d-a49190224d24
| \---6fcc6ef6-511a-4f9a-be16-a8b9d9e951fc
+---7
| +---751abfa2-0788-434d-9513-055f6b538a40
| +---76a1d7fa-f481-4adf-840d-27b680a2e513
| \---795a223a-ca0c-4a63-8dc1-cc8967d1379c
+---8
| +---80db8f0e-b4f5-48d0-af83-e589576a0631
| +---834f086a-b0b5-47b6-9727-548ccb876bdf
| +---8c8bf981-24b6-4ab8-ae53-92bdb2fce1cd
| +---8e3428a7-f63a-4576-a6f0-d4c9c3cb4d46
| \---8e414e7c-3ad6-4132-a1ff-018107d8f01e
+---9
| +---900e049d-5927-40cf-80df-5b3fbdf6672e
| +---90b707e2-ddd6-451c-bbae-88c977686ec1
| +---919244e8-9568-4cea-a6f6-113dba63e21f
| \---9a09011a-9ca4-4b2d-8f8b-ffa6c128cc35
+---a
| +---a18f5ad3-a9a7-40c2-9918-8d3504483266
| +---a23b5f63-0297-4772-a6d8-c808c4b61ba0
| +---a294c53d-9fa8-442e-b189-754d047dded3
| +---a7fe24db-3163-44ff-9382-af3404b607b1
| +---a9139650-57ef-4205-9147-a683057d975c
| +---a9ae7464-cf17-42fc-8200-d35eaf205289
| \---af80e537-5ceb-4676-b13d-956710752dbf
+---b
| +---b842d551-3a01-4d83-abcf-67f213363bc2
| +---bc5f482e-897b-4264-8c58-9132747f1051
| \---bf8a677b-3687-41fc-8078-b973879a7315
+---c
| +---c25d0fee-ae75-439c-90b4-49b8793ddf36
| +---c506c75d-dc4f-4743-818b-7cac35d79b95
| \---c9b85135-0030-426c-9146-2039eb0f27ee
+---d
| +---d0424628-bb70-4714-a44f-e02e51184ff6
| +---d283787b-795d-4e72-bca9-95752d9f10b7
| +---d4292dd4-5689-4cf5-99a6-174f97f4c41b
| \---d918e6d5-1a34-49b1-8134-3d890d45d364
+---e
| +---e1f0c851-aaa9-496e-b2d9-30607453215e
| +---edafcd97-1f51-466f-80f8-385f95f501d3
| \---ee2d8719-881a-4187-b604-c5cb9c2ca991
\---f
+---f0a77bdb-fc26-4d0d-8212-9c265e1e50a8
+---f54553de-e334-47c1-997d-76f2999982e1
+---f992a805-e6c4-4239-b2d5-7f91ea018c60
+---fc627ddd-82d4-43e7-891b-1f9bcb0cceb7
+---ff200544-b4c7-4a75-904d-63c8cee55f9d
+---ff252500-59ed-4f61-94f0-adf577958b5f
\---ff2e54a7-e235-4a65-a548-64b8772626d1
maintain-repository
- Find content files in the S3 store that are not referenced any longer by an object in the database.
Find content files in the S3 store that are not referenced any longer by an object in the database.
yuuvis® Momentum stores content files separately from their metadata. The content files are indicated by a contentStreamId
and can be stored in an S3 store. Each corresponding object with its metadata is stored in a database and contains a reference on the contentStreamId
of its content file. If the object is deleted, the metadata are read from the database and deleted. The content file is searched afterwards by the contentStreamId
that was read from the database before, and deleted. If an error occurs during this process, the object might be removed from the database but not the corresponding content file. Thus, over time, several content files might remain in the S3 store that are not referenced by an existing object. As of yuuvis® Momentum version 2020 Winter, it is possible to find those content files in the S3 store by means of the maintain-repository
command provided by the commander
service.
The command determines all content files in a specified S3 store and checks in the database whether they are referenced by an existing object or an old version of an object. Content files without any reference in the database are listed via contentStreamId and returned in a JSON structure.
These parameters can be given to the maintain-repository
command:
Parameter | Description |
---|---|
|
Specifies the ID of the repository that to be searched. If the specified repository is not an S3 store, an error is returned. Example
|
maintain-tenant-data-delete
- Deletes all data belonging to a tenant of the core system, including all objects in the repository, database, Elasticsearch, audit entries and config files.
This command may be useful if all data of a tenant should be deleted. Before using this command, you should ensure that the tenant is already disabled for user login, to prevent any unexpected data manipulations while the deletion process is running. Please note that this operation cannot be undone and that there is no automatic data backup. Even objects under retention will be deleted. However, if binary content files are protected by an archive-internal retention, they cannot be deleted via this command.
While the command runs continuously, the deletion of DMS objects is performed step by step. Each day between the object creation date and the current date is separately processed. Then again, each day is split in a variable number of time periods, such that the amount of objects to be deleted in each period is approximately equal to the number of fetch-size
. For each period, the command follows this procedure:
-
Process all current object versions:
-
Delete each repository item, i.e., binary content files. (individual requests)
-
Delete the objects in the Elasticsearch index. (batch request)
-
Delete all database rows. (batch request)
-
-
Process all old versions of DMS objects:
-
Delete each repository item, i.e., binary content files. (individual requests)
-
Delete all database rows. (batch request)
-
If one of the deletion sub-processes (in repository, search index or database) fails for a DMS object, the problem is logged and the deletion continues with the other sub-processes nevertheless.
After all time periods of a day are finished, all audit entries of this day are deleted. Then, the procedure is repeated for the next day until the current date has been processed. Depending on the number of objects for the tenant, this process can take a long time. While running the task, the process progress is continuously displayed including an estimated completion time.
After processing all days, as a last step, the tenant’s configuration is deleted.
The following parameters can be given to the maintain-tenant-data-delete
command:
Parameter | Argument Type | Description | Required | Default |
---|---|---|---|---|
|
string |
Tenant for which all data should be deleted. Example
|
yes |
- |
|
string |
Target directory for result log. Example
|
no |
- |
|
int |
Fetch size, used to split days in time periods. Each period contains approximately as many elements as specified by The value must be at least 100 and not bigger than 10,000. Example
|
no |
1000 |
|
boolean |
Setting this flag will prevent the execution of the deletion. The process will be simulated in order to count all documents that would be deleted without this flag. Example
|
no |
|
|
boolean |
Setting this flag will skip the initial warning that all data will be deleted. Example
|
no |
false |
In the following example, all objects of the tenant default
will be deleted. Each day is split in time periods which contain approximately 500 objects.
Lt. Commander>maintain-tenant-data-delete --tenant default --fetch-size 500
Running tenant delete job for 'default'
Any unexpected results will be continuously displayed while the process is running.
Database Commands
Check the data stock for consistency or execute global tasks that affect the entire system via commander
functions called with the following commands.
dbs-reindex
- Restore the entire Elasticsearch index from the database via Commander service.
Changes in the object structure might lead to differences between the index of Elasticsearch and the database. As of yuuvis® Momentum version 2020 Winter, it is possible to reindex Elasticsearch according to the database by means of the dbs-reindex
command provided by the commander
service.
The reindexing can be limited by a start date and an end date, and by specifying a tenant. Before the reindexing, execute the dbs-configure
command to turn the simulation mode on/off.
These parameters can be given to the dbs-reindex
command:
Parameter | Description |
---|---|
|
Sets an end date. The argument is in format Example
|
|
Sets a start date. The argument is in format Example
|
|
Specifies the target tenant. If not specified, the command is executed for all tenants. Example for tenant 'default'
|
The following example code shows the commands together with the corresponding command line outputs for a non-simulation reindexing. The simulation mode is turned off (command dbs-configure
) in line 16. In line 19, the reindexing is executed for the default
tenant starting from 2020-01-01
and ending on 2022-01-01
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Lt. Commander>help dbs-configure
NAME
dbs-configure - configure timeouts
SYNOPSYS
dbs-configure [-s]
OPTIONS
-s or --simulation
turn simulation mode on/off
[Optional, default = false]
Lt. Commander>dbs-configure
Running dbs-configure setting values simulation('false')
SessionState(simulation=false, reindexing=false)
Lt. Commander>dbs-reindex -t default -s 2020-01-01 -e 2022-01-01
Running dbs-reindex for 'default' from '2020-01-01' to '2022-01-01'
dbs-configure
- Turn on/off the simulation mode for the reindexing command.
It is possible to reindex Elasticsearch according to the database by means of the dbs-reindex
command provided by the commander
service. Via the dbs-configure
command, the reindxing can be configured to be executed in a simulation mode that does not manipulate any data. In order to actually apply the reindexing to the data, the simulation mode has to be turned off with the dbs-configure
command.
These parameters can be given to the dbs-configure
command:
Parameter | Description |
---|---|
|
Turns the simulation mode on ( Example
|
The following example code shows the commands together with the corresponding command line outputs for a non-simulation reindexing. The simulation mode is turned off in line 16. In line 19, the reindexing is executed for the default
tenant starting from 2020-01-01
and ending on 2022-01-01
.
Audit Commands
Check the data stock for consistency or execute global tasks that affect the entire system via commander
functions called with the following commands.
audit-cleanup
- Remove entries from the audit trail by means of the commander
service.
It is possible to delete old audit trail entries by means of the audit-cleanup
command provided by the commander
service, together with the ./config/system/cleanupConfiguration.json
configuration file.
The audit
field in the JSON file contains details on the deletion of the audit trail entries using the following parameters:
Parameter | Description | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
An integer default value for the cleanupAfterDays parameter. It is valid for any action that is not listed in actions.
|
{
"audit": {
"defaultCleanupAfterDays": 10,
"actions": [
{
"comment": "OBJECT_CREATED",
"action": 100,
"cleanupAfterDays": -1
},
{
"comment": "DOCUMENT_ACCESSED",
"action": 400,
"cleanupAfterDays": 1
}
]
}
}
When the lifetime of the audit trail entries is exceeded, they are not automatically deleted. The deletion of entries takes place only as a result of the execution of the audit-cleanup
command in the commander
service AND if the specified lifetime is exceeded. When executed, the command reads the cleanupConfiguration.json
file. If the file does not exist, the defaultCleanupAfterDays
value is set to -1 and thus no entry will be deleted from the audit trail.
Finally, for the execution in the commander
, the following parameters can be given to the audit-cleanup
command:
Parameter | Description |
---|---|
|
Specifies the target tenant. If not specified, the command is executed for all tenants. Example for tenant 'default'
|
3. Practice Examples
The following example tutorials may help you to design your own solutions based on yuuvis Momentum core system. The example source code is available on gitHub.
3.1. Login to the Core API
To interact with the yuuvis® API, it is necessary to log in with a user account. The user accounts are managed by at least one external identity provider (such as Keycloak or the Active Directory Federation Service). It is possible to configure different identity providers for different tenants. Each user account belongs to exactly one tenant, which must be specified with each login.
Check out our graphical overview of the architecture which describes the basic use case flow for logging in to the core API.
3.1.1. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® API system (see Installation Guide)
-
A user with at least read permissions on a document type in the system (see tutorial for permissions)
-
Simple Maven project
-
Preconfigured yuuvis® API system with Keycloak as the identity provider
-
Keycloak contains a realm default
-
In the realm default, the Authentication service is registered as a client under the name enaio
-
The realm default contains a user clouduser with the password secret
-
3.1.2. Session Management
The login is done using request headers, which are passed during the first call of an API function. The calling HTTP client must have a Cookie Manager to enrich further requests with the session cookie (GWSESSIONID). This prevents the user from logging on again for each request. In the tutorial, the OkHttpClient by Square, Inc. is used to this. Therefore, the following block must be added to the Maven dependencies in the pom.xml of the project:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-urlconnection</artifactId>
<version>3.12.0</version>
</dependency>
To activate Cookie Management in the OkHttpClient, you can do the following:
CookieJar cookieJar = new JavaNetCookieJar(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
OkHttpClient client = new OkHttpClient.Builder().cookieJar(cookieJar).build();
3.1.3. Secure Data Transmission with SSL
To use encrypted (HTTPS) endpoints with an OkHttpClient, it must be configured for the SSL encryption protocol. For this, it must also be capable of certificate treatment according to the X-509 standard. For this, the OkHttpClient receives a hostnameVerifier and a sslSocketFactory at initialization to check incoming certificates with the TLS handshake. In our example, we just keep building our X509TrustManager for the sslSocketFactory for demonstration purposes, so that certificates are almost always accepted. The following code creates an OkHttpClient that is both session- and SSL-enabled.
private OkHttpClient client = null;
// necessary to obtain access tokens via SSL
X509TrustManager trustManager = new X509TrustManager()
{
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {}
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {}
public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
};
CookieJar cookieJar = new JavaNetCookieJar(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{this.trustManager}, new SecureRandom());
// create HTTP Client
this.client = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.hostnameVerifier((s, sslSession) -> true)
.sslSocketFactory(sslContext.getSocketFactory(), this.trustManager)
.build();
3.1.4. Required System Data
To log in to the Core API, a client needs some information about the system. Of course, they first need valid credentials (username / password) of a user existing in the system. In addition, the Keycloak login client must be able to identify itself as an approved application, so it must know a registered clientId with an associated clientSecret. In addition, both pairs of credentials are only valid for a certain tenant whose name must also be known to the client for the requests. Finally, the client must also know the one accessible base URL of the Core API and the associated Keycloak identity provider.
private String userName = "clouduser";
private String userPwd = "secret";
private String userTenant = "default";
private String clientId = "clouduser";
private String clientSecret = "cd7e6ce4-781b-40db-af5f-e4106926e96c"; //client secret, obtainable through keycloak credentials tab of client matching client id and tenant
private String yuuvisBaseUrl= "http://10.10.6.242"; //Base URL of yuuvisclient
private String keycloakBaseUrl = "https://10.10.6.252:8443"; //Base URL of keycloak identity provider
Generating a Secret
To log in with an oAuth2 access token, the client must authenticate itself to Keycloak with its client secret. This secret is static and can be taken from the Keycloak interface. To do this, log on to the Keycloak interface with a technical user, select the tenant applicable to the client, select the correct client under "Clients" (here "Enaio") and take out the secret of the client under the "Credentials" tab.
3.1.5. Login Procedures
Login with Username and Password
The username, password, and associated tenant are passed as HTTP headers. The username and password must be encoded with Base64 in the same way as for classic Basic authentication. The headers are then sent to any Core API endpoint.
byte[] credentials = "clouduser:secret".getBytes(StandardCharsets.UTF_8);
String authorization = "Basic " + Base64.getEncoder().encodeToString(credentials);
Headers headers = new Headers.Builder()
.add("Authorization", authorization)
.add("X-ID-TENANT-NAME", "default")
.build();
Login with an OAuth 2.0 Access Token
For this login procedure, the application must have received an access token from the identity provider from a third-party application (for example, a proxy). The access token and the associated tenant are passed as HTTP headers for login.
Keycloak can request an access token with the Password Credentials Grant Flow. The request must contain the user name, the user password, the client ID and the secret as parameters. Keycloak’s response contains a JSON object from which the access token and token type must be extracted. In the example, JsonPath is used for this.
String payload = "client_id=enaio&" +
"client_secret=4c5254363c1d&" +
"username=clouduser&" +
"password=secret&" +
"grant_type=password";
//retrieve access token from identity provider (Keycloak)
Request.Builder request = new Request.Builder()
.url(keycloakBaseUrl+"/auth/realms/default/protocol/openid-connect/token")
.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded"), payload))
.build();
String responseJson = this.client.newCall(request).execute().body().string();
DocumentContext context = JsonPath.parse(responseJson);
String tokenType = context.read("token_type");
String accessToken = context.read("access_token");
Finally, the logon headers are created and sent to any Core API endpoint.
Headers headers = new Headers.Builder()
.add("Authorization", tokenType + " " + accessToken)
.add("X-ID-TENANT-NAME", "default")
.build();
Login with the OAuth 2.0 Device Flow
With this logon procedure, the client application calls the system browser so that the user can log on to an HTML form. The OAuth 2.0 Device Flow is used for this purpose. The procedure is done in the following four steps:
-
Start the login process and read out the parameters Device Code, User Code, and Verification URI. The example uses JsonPath for this. The parameter values lose their validity after five minutes. In this time window, the user must have finished logging in to the browser.
OAuth 2.0 Device Flow: Step 1Request.Builder startRequest = new Request.Builder().url(keycloakBaseUrl+"/tenant/default/loginDevice"); String responseJson = this.client.newCall(startRequest.build()).execute().body().string(); DocumentContext context = JsonPath.parse(responseJson); String deviceCode = context.read("device_code"); String userCode = context.read("user_code"); String verificationUri = context.read("verification_uri");
-
The Verification URI is opened with the User Code as a parameter in the system browser. The Authentication service then forwards to the login page of the identity provider, where the user can log in.
OAuth 2.0 Device Flow: Step 2Desktop.getDesktop().browse(new URI(keycloakBaseUrl + verificationUri + "?user_code=" + userCode));
-
At regular intervals, the client application queries the Authentication service to see whether the user has successfully logged in. This is the case if the status request receives the return code OK (200). The response of the status request contains a JSON object from which the access token and the token type must be extracted. In the example, JsonPath is used for this.
OAuth 2.0 Device Flow: Step 3String tokenType = null; String accessToken = null; for (int i = 1 ; i != 30 ; i++, Thread.sleep(2000)) { Request.Builder pollingRequest = new Request.Builder().url(keycloakBaseUrl+"/auth/info/state?device_code=" + deviceCode); Response pollingResponse = this.client.newCall(pollingRequest.build()).execute(); if (pollingResponse.code() != 200) continue; context = JsonPath.parse(pollingResponse.body().string()); tokenType = context.read("token_type"); accessToken = context.read("access_token"); break; }
-
Finally, the logon headers are assembled and sent to any Core API endpoint.
OAuth 2.0 Device Flow: Step 4Headers headers = new Headers.Builder() .add("Authorization", tokenType + " " + accessToken) .add("X-ID-TENANT-NAME", "default") .build();
3.1.6. Logout
After all necessary API operations have been performed, the session established by the logon can be closed.
Request.Builder logoutRequest = new Request.Builder().url(keycloakBaseUrl+"/logout");
this.client.newCall(logoutRequest.build()).execute();
3.1.7. Summary
This tutorial explains how an OkHttp3 Java client implements the different logon procedures for the Core API.
3.2. Importing Documents via Core API
This tutorial shows how documents can be imported into a yuuvis® API system via the Core API. During this tutorial, a short Java application will be developed that implements the HTTP requests for importing documents. We additionally provide a JavaScript version of this tutorial.
Check out our graphical overview of the architecture which describes the basic use case flow for importing documents.
3.2.1. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® API system (see Installation Guide)
-
A user with at least read permissions on a document type in the system (see tutorial for permissions)
-
Simple Maven project
3.2.2. Maven Configuration
Our Java client will submit its requests to the Core API using OkHttp 3.12 by Square, Inc. Therefore, the following block must be added to the Maven dependencies in the pom.xml of the project:
1
2
3
4
5
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
Client Configuration To interact with the yuuvis® API system via the Core API, we use an OkHttp3 client to send HTTP requests and read their responses.
String baseUrl = "http://127.0.0.1"; //baseUrl of gateway: "http://<host>:<port>"
String username = "clouduser";
String userpassword = "secret";
String tenant = "default";
String auth = java.util.Base64.getEncoder().encodeToString((username + ":" + userpassword).getBytes());
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient client = builder.build();
For more information on setting up the OkHttp3 client with cookie handling, please refer to this Login Tutorial.
3.2.3. Importing a Single Document
To import a document using the Java client, we need the metadata and optionally the content of the document (depending on the schema definition, there are document types that may or must have content or must not have content).
The metadata when importing a document has the following format:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"objects": [{
"properties": {
"objectTypeId": {
"value": "document"
},
"Name": {
"value": "test import"
}
},
"contentStreams": [{
"cid": "cid_63apple"
}]
}]
}
In our example, the schema contains an object type document with the Name property, which may or must have content. The content is referenced in the contentStreams
object by specifying a cid
(multipart content ID). In the example, the cid references a multipart content with content ID cid_63apple
.
A content file can be in different file formats. It is recommended to specify the format correctly in the metadata and in the multipart request. If the content type is not specified, it is automatically determined during the content analysis. If the content type determination is not clear or the content analysis is switched off, the content type application/octet-stream
is used.
In our example we have chosen a text file (Content-Type: text/plain
).
Request
For an import, a POST request must be sent to the endpoint /api/dms/objects
with a multipart body consisting of metadata and, if applicable, content of the object to be imported. To construct such a request, we use a MultipartBody.Builder()
, which allows us to build the request body from several form parts as follows.
1
2
3
4
5
6
7
8
9
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("data", "metaData.json",
RequestBody.create(MediaType.parse("application/json; charset=utf-8"),
new File("./src/main/resources/metaData.json")))
.addFormDataPart("cid_63apple", "test.txt",
RequestBody.create(MediaType.parse("text/plain; charset=utf-8"),
new File("./src/main/resources/test.txt")))
.build();
We use a Request.Builder()
to create a request object with the multipart body, headers, and the URL. The following headers are necessary for the import because they contain user information of the user accessing the endpoint: Authorization
header that contains the Base64-coded credentials of the user and an X-ID-TENANT-NAME
header that contains the tenant name of the user. If the used OkHttp client supports cookie handling, the Authorization
header can be omitted after the client’s first request, since the logon information is stored in a session cookie (see also Login Tutorial).
1
2
3
4
5
6
Request request = new Request.Builder()
.header("Authorization", "Basic "+ auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects") //baseUrl: "http://<host>:<port>"
.post(requestBody)
.build();
Response
To display the response of the API to the console, we create an associated response object when the request is executed. Please note that an IOException can be thrown by the OkHttpClient when creating the response object.
1
2
3
4
5
6
try{
Response response = client.newCall(request).execute();
System.out.println(response.body().string()); //print to console
} catch (IOException e) {
e.printStackTrace();
}
3.2.4. Importing Multiple Documents in Batch Mode
If multiple documents are to be imported at the same time, this can be done using the same endpoint of the Core API. Instead of a single object, the objects
list consists of several metadata records. The individual content files of the objects then each require a unique cid
as the name of the form-data parts in the multipart request. This cid
is referenced in the associated metadata record in the contentStreams
list, which allows metadata to be uniquely assigned to content.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"objects": [{
"properties": {
"objectTypeId": {
"value": "document"
},
"Name": {
"value": "test import object 1"
}
},
"contentStreams": [{
"cid": "cid_63apple"
}]
},
{
"properties": {
"objectTypeId": {
"value": "document"
},
"Name": {
"value": "test import object 2"
}
},
"contentStreams": [{
"cid": "cid_64apple"
}]
}]
}
Batch Request
In the multipart body, we create a separate FormDataPart for the content of each object, whose first parameter is the content ID (cid
).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
RequestBody batchImportRequestBody = new MultipartBody
.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("data",
"metaDataBatch.json",
RequestBody.create(MediaType.parse("application/json; charset=utf-8"),
new File("./src/main/resources/metaDataBatch.json")))
.addFormDataPart("cid_63apple",
"test1.txt",
RequestBody.create(MediaType.parse("text/plain; charset=utf-8"),
new File("./src/main/resources/test1.txt")))
.addFormDataPart("cid_64apple",
"test2.txt",
RequestBody.create(MediaType.parse("text/plain; charset=utf-8"),
new File("./src/main/resources/test2.txt")))
.build();
The assembly of the request object is identical to the normal import.
Response of Batch Request
If successful, the response object contains a multi-element objects list that contains the metadata records of all objects imported in this batch import.
3.2.5. Referencing an Existing Binary Content File
To save storage in your repository, multiple documents can reference the same binary content file. Specify contentStreamId
and repositoryId
of the existing binary content file in the import request as shown in the following example.
The archivePath
is only required if its value cannot be determined from the current request. For example, it is possible to configure a pathTemplate
containing dynamic path elements like DATE
in the application-storage.yml
configuration file. Values for archivePath
resulting from such dynamic path templated cannot be reconstructed for subsequently created objects that reference the same binary content.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"objects": [{
"properties": {
"objectTypeId": {
"value": "document"
},
"Name": {
"value": "test import with reference on existing content"
}
},
"contentStreams": [{
"contentStreamId": "DB886B37-FEEF-11E9-BCEC-3FAD551A2B8A",
"archivePath": "default/DOCUMENT/2024-03-21/86/B/",
"repositoryId": "repo252"
}]
}]
}
A special case is the creation of compound documents and corresponding sub-documents.
3.2.6. Summary
In this tutorial an OkHttpClient with Cookie-Handling was used to import documents via the Core API, both in batch mode and individually.
A complete code example can be found in this git repository.
3.3. Retrieving Documents via Core API
In this tutorial, we will discuss various ways to retrieve objects via the Core API from the yuuvis® API system using an OkHttp3 Java client.
Check out our graphical overview of the architecture which describes the basic use case flow for retrieving content or metadata.
3.3.1. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® API system (see installation guide)
-
A user with at least read permissions on a document type in the system (see tutorial for permissions)
-
Simple Maven project
3.3.2. Maven Configuration
Our Java client will submit its requests to the Core API using OkHttp 3.12 by Square, Inc. Therefore, the following block must be added to the Maven dependencies in the pom.xml
of the project:
1
2
3
4
5
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
3.3.3. Client Configuration
To interact with the yuuvis® API system via the Core API, we use an OkHttp3 client to send HTTP requests and read their responses.
1
2
3
4
5
6
7
8
String baseUrl = "http://127.0.0.1"; //baseUrl of gateway: "http://<host>:<port>"
String username = "clouduser";
String userpassword = "secret";
String tenant = "default";
String auth = java.util.Base64.getEncoder().encodeToString((username + ":" + userpassword).getBytes());
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient client = builder.build();
For more information on setting up the OkHttp3 client with cookie handling, please refer to this login tutorial.
3.3.4. Retrieving Documents
To be able to access documents, they must exist in the system. A tutorial for importing documents can be found here.
Retrieving Documents via Object ID
The direct access to a document takes place via its object ID via GET request to the endpoint /api/dms/objects/{objectId}
. The objectId
serves as a unique identifier of a document and can be obtained from the response of the API call of an import (see Tutorial for updating documents: Determining the objectId
after import).
1
2
3
4
5
6
7
8
9
10
11
String objectId = "1234567890"; //example-objectId
Request metadataRequest = new Request.Builder()
.header("Authorization", "Basic " + auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl+ "/api/dms/objects/" + objectId)
.get().build();
Response metadataResponse = client.newCall(metadataRequest).execute();
String metadataResponseString = metadataResponse.body().string();
The API call response will contain the current version of the objects' metadata in JSON format.
To retrieve the content of an object, a GET request is sent to the endpoint /api/dms/objects/{objectId}/contents/file
.
1
2
3
4
5
Request contentRequest = new Request.Builder()
.header("Authorization", "Basic " + auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl+ "/api/dms/objects/" + objectId + "/contents/file")
.get().build();
If a specific version of the document is to be requested, the endpoint to be called for the documents' metadata changes to /api/dms/objects/{objectId}/versions/{versionNr}
and for the documents' content to /api/dms/objects/{objectId}/versions/{versionNr}/contents/file
. More about this topic can be found in the Updating Documents via Core API tutorial under Versioning.
Retrieving Documents via Search Endpoint
The Core API provides a search endpoint (/api/dms/objects/search
) that can process search queries written in the proprietary Search Query Language. The search query is sent to the search endpoint in JSON format in the body of a POST request.
{
"query": {
"maxItems": 50,
"statement": "SELECT * FROM system:object WHERE CONTAINS('Europan') AND Name Like 'E%'",
"skipCount": 0
}
}
This example query searches for all objects of type enaio:object
whose content contains the string Europan
and whose value of property Name
begins with the character E
.
To create such a query object programmatically, a JSON library is needed to create the query JSON. We use org.json
, so the following block must be added to the Maven dependencies in the pom.xml
of the Java project:
1
2
3
4
5
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
Now we can implement a method createQueryJSON(String statement, int skipCount, int maxItems)
that creates a query object and returns it as a string. We send the string to the search endpoint in the request body of a POST request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static String createQueryJSON(String statement, int skipCount, int maxItems) {
JSONObject queryObject = new JSONObject();
JSONObject queryAttributes = new JSONObject();
queryAttributes.put("statement", statement);
queryAttributes.put("skipCount", skipCount);
queryAttributes.put("maxItems", maxItems);
queryObject.put("query", queryAttributes);
return queryObject.toString();
}
String query = createQueryJSON("SELECT * FROM system:object WHERE CONTAINS('Europan') AND Name Like 'E%'", 0, 50);
Request attributeSearchRequest = new Request.Builder()
.header("Authorization", "Basic " + auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/search")
.post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), query))
.build();
Response attributeSearchResponse = client.newCall(attributeSearchRequest).execute();
System.out.println(attributeSearchResponse.body().string());
The expected response is a list of DMS objects with metadata matching the search query, which can also be an empty list.
3.3.5. Summary
This tutorial showed how to use an OkHttpClient to retrieve documents via Core API.
A complete code example can be found in this Git repository.
3.4. Updating Documents via Core API
This tutorial demonstrates how to update documents in yuuvis® API with the Core API. The following example will result in a short Java application that implements the HTTP requests for updating a document.
Check out our graphical overview of the architecture which describes the basic use case flow for updating content or metadata.
3.4.1. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® API system (see Installation Guide)
-
A user with at least read permissions on a document type in the system (see tutorial for permissions)
-
Simple Maven project
3.4.2. Maven Configuration
Our Java client will submit its requests to the Core API using OkHttp 3.12 by Square, Inc. Therefore, the following block must be added to the Maven dependencies in the pom.xml
of the project:
1
2
3
4
5
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
3.4.3. Client Configuration
To interact with the yuuvis® API system via the Core API, we use an OkHttp3 client to send HTTP requests and read their responses.
1
2
3
4
5
6
7
8
String baseUrl = "http://127.0.0.1"; //baseUrl of gateway: "http://<host>:<port>"
String username = "clouduser";
String userpassword = "secret";
String tenant = "default";
String auth = java.util.Base64.getEncoder().encodeToString((username + ":" + userpassword).getBytes());
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient client = builder.build();
For more information on setting up the OkHttp3 client with cookie handling, please refer to this login tutorial.
The example client, which is created in this tutorial, is intended to exemplarily implement the possibilities of the DMS API for updating existing objects. For this purpose, the client needs the object ID of the existing object to be updated. We will update metadata and content of an object via the Core API and access older versions of the object.
3.4.4. Determining the Object ID after Import
The object ID of an object in the system remains consistent across all updates, so it is possible to pass the object ID of an existing object to the client. In our code example the client initially imports an object (tutorial here) to the system and extracts the objectId
of the newly created object from the response. The Java library org.json can accomplish this and will be used in this example, so it needs to be added to dependencies of the maven project:
1
2
3
4
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</dependency>
The extraction of the objectId
from the answer can be realized with org.json
as follows:
1
2
3
4
5
6
7
8
public static String parseObjectIdFromJsonResponse(String responseJson){
JSONObject jsonObject = new JSONObject(responseJson);
return jsonObject.getJSONArray("objects")
.getJSONObject(0)
.getJSONObject("properties")
.getJSONObject("system:objectId")
.getString("value");
}
3.4.5. Updating Documents
Update Metadata
POST Update Metadata (overwrite all)
To update the metadata of an existing object, a POST request containing the new metadata in the body must be sent to the endpoint (POST /api/dms/objects/{objectId}
). Instead of using a multipart body, the new metadata is passed to the body as a string and designated as media type JSON.
1
2
3
4
5
6
7
Request updateMetadataRequest = new Request.Builder()
.header("Authorization", "Basic "+ auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/" + objectId)
.post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"),
new File("./src/main/resources/metaData2.json")))
.build();
The response returns the full, modified metadata with a new version number.
PATCH Update Metadata (only provided properties)
Since a regular POST update overwrites all properties of an object type and can end up removing attributes if they are not resupplied, an alternative option for updating metadata is provided in the PATCH endpoint (PATCH /api/dms/objects/{objectId}
). It allows users to update or add only those properties provided in the request body. Properties can also be removed using the PATCH endpoint by setting the value of an existing property to null
.
1
2
3
4
5
6
7
Request patchMetadataRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/" + objectId)
.patch(RequestBody.create(MediaType.parse("application/json; charset=utf-8"),
new File("./src/main/resources/metadataPatch.json")))
.build();
3.4.6. Update Content
To update the content of an existing object, a POST request must be sent to the endpoint /api/dms/objects/{objectId}/contents/file
with the new content as a file in the body. The file name of the content file can be specified via the Content-Disposition
header.
1
2
3
4
5
6
7
8
Request updateContentRequest = new Request.Builder()
.header("Authorization", "Basic "+ auth)
.header("X-ID-TENANT-NAME", "default")
.header("Content-Disposition", "attachment; filename=\"test2.txt\"")
.url(baseUrl + "/api/dms/objects/" + objectId + "/contents/file") //baseUrl: "http://<host>:<port>"
.post(RequestBody.create(MediaType.parse("text/plain; charset=utf-8"),
new File("./src/main/resources/test2.txt")))
.build();
3.4.7. Versioning
When updating content or metadata, a new version of the object is created each time. The endpoints for fetching metadata (/api/dms/objects/{objectId}
) and content (/api/dms/objects/{objectId}/contents/file
) always return the current version of an object. It is also possible to get an older version of the object. How to do this is described in the next section.
Retrieving Version-Related Metadata
To retrieve metadata of a version, a GET request must be sent to the endpoint /api/dms/objects/{objectId}/versions/{versionNr}
. The version number for each object starts at 1 and is incremented with each update.
1
2
3
4
5
Request versionMetadataRequest = new Request.Builder()
.header("Authorization", "Basic "+ auth)
.header("X-ID-TENANT-NAME", "default")
.url(baseUrl+ "/api/dms/objects/" + objectId + "/versions/1")
.get().build();
Retrieving Version-Related Content
To retrieve the content of a version, a GET request must be sent to the endpoint /api/dms/objects/{objectId}/versions/{versionNr}/contents/file
.
1
2
3
4
5
Request versionContentRequest = new Request.Builder()
.header("Authorization", "Basic "+ auth)
.header("X-ID-TENANT-NAME", "default")
.url(baseUrl+ "/api/dms/objects/" + objectId + "/versions/2/contents/file")
.get().build();
3.4.8. Summary
In this tutorial, we used an OkHttpClient with cookie handling to import an object, to update its metadata and content, and finally retrieve the revised versions via the version-related endpoints.
The complete code example can be found in the Git repository.
3.5. Deleting Documents via Core API
This tutorial explains how documents can be deleted using the Core API with the help of a Java client. This tutorial requires basic knowledge of importing documents using the Core API.
Check out our graphical overview of the architecture which describes the basic use case flow for deleting content.
3.5.1. Requirements
To work through this tutorial, the following is required:
Set-up yuuvis® API system (see Installation Guide) A user with read and delete permissions on a document type in the system (see tutorial for permissions) Simple Maven project
3.5.2. Maven Configuration
Our Java client will submit its requests to the Core API using OkHttp 3.12 by Square, Inc. Therefore, the following block must be added to the Maven dependencies in the pom.xml
of the project:
1
2
3
4
5
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
3.5.3. Client Configuration
To interact with the yuuvis® API system via the Core API, we use an OkHttp3 client to send HTTP requests and read their responses.
1
2
3
4
5
6
7
8
9
String baseUrl = "http://127.0.0.1"; //baseUrl of gateway: "http://<host>:<port>"
String username = "clouduser";
String userpassword = "secret";
String tenant = "default";
String auth = java.util.Base64.getEncoder().encodeToString((username + ":" + userpassword).getBytes());
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient client = builder.build();
For more information on setting up the OkHttp3 client with cookie handling, please refer to this Login Tutorial.
3.5.4. Deleting a Document
To delete a document from the system, a DELETE request must be sent to the endpoint /api/dms/objects/{objectId}
for the corresponding object ID. This deletes the metadata record and, if present, the content file.
1
2
3
4
5
Request deleteRequest = new Request.Builder()
.header("Authorization", "Basic "+ auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/" + objectId) //baseUrl: "http://<host>:<port>"
.delete().build();
3.5.5. Deleting a Version of a Document
To delete a version of a document from the system, a DELETE request must be sent to the endpoint /api/dms/objects/{objectId}/versions/{versionNr}
. The corresponding version number must exist for the document. If the specified version number indicates the current version of the document, the entire document including all associated versions will be deleted.
1
2
3
4
5
6
Request deleteVersionRequest = new Request.Builder()
.header("X-ID-TENANT-NAME", "default")
.header("Authorization", "Basic "+ auth)
.url(baseUrl + "objects/"+objectId+"/versions/1") //baseUrl: "http://<host>:<port>"
.delete().build();
Response deleteVersionResponse = client.newCall(deleteVersionRequest).execute();
3.5.6. Deleting a Document with Binary Content
During the deletion of documents with binary content, yuuvis® Momentum searches for other documents that might refer to the same binary content file. It is identified by the content stream properties contentStreamId
and repositoryId
. Current object versions are considered as well as older versions.
-
If there are NO further references on the binary content, the document’s metadata AND binary content are deleted.
-
If there is at least one reference on the binary content, ONLY the metadata of the requested object are deleted.
Thus, the binary content is available for all remaining documents (an document versions) that still refer to it.
3.5.7. Deleting Compound Documents
Deleting compound documents is a special case of deleting documents with binary content. The chapter Using Compound Documents describes what compound documents are and what to consider when deleting compound documents.
3.5.8. Summary
In this tutorial an OkHttpClient with cookie handling was used to delete an object or a certain version of the object.
The complete code example can be found in the Git repository.
3.6. Retrieving Document History Entries
This tutorial shows how we can use a Java application to make a request to the Core API of the yuuvis® API system to retrieve the history entries of a DMS document. In addition, it briefly describes which history entries are generated for a document.
3.6.1. Introduction
The history of a DMS document is used to trace what happened to the document from the creation of the document in the system, meaning the import, to the disappearance of the document from the system, the deletion. This also includes events such as updating or retrieving the document.
3.6.2. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® API system (see Installation Guide)
-
A user with at least read permissions on a document type in the system (see tutorial for permissions)
-
Simple Maven project
3.6.3. The History Entry
An entry in the history looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"properties": {
"system:objectId": {
"value": 223439898
},
"system:objectTypeId": {
"value": "system:audit"
},
"system:baseTypeId": {
"value": "item"
},
"system:createdBy": {
"value": "353c631e-6a61-4e89-9512-8d275c826ce5"
},
"system:tenant": {
"value": "default"
},
"system:creationDate": {
"value": "2018-12-21T12:23:34.510Z"
},
"description": {
"value": ""
},
"action": {
"value": 101
},
"detail": {
"value": "CREATE_METADATA_WITH_CONTENT"
},
"referredObjectId": {
"value": "d3241d76-0652-4ac8-ba6d-892d719a2a6d"
},
"traceid": {
"value": "b279402aa9a2073b"
},
"system:versionNumber": {
"value": 1
}
}
}
A history entry is structured like a map, i.e. the entry consists of key-value pairs, whereby a value can also be a key-value pair.
Each history entry has an objectId
and a referencedObjectId
. The referredObjectId
is the object ID of the document for which the entry was written and the objectId
is the object ID of the entry itself.
Furthermore there are properties like createdBy
, detail
or versionNumber
, which indicate in which user context the entry was created, what happened and which version number the corresponding DMS document has after the protocolled action.
The time of the action (creationDate
) and the associated trace ID (traceid
) are also saved to ensure traceability.
3.6.4. The Client Application
We use a Java client to send a GET request to the Core API.
3.6.5. Maven Configuration
This example uses the OkHttpClient by Square, Inc. Therefore we add the following dependency to the file pom.xml
:
1
2
3
4
5
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
3.6.6. Client Configuration
To interact with the yuuvis® API system via the Core API, we use an OkHttp3 client to send HTTP requests and read their responses.
1
2
3
4
5
6
7
8
String baseUrl = "http://127.0.0.1"; //baseUrl of gateway: "http://<host>:<port>"
String username = "clouduser";
String userpassword = "secret";
String tenant = "default";
String auth = java.util.Base64.getEncoder().encodeToString((username + ":" + userpassword).getBytes());
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient client = builder.build();
For more information on setting up the OkHttp3 client with cookie handling, please refer to this Login Tutorial.
3.6.7. Retrieve History Entries of a Document
With a GET request to the URL /api/dms/objects/{objectId}/history
we can retrieve the history of the DMS document with the object ID objectId
. The objectId
serves as the unique identification number of an object and can be retrieved from the API response during import, for example (see tutorial on updating documents).
1
2
3
4
5
6
7
8
String objectId = "1234567890"; //example-objectId
Request request = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/" + objectId + "/history")
.get()
.build();
We can now execute the above request object with the OkHttpClient instance created at the beginning. Then we let the result be displayed as a string in the command line.
1
2
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
The returned history for a DMS document is a list of all history entries. All history codes available in yuuvis® Momentum are listed and explained in the concept article on the Audit Trail.
3.6.8. Summary
In this article, we used the OkHttpClient to retrieve the history of a DMS document and output the result to the command line. If you want to use a client to send several requests to the system in the same user context, we recommend a session handling, such as described here.
The full implementation of this example can be found in this git repository.
3.7. Using Compound Documents
Concatenate multiple binary content files as byte arrays in one compound document. Create sub-documents that refer to specified ranges within the total byte array.
3.7.1. Introduction
Compound documents in yuuvis® Momentum are document objects with a byte array as binary content file. In the byte array, it is possible to concatenate the binary coding of multiple individual files. Sub-documents can be defined such that they refer exactly to the ranges within the byte array where the individual original files are located. A retrieval request for the content file of such sub-documents then returns exactly the binary coding of the individual original files. But also any other range or any combination of ranges can be referenced as content of sub-documents. A retrieval request for the content file of such sub-documents then returns the concatenation of the specified ranges.
In this tutorial, we provide an example scenario for the handling of compound documents and sub-documents.
3.7.2. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® Momentum system (see Installation Guide)
-
Configured user with appropriate permissions (in the example:
clouduser:secret
on tenantdefault
) -
Simple Maven project
3.7.3. Maven Configuration
Our Java client will submit its requests to the Core API using OkHttp 3.12 by Square, Inc. To build the metadata of a compound document and evaluate the responses of the Core API, it also requires a JSON library, with org.json selected in this tutorial. To work with these libraries, the following block must be added to the Maven dependencies in the pom.xml
of the project:
1
2
3
4
5
6
7
8
9
10
11
12
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
</dependencies>
3.7.4. Client Configuration
The basis for accessing the Core API is an OkHttp3 client that can issue HTTP requests against reachable URLs. Additionally, we need to define some variables that our OkHttp3 client will use to reach and authenticate at the Core API.
1
2
3
4
5
6
7
8
String baseUrl = "http://127.0.0.1"; //baseUrl of gateway: "http://<host>:<port>"
String username = "clouduser";
String userpassword = "secret";
String tenant = "default";
String auth = java.util.Base64.getEncoder().encodeToString((username + ":" + userpassword).getBytes());
CookieJar cookieJar = new JavaNetCookieJar(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
OkHttpClient client = new OkHttpClient.Builder().cookieJar(cookieJar).build();
For more information on setting up the OkHttp3 client with cookie handling, see this tutorial on logging into the Core API.
3.7.5. Binary Content of the Compound Document
The binary content of a compound document must be a byte array. All individual files you want to concatenate have to be converted into this format. In the example code block below, FileUtils.readFileToByteArray(File file)
is used to convert the contents of a file into a ByteArray
(transforming it into binary code). If you want to reference the content of the individual original files lateron, you need to know their length within the byte array to determine their ranges.
1
2
3
4
5
6
7
byte[] document1BA = FileUtils.readFileToByteArray(new File("./src/main/resources/test.txt"));
byte[] document2BA = FileUtils.readFileToByteArray(new File("./src/main/resources/test1.txt"));
byte[] document3BA = FileUtils.readFileToByteArray(new File("./src/main/resources/test2.txt"));
long document1BAlength = document1BA.length;
long document2BAlength = document2BA.length;
long document3BAlength = document3BA.length;
The converted individual files can easily be concatenated to an output stream as shown in the next example code block. Pay attention to set the offset correctly in order to not overwrite parts of individual contents. You should store the byte ranges that correspond to the individual original files. In the example, they are stored in the ranges
array. Additionally, the original file names of the individual files are stored in the partialNames
array. Those values can be used to provide a more convenient recognition of the referenced ranges in the sub-documents' metadata.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//generate file for compound document content
File compoundFile = File.createTempFile("compound", ".bin");
OutputStream bos = new BufferedOutputStream(new FileOutputStream(compoundFile));
//partial document = Teildokument
String[] ranges = new String[3]; //Byte ranges of the partial documents in the compound document
String[] partialNames = new String[3]; //Names of the partial documents
//write partial document bytestreams into binary compound file
long offset = 0;
String range1 = offset + "-" + (offset + document1BAlength - 1);
bos.write(document1BA);
ranges[0] = range1;
partialNames[0] = "test.txt";
offset += document1BAlength;
String range2 = offset + "-" + (offset + document2BAlength - 1);
bos.write(document2BA);
ranges[1] = range2;
partialNames[1] = "test1.txt";
offset += document2BAlength;
String range3 = (offset) + "-" + (offset + document3BAlength - 1);
bos.write(document3BA);
ranges[2] = range3;
partialNames[2] = "test2.txt";
IOUtils.closeQuietly(bos);
3.7.6. Metadata for the Object Creation
Creating a Compound Document
The import endpoint POST /api/dms/objects
expects a multipart request body. Multiple objects can be created in yuuvis® Momentum with one request. Thus, it is possible to create the compound document with the concatenated byte array as content file and, in the same request, some sub-documents.
As shown in the example objects list below, the compound document is defined first. All following objects are sub-documents. They refer to the same cid
like the compound document, but a range
is additionally specified. Here, the ranges correspond to the individual original files and their original file names are noted in the metadata of the sub-documents.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
{
"objects": [
{
"contentStreams": [
{
"fileName": "compound.bin",
"mimeType": "application/octet-stream",
"cid": "cid_63apple"
}
],
"properties": {
"objectTypeId": {
"value": "document"
},
"name": {
"value": "testCompound"
}
}
},
{
"contentStreams": [
{
"fileName": "compound.bin",
"range": "0-1244",
"mimeType": "text/plain",
"cid": "cid_63apple"
}
],
"properties": {
"objectTypeId": {
"value": "document"
},
"name": {
"value": "test.txt"
}
}
},
{
"contentStreams": [
{
"fileName": "compound.bin",
"range": "1245-1338",
"mimeType": "text/plain",
"cid": "cid_63apple"
}
],
"properties": {
"objectTypeId": {
"value": "document"
},
"name": {
"value": "test1.txt"
}
}
},
{
"contentStreams": [
{
"fileName": "compound.bin",
"range": "1339-2610",
"mimeType": "text/plain",
"cid": "cid_63apple"
}
],
"properties": {
"objectTypeId": {
"value": "document"
},
"name": {
"value": "test2.txt"
}
}
}
]
}
Creating Sub-Documents
It is also possible to create sub-documents of an already existing compound document. Do not assign a binary content file a second time, but reference the contentStreamId
, repositoryId
and archivePath
where the binary content file of the compound document is stored. The archivePath
is especially required if reconstruction is not possible with metadata information (e.g., if a pathTemplate
containing dynamic path elements like DATE
is configured in the archive profile). As you can see in the example, you can also specify a concatenation of multiple ranges.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"objects": [
{
"contentStreams": [
{
"contentStreamId": "8FF6DBAE-1969-11E9-83A4-DFA1C5E44BD0",
"repositoryId": "repo242",
"archivePath": "default/2023/01/06/",
"range": "1159-1365,0-45"
"mimeType": "text/plain"
}
],
"properties": {
"objectTypeId": {
"value": "document"
},
"name": {
"value": "sub-concatenation.txt"
}
}
}
]
}
3.7.7. Importing Compound Documents
Importing a compound document with the DMS API works in the same way as regular imports via POST of a multipart body with metadata and content to the endpoint /api/dms/objects
. In the example, the compoundImportJsonString
contains the metadata for the compound document and sub-documents as shown before.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
RequestBody compoundImportRequestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("data", "metaData.json", RequestBody.create(JSON, compoundImportJsonString))
.addFormDataPart("cid_63apple", "compound.bin", RequestBody.create(OCTETSTREAM, compoundFile))
.build();
Request compoundImportRequest = new Request.Builder()
.header("Authorization", "Basic " + auth)
.header("X-ID-TENANT-NAME", "default")
.url(baseUrl + "objects")
.post(compoundImportRequestBody)
.build();
Response compoundImportResponse = client.newCall(compoundImportRequest).execute();
3.7.8. Importing Large Compound Documents
Importing very large compound documents together with the creation of many sub-documents (about 5000 or more) within one request can overload the Core API and cause some of the operations to fail. Therefore, it is recommended to stage such requests in several episodes: First, import the compound document itself as a single document and extract the contentStreamID
and repositoryId
from the response. From there, import the metadata of all sub-documents subsequently in a series of batch imports. Limit the amount of sub-documents per import to less than 5000 to avoid overloading.
When subsequently importing sub-documents, please note that the metadata (postSubDocumentImportJsonString
in the example) must be sent in a multipart body as well, even if this multipart body consists of only one part.
1
2
3
4
5
6
7
8
9
10
11
12
13
RequestBody postSubDocumentImportRequestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("data", "metadata.json", RequestBody.create(JSON, postSubDocumentImportJsonString))
.build();
Request postSubDocumentImportRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "objects")
.post(postSubDocumentImportRequestBody)
.build();
Response postSubDocumentImportResponse = client.newCall(postSubDocumentImportRequest).execute();
3.7.9. Retrieving Sub-Documents
If you request the content of a compound document, you will get the total byte array. However, in most use cases, you want to retrieve a specific section of the total byte array. This is easily possible by retrieving a sub-document with a suitable range
value that references the desired section in the total byte array (creation described above). You can retrieve its content by objectId
(of the dub-document) as usual and you will get the corresponding section of the compound document’s content.
1
2
3
4
5
6
7
Request getContentOfSubDocumentRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "objects/" + objectId + "/contents/file")
.get().build();
Response getContentOfSubDocumentResponse = client.newCall(getContentOfSubDocumentRequest).execute();
See also the tutorial Retrieving Documents via Core API.
3.7.10. Deleting Compound Documents
If you request the deletion of a compound document, its metadata is deleted from the database. Thus, the DMS object itself does not exist in the system anymore. However, if at least one sub-document references a range within the former compound document’s binary content file, the entire original byte array remains in the binary storage. It is even possible to define new sub-documents with reference on the same repositoryId and contentStreamId
. Only if you delete all sub-documents of an already deleted compound document, the binary content is deleted as well.
See also the tutorial Deleting Documents via Core API.
3.7.11. Summary
In this tutorial, we used an OkHttpClient to import and retrieve a compound document and several sub-documents through the Core API.
A complete code example can be found in this git repository.
3.8. Managing the Schema
This tutorial shows how to use the Core API to get the tenant-specific schema of the system, how to validate a schema, and how to bring in a new schema.
3.8.1. Introduction
The schema consists of the tenant-specific schema, the unchangeable system properties, and the global schema. It determines the attributes and properties that objects must or may have in the system. You can find out more about the structure of the schema here.
This tutorial deals with the administration of tenant-specific schemas. The global schema remains unchanged from the endpoints presented below.
A user can only manage the schema that belongs to the client to which he or she belongs. It is not possible to manage schemas of other clients. A user also requires the role 'YUUVIS_TENANT_ADMIN'.
The endpoints presented in the following example provide or expect a schema in XML format.
3.8.2. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® API system (see Installation Guide)
-
A user with read and delete permissions on a document type in the system (see tutorial for permissions)
-
Simple Maven project
3.8.3. Maven Configuration
This example uses the OkHttpClient of the open source portal Square Open Source. For this, we add the following dependency to the file pom.xml
:
1
2
3
4
5
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.0</version>
</dependency>
3.8.4. Client Configuration
To interact with the yuuvis® API system via the Core API, we use an OkHttp3 client to send HTTP requests and read their responses.
1
2
3
4
5
6
7
8
String baseUrl = "http://127.0.0.1"; //baseUrl of gateway: "http://<host>:<port>"
String username = "clouduser";
String userpassword = "secret";
String tenant = "default";
String auth = java.util.Base64.getEncoder().encodeToString((username + ":" + userpassword).getBytes());
OkHttpClient.Builder builder = new OkHttpClient.Builder();
OkHttpClient client = builder.build();
For more information on setting up the OkHttp3 client with cookie handling, please refer to this login tutorial.
3.8.5. Retrieving the Schema
The active schema can be retrieved with a GET request to the URL /api/admin/schema
. This schema contains only the tenant-specific, user-defined object types, properties, and so on. It does not contain any system types, meaning you can upload it as it is without the system behaving differently afterwards. Only the version number of the schema and the modification date would change. Underneath the tenant-specific schema lies a preconfigured global schema which can be altered only by authorized administrators via the URL /api/system/schema
. To retrieve a complete schema consisting of the global schema and the additions specific to the tenant of the user that requests it, use /api/dms/schema
.
1
2
3
4
5
6
Request getSchemaRequest = new Request.Builder()
.header("Authorization", "Basic " + auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/admin/schema")
.get()
.build();
The OkHttpClient instance now makes it easy to write the schema to a file.
1
2
3
4
5
try(FileOutputStream fos = new FileOutputStream("activeSchema.xml")) {
Response activeSchemaResponse = client.newCall(getSchemaRequest).execute();
byte[] bytes = activeSchemaResponse.body().bytes();
fos.write(bytes);
}
3.8.6. Validating a Schema
A POST request for the URL /api/admin/schema/validate
can be used to verify that a schema is valid. This requires a schema; in the example, under the path ./schemaToValidate.xml
. The schema is sent as a multi-part in the body of the request.
1
2
3
4
5
6
7
8
9
10
11
12
13
String filename = "./schemaToValidate.xml";
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", "schema.xml", RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), new File(filename)))
.build();
Request validateSchemaRequest = new Request.Builder()
.header("Authorization", "Basic " + auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/admin/schema/validate")
.post(requestBody)
.build();
The response to this request contains an HTTP status code and the validation result in JSON format. You can simply output this to the console after the request was called using an OkHttpClient instance.
1
2
3
4
Response validationResponse = client.newCall(validateSchemaRequest).execute();
System.out.println(validationResponse.code());
String validationResponseAsString = validationResponse.body().string();
System.out.println(validationResponseAsString);
In the case of a valid schema, the response contains the HTTP status code 200 and the validation result is an empty list, meaning it does not contain any validation errors.
1
2
3
{
"validationErrors": []
}
If, however, the schema is not valid, the response contains the HTTP status code 422 and there is at least one validation error.
1
2
3
4
5
{
"validationErrors": [{
"message": "Invalid property reference 'name' in type definition 'email'."
}]
}
3.8.7. Importing a New Schema
A new schema can be imported with the POST request to the URL /api/admin/schema
. The endpoint behaves similar to the validation endpoint, meaning the HTTP status code of the answer tells you if the schema is valid and the answer contains a validation result. The difference is that if the validation is successful, the schema is stored and activated in the system.
1
2
3
4
5
6
7
8
9
10
11
12
13
String filename = "./schemaToImport.xml";
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", "schema.xml", RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), new File(filename)))
.build();
Request validateSchemaRequest = new Request.Builder()
.header("Authorization", "Basic " + auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/admin/schema")
.post(requestBody)
.build();
The further use of the request is analogous to the validation of a schema described in the previous section.
3.8.8. Changing the Schema
Typically, you rarely want to import a completely new schema. Often you only want to extend the active schema with object types or properties or make small changes. This can be done with the help of the three preset endpoints:
-
Fetch the schema to be changed and save it locally in an XML file.
-
Make the desired changes to the XML file and verify with the validation endpoint whether the new version of the schema is still valid.
-
Import the changed, valid schema
3.8.9. Summary
This tutorial showed how to get the tenant-specific schema in XML format for editing, how to validate any schema and how to import a new schema.
The full implementations of these examples can be found in this Git repository.
For more information about creating your own Schema, please refer to the Schema concepts article.
3.9. Changing Object Structure during Lifecycle
This tutorial shows how to change the set of available metadata properties for individual DMS objects during their entire lifecycle. Classify objects at a later point in time, add or remove property groups at runtime by defining and referencing floating secondary object types (SOTs).
3.9.1. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® Momentum core system (see Installation Guide)
-
A user with
read
andwrite
permissions on a document type in the system (see Access Management)
3.9.2. Example Use Case
Since a high variety of customized business processes can be set up for managing content, this tutorial shows one basic example to give you a better understanding of the idea behind the provided functionality. Let us imagine the following initial situation: we want to import documents and do not know the content types yet. At a later point in time, if the content type is known, we would like to add the needed group of properties for invoice, delivery slip and supplier metadata by using floating secondary object types.
Defining Document Object Types
Add a new document object type definition (document
) with a single property (DateOfReceipt
) to your schema to enable the import in general. To store objects with content, the objects' type must be a document type and the contentStreamAllowed
attribute must specify that this type can or must have content (allowed
or required
).
...
<typeDocumentDefinition>
<id>appSot:document</id>
<baseId>system:document</baseId>
<contentStreamAllowed>allowed</contentStreamAllowed>
<propertyReference>appSot:DateOfReceipt</propertyReference>
</typeDocumentDefinition>
...
Define Secondary Object Types
Add three new SOTs to your schema - each representing a group of properties used for specifying the content type in detail (INV
invoice, DEL
delivery slip and SUP
supplier). At this point, it does not matter whether the SOT will be used later on by a document object type as static or floating.
...
<typeSecondaryDefinition>
<id>appSot:INV</id>
<baseId>system:secondary</baseId>
<propertyReference>appSot:invoiceNo</propertyReference>
</typeSecondaryDefinition>
<typeSecondaryDefinition>
<id>appSot:DEL</id>
<baseId>system:secondary</baseId>
<propertyReference>appSot:deliverySlipNo</propertyReference>
</typeSecondaryDefinition>
<typeSecondaryDefinition>
<id>appSot:SUP</id>
<baseId>system:secondary</baseId>
<propertyReference>appSot:name</propertyReference>
<propertyReference>appSot:address</propertyReference>
<propertyReference>appSot:phone</propertyReference>
</typeSecondaryDefinition>
...
Adding References to Secondary Object Types
Now, add three references to the secondary object types for your defined document object type (document
). All three are floating references (static="false"
), since they should only be used if the content type is known and the properties are useful and necessary.
...
<typeDocumentDefinition>
<id>appSot:document</id>
<baseId>system:document</baseId>
<contentStreamAllowed>allowed</contentStreamAllowed>
<secondaryObjectTypeId static="false">appSot:INV</secondaryObjectTypeId>
<secondaryObjectTypeId static="false">appSot:DEL</secondaryObjectTypeId>
<secondaryObjectTypeId static="false">appSot:SUP</secondaryObjectTypeId>
</typeDocumentDefinition>
...
Importing New Documents
First of all, import your documents as a simple instance of document
including the values for the date of receipt using the POST /api/dms/objects
endpoint.
{
"objects": [{
"properties": {
"system:objectTypeId": {
"value": "appSot:document"
}
"appSot:DateOfReceipt": {
"value": "2020-10-07"
}
}
}]
}
Adding Secondary Object Types
During the Lifecycle
If the content type is known, you update the DMS object’s metadata structure by assigning the necessary SOTs (POST /api/dms/objects/{objectId}
or PATCH /api/dms/objects/{objectId}
). Use the keyword add
for a single secondary object type, or value
with a comma separated list, e.g., ["INV","SUP"]
for multiple ones. Note that by using the keyword value
, the list of floating SOTs transferred will replace all existing ones. This includes the related properties and metadata values. If you want to keep the existing floating SOTs, you have to list them as well.
{
"objects": [{
"properties": {
"system:secondaryObjecttypeIds": {
"add": "INV"
},
"appSot:invoiceNo": {
"value": "K0815-2020-1894834"
}
}
}]
}
{
"objects": [{
"properties": {
"system:secondaryObjecttypeIds": {
"value": ["INV","SUP"]
},
"appSot:invoiceNo": {
"value": "K0815-2020-1894834"
},
"appSot:name": {
"value": "Supplier Smith"
},
"appSot:address": {
"value": "7 Main Street, London"
},
"appSot:phone": {
"value": "004420834029390"
}
}
}]
}
Right at the Start of the Lifecycle (Import)
If you already know what content type you are going to import (e.g., an invoice), you can add one or more floating SOTs right away. Use the keyword value
with a comma separated list, e.g., ["INV","SUP"]
and the POST /api/dms/objects
endpoint.
{
"objects": [{
"properties": {
"system:objectTypeId": {
"value": "appSot:document"
}
"system:secondaryObjectTypeIds": {
"value": ["INV","SUP"]
}
"appSot:DateOfReceipt": {
"value": "2020-10-07"
}
}
}]
}
Removing Secondary Object Types
When a floating SOT is not needed any longer, you remove it from the DMS object using the update endpoints (POST /api/dms/objects/{objectId}
or PATCH /api/dms/objects/{objectId}
). All related properties and metadata values will be removed as well.
{
"objects": [{
"properties": {
"system:secondaryobjecttypeids": {
"remove": "INV"
}
}
}]
}
Searching for Objects
You search for objects that use secondary object types by explicitly specifying them in the FROM
clause:
select * from appSot:INV
The search result delivers the entire object and not only the properties of the specified secondary object type.
3.10. Tagging Objects for Processing
Based on tags, you set up complex stateful processing chains. This tutorial describes how tags can be added, displayed, and updated in an example context. For this purpose, a typical application will be discussed: An import management system, which is an example for a processing chain, where tags are a helpful tool to describe the current status of each object.
3.10.1. Introduction
In modern data processing chains, asynchronous operations become more and more popular. Concerning the administration of such complex procedures, a status measure is essential. The lifecycle of any object needs to be documented with a view to a general knowledge on the current state of progress, and in order to enable the resumption of interrupted processes. If the object status were located in the metadata, each pass through a multi-stage processing chain would create a completely new version of the whole object, which needs to be stored in addition to the previous one. In contrast, tags are treated separately. They always have a state
and a traceId
, which are a basis for external support as well as a possibility to control asynchronous operations. This additional information is stored together with the object, but independently of the metadata. Tags can only be assigned to the current version of an object. At the same time, their management and modification does not trigger the creation of a new version. The so assigned processing status reflects a concrete state of the object and serves as the basis for further transactions.
3.10.2. Requirements
This tutorial is dedicated to experienced users. Please find information on requirements, maven and client configuration in our Importing Documents via Core API tutorial, on which the variables' names are based. The handling of any IOException is demonstrated there, too.
3.10.3. Application Example – Import Management
The import management allows for subsequent object type classification that is independent of the actual import process. As a matter of fact, the initial step is a general search for recently created objects that have to be analyzed. Any object identified will be flagged with an integer tag analysis
showing the current state of progress within the characterization process (waiting to be processed (1) → processing started (2) → processing finished (3) → metadata updated (4)).
Further tags will be assigned to the object in order to demonstrate the handling of multiple tags assigned to one object, to explain the tracing for tag operations and to illustrate the behavior of tags during metadata and content updates.
In this tutorial, the tag handling is explained by following one object with the arbitrary objectId=1234567812345678
through the processing chain of the import management. The code snippets can be executed in the same order as they are shown if the requirements are met and at least one document was imported. Replace the example objectId
in the code snippets by the actual objectId
of your imported document.
Adding Tags to Objects
A general search might deliver a long result list. In this example, one object is selected in order to demonstrate how to add a new tag. The selected object has the objectId=1234567812345678
. An analysis
tag is added with the current state
value 1 (= waiting to be processed). For the import management, this step will be carried out for each individual result of the general search.
The string variables auth
, tenant
and baseUrl
are defined in the client configuration.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String objectId = "1234567812345678";
String tagName = "analysis";
String tagValue = "1";
RequestBody addTagBody = RequestBody.create(null, new byte[]{});
Request addTagRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/" + objectId + "/tags/" + tagName + "/state/" + tagValue)
.post(addTagBody)
.build();
Response addTagResponse = client.newCall(addTagRequest).execute();
String addTagResponseString = addTagResponse.body().string();
System.out.println(addTagResponseString);
1
2
3
4
5
6
7
8
9
10
{"objects": [{
"properties": {
"system:tags": {
"value": [
["analysis",1,"2021-06-30T15:19:25.370Z","0ff83b2d8c17b704"]
]
}
}
}]
}
Endpoint details: POST /api/dms/objects/{objectId}/tags/{name}/state/{state}
.
We add a second tag to the example object in order to demonstrate the handling of multiple tags. The procedure is exactly the same.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String objectId = "1234567812345678";
String tagName = "testtag";
String tagValue = "7";
RequestBody addTagBody = RequestBody.create(null, new byte[]{});
Request addTagRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/" + objectId + "/tags/" + tagName + "/state/" + tagValue)
.post(addTagBody)
.build();
Response addTagResponse = client.newCall(addTagRequest).execute();
String addTagResponseString = addTagResponse.body().string();
System.out.println(addTagResponseString);
1
2
3
4
5
6
7
8
9
10
11
{"objects": [{
"properties": {
"system:tags": {
"value": [
["analysis",1,"2021-06-30T15:19:25.370Z","0ff83b2d8c17b704"],
["testtag",7,"2021-06-30T15:19:26.700Z","4b2448d66e4d02eb"]
]
}
}
}]
}
Showing Tags of Objects
To check the current state of the object processing, the tags of a specified object can be viewed. The response will contain the status information for all tags of the object with the given objectId
. In particular, the example code below returns the analysis
tag together with its state
value 1 as well as the testtag
tag together with its state
value 7.
1
2
3
4
5
6
7
8
9
10
11
String objectId = "1234567812345678";
Request getTagRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl+ "/api/dms/objects/" + objectId + "/tags")
.get().build();
Response tagResponse = client.newCall(getTagRequest).execute();
String tagResponseString = tagResponse.body().string();
System.out.println(tagResponseString);
1
2
3
4
5
6
7
8
9
10
11
12
{"objects": [{
"properties": {
"system:tags": {
"columnNames": ["name","state","creationDate","traceId"],
"value": [
["analysis",1,"2021-06-30T15:19:25.370Z","0ff83b2d8c17b704"],
["testtag",7,"2021-06-30T15:19:26.700Z","4b2448d66e4d02eb"]
]
}
}
}]
}
Endpoint details: GET /api/dms/objects/{objectId}/tags
Searching Objects and Updating Their Tags
At this point in the import management context, there are several objects in the system having a newly added analysis
tag with the state
1. They are all waiting for a time-consuming processing step, but only one of them can be handled at the same time. In order to select one individual object for further processing, a search query is used, which returns a limited result list of objects having an analysis
tag with the state
1 that was created/modified today or yesterday. The first result in this list is updated to state=2
which means processing started. In the code snippet of the Adding Tags to Objects section, only one object was flagged with the tag and thus the following code snippet will continue with exactly this object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
String statement = "SELECT * FROM document WHERE system:tags[analysis].(state=1 AND (creationDate=YESTERDAY() OR creationDate=TODAY()))";
String tagName = "analysis";
String newTagValue = "2";
Request queryTagRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/tags/" + tagName + "/state/" + newTagValue + "?query=" + statement)
.post(RequestBody.create(null, new byte[0]))
.build();
Response queryTagResponse = client.newCall(queryTagRequest).execute();
String queryTagResponseString = queryTagResponse.body().string();
System.out.println(queryTagResponseString);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{"objects": [{
"properties": {
"system:objectId": {
"value": "1234567812345678"
},
...
"system:versionNumber": {
"value": 1
},
...
...
"system:tags": {
"value": [
["analysis",2,"2021-06-30T15:19:27.950Z","0ff83b2d8c17b704"],
["testtag",7,"2021-06-30T15:19:26.700Z","4b2448d66e4d02eb"]
]
},
...
},
...
}]
}
Endpoint details: POST /api/dms/objects/tags/{name}/state/{state}?query=<SQL>
Updating Tags of Objects
As soon as the processing of the object is finished, the tag should be updated as well. The code below will change the status value of the analysis
tag to 3 (= processing finished).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
String objectId = "1234567812345678";
String tagName = "analysis";
String newTagValue = "3";
Request updateTagRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.url(baseUrl + "/api/dms/objects/" + objectId + "/tags/" + tagName + "/state/" + newTagValue + "?overwrite=true")
.post(RequestBody.create(null, new byte[0]))
.build();
Response updateTagResponse = client.newCall(updateTagRequest).execute();
String updateTagResponseString = updateTagResponse.body().string();
System.out.println(updateTagResponseString);
1
2
3
4
5
6
7
8
9
10
11
12
{"objects": [{
"properties": {
"system:tags": {
"columnNames": ["name","state","creationDate","traceId"],
"value": [
["analysis",3,"2021-06-30T15:19:28.530Z","faa0cdae5008d7e0"],
["testtag",7,"2021-06-30T15:19:26.700Z","4b2448d66e4d02eb"]
]
}
}
}]
}
Adding Tags with Specified 'traceId'
In order to label multiple tag operations to associate them with one overall process, the traceId can be specified. In the code block below, the tracingprocess
tag with state
value 1 is added to our example object specified by its objectId
. Additionally, a string traceId is defined in line 4. The traceId is passed to the endpoint in the request header in line 9. It will be set as value for the traceId
of the new tag tracingprocess
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String objectId = "1234567812345678";
String tagName = "tracingprocess";
String tagValue = "1";
String traceId = "1122334455667788";
Request addTagRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.header("X-B3-TraceId", traceId)
.url(baseUrl + "/api/dms/objects/" + objectId + "/tags/" + tagName + "/state/" + tagValue)
.post(RequestBody.create(null, new byte[0]))
.build();
Response addTagResponse = client.newCall(addTagRequest).execute();
String addTagResponseString = addTagResponse.body().string();
System.out.println(addTagResponseString);
1
2
3
4
5
6
7
8
9
10
11
12
13
{"objects": [{
"properties": {
"system:tags": {
"columnNames": ["name","state","creationDate","traceId"],
"value": [
["analysis",3,"2021-06-30T15:19:28.530Z","faa0cdae5008d7e0"],
["testtag",7,"2021-06-30T15:19:26.700Z","4b2448d66e4d02eb"],
["tracingprocess",1,"2021-06-30T15:19:30.250Z","1122334455667788"]
]
}
}
}]
}
Endpoint details: POST /api/dms/objects/{objectId}/tags/{name}/state/{state}
Updating Tags with Specified 'traceId'
Similar as in Adding Tags with Specified 'traceId', also in a tag update request, the query parameter traceIdMustMatch=true
can be set if a traceId
is specified in the header. The update operation will be performed only if the values are matching. Thus, the tag can only be updated if the previous traceId
is known to the caller. Furthermore, the update operation will appear with the same traceId in the audit trail and can thus be summarized with the tag creation operation in one overall process trace.
The code block below shows an update request for the tracingprocess
tag to the state
value 2. Since the traceId
specified in line 4 and referenced in line 9 matches the current traceId
of the tracingprocess
tag, the update will be successful. Of course, the traceId
will remain the same after the tag update.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
String objectId = "1234567812345678";
String tagName = "tracingprocess";
String newTagValue = "2";
String traceId = "1122334455667788";
Request updateTagRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.header("X-B3-TraceId", traceId)
.url(baseUrl + "/api/dms/objects/" + objectId + "/tags/" + tagName + "/state/" + newTagValue + "?overwrite=true&traceIdMustMatch=true")
.post(RequestBody.create(null, new byte[0]))
.build();
Response updateTagResponse = client.newCall(updateTagRequest).execute();
String updateTagResponseString = updateTagResponse.body().string();
System.out.println(updateTagResponseString);
1
2
3
4
5
6
7
8
9
10
11
12
13
{"objects": [{
"properties": {
"system:tags": {
"columnNames": ["name","state","creationDate","traceId"],
"value": [
["analysis",3,"2021-06-30T15:19:28.530Z","faa0cdae5008d7e0"],
["testtag",7,"2021-06-30T15:19:26.700Z","4b2448d66e4d02eb"],
["tracingprocess",2,"2021-06-30T15:19:30.780Z","1122334455667788"]
]
}
}
}]
}
Endpoint details: POST /api/dms/objects/{objectId}/tags/{name}/state/{state}?overwrite=true
Deleting Tags with Specified 'traceId'
The deletion of a tag can be requested with the appended query parameter traceIdMustMatch=true
or without. If not specified, the default traceIdMustMatch=false
will be set and the current traceId
of the corresponding tag will not be checked.
The code block shows a deletion call with traceIdMustMatch=true
. The traceId
in the header will be compared with the current traceId
of the tag tracingprocess
. If the values are matching, the tag is deleted.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
String objectId = "1234567812345678";
String tagName = "tracingprocess";
String traceId = "1122334455667788";
Request deleteTagRequest = new Request.Builder()
.header("Authorization", auth)
.header("X-ID-TENANT-NAME", tenant)
.header("X-B3-TraceId", traceId)
.url(baseUrl + "/api/dms/objects/"+ objectId + "/tags/" + tagName + "?traceIdMustMatch=true")
.delete().build();
Response deleteTagResponse = client.newCall(deleteTagRequest).execute();
if(deleteTagResponse.code() == 200) System.out.println("Successfully deleted.");
else System.out.println("Error while deleting: " + deleteTagResponse.code());
Endpoint details: DELETE /api/dms/objects/{objectId}/tags/{name}
Tag Behavior in PATCH Metadata Update
In this section the behavior of tags during PATCH metadata update calls is demonstrated. To learn about requesting the call itself, please refer to the Updating Documents via Core API tutorial.
In a PATCH update, only the properties referenced in the request body will be modified. Although the tags do not belong to the metadata, they can be modified like metadata and together with the metadata in one call. The tag information is stored in table format. Thus, like for metadata table properties, the entire table will be replaced during the PATCH update. Consequently, tags can be added, updated or removed from the object. The code block shows an example request body that updates the state of the analysis tag to value 4 (= metadata updated) and adds the new tag contentprocessing:resistant
. The suffix resistant indicates that the tag persists during updates of the binary content file assigned to the corresponding object. From the PATCH request body, only name and state of the tags are read. The tag properties creationDate
and traceId
are automatically determined by the system. The traceId
of each tag will have the value of the system:traceId
metadata property. In our example request body, the table row for the testtag
tag is missing and will thus not appear in the new tag table anymore.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"objects": [{
"properties": {
"Name": {
"value": "Test 3"
},
"system:tags": {
"value": [
["analysis",4],
["contentprocessing:resistant",13]
]
}
}
}]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{"objects": [{
"properties": {
"system:objectId": {
"value": "1234567812345678"
},
...
"system:versionNumber": {
"value": 2
},
...
"system:traceId": {
"value": "118343a3fbc940e6"
},
"system:tags": {
"value": [
["analysis",4,"2021-06-30T15:19:32.560Z","118343a3fbc940e6"],
["contentprocessing:resistant",13,"2021-06-30T15:19:32.560Z","118343a3fbc940e6"]
]
},
"Name": {
"value": "Test 3"
},
},
...
}]
}
Endpoint details: PATCH /api/dms/objects/{objectId}
Content Update
See how to prepare a call for the update of the binary content file in the Updating Documents via Core API tutorial. The content update creates a new version of the object and deletes all the assigned tags that are not resistant tags.
From our example object, the tag analysis
is removed, but the resistant tag contentprocessing:resistant
is kept for the new object version. The values of the tag properties remain unchanged. The code block below shows an excerpt of the response including the system:tags
tag table after the update of the binary content file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{"objects": [{
"properties": {
"system:objectId": {
"value": "1234567812345678"
},
...
"system:versionNumber": {
"value": 3
},
...
...
"system:tags": {
"value": [
["contentprocessing:resistant",13,"2021-06-30T15:19:32.560Z","118343a3fbc940e6"]
]
},
"Name": {
"value": "Test 3"
},
},
...
}]
}
Endpoint details: POST /api/dms/objects/{objectId}/contents/file
POST Metadata Update
See how to prepare a POST update of the metadata in the Updating Documents via Core API tutorial. The update replaces all the metadata of the object with the values specified in the request body. If a property is missing in the request body, it will be removed from the object (except automatically determined system properties). Also the entire table with the tag information has to be explicitly specified as already described in the Tag Behavior in PATCH Metadata Update section. If the system:tags
table is not specified in the request body, all tags will be removed from the object.
The code block below shows an example request body where no tags are specified. Thus, the analysis
tag and especially also the contentprocessing:resistant
tag are deleted.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{"objects": [{
"properties": {
"system:objectId": {
"value": "1234567812345678"
},
...
"system:versionNumber": {
"value": 4
},
...
"system:tags": {
"value": null
},
"Name": {
"value": "Test 2"
},
},
...
}]
}
3.10.4. Summary
This tutorial illustrated the tag handling supported by yuuvis® Momentum in the example context of a simplified import management system. For control and administration of the status of individual objects within a process chain, tags are the means of choice.
Code examples in gitHub
3.11. Setting and Querying Structured Data
This example tutorial provides explanations and code examples to get an idea on how to define and specify structured data properties and on how to query them.
3.11.1. Introduction
yuuvis® Momentum offers a property type for the storage of structured data in JSON format. Thus, it is possible to store interleaved data structures in a queryable way without defining each single sub-property in the schema. The structured data properties should NOT be considered to replace the concept of a well-defined schema. They should be used only if the handling of objects' metadata via the conventional property definitions is not reasonable. Especially, if the structure of metadata and/or the availability of properties differs a lot for the individual object instances, the schema might grow to a really long list of scarcely used properties. This can be avoided by the usage of a property field that can store a JSON structure as value. In this tutorial, the bibliographic information of media in a library is considered an example use case. For this purpose, the set of information for each medium is provided in JSON structure following the concept of BibJSON.
Code examples in GitHub.
3.11.2. Requirements
This tutorial is dedicated to experienced users. Please find information on requirements, maven and client configuration in our Importing Documents via Core API tutorial. The handling of any IOException is demonstrated there, too.
3.11.3. Definition in the Schema
In the context of the library example, the below displayed app schema is used. It contains two property definitions and one object type definition referencing the properties. The first property bibjsonsample:bibjson
has the property type structureddata
. Its id
matches the expression expected for the validation and the cardinality
is single which is the only accepted value.
This property will be used for the storage of the BibJSON structure containing the bibliographic information of the corresponding medium. The second property bibjsonsample:locations
allows for the assignment of a list of strings indicating storage locations if a printed version is available for the corresponding medium. In the object type definition of bibjsonsample:medium
, both properties are referenced. Additionally, a binary content file can be assigned if necessary as defined in line 25 with the value allowed for the contentStreamAllowed
attribute.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://optimal-systems.org/ns/dmscloud/schema/v5.0/dmsCloud-schema.xsd">
<propertyStructuredDataDefinition>
<id>bibjsonsample:bibjson</id>
<description>field for the BibJSON structure identifying and describing the medium</description>
<propertyType>structureddata</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStructuredDataDefinition>
<propertyStringDefinition>
<id>bibjsonsample:locations</id>
<description>field for storage locations of printed versions of the medium</description>
<propertyType>string</propertyType>
<cardinality>multi</cardinality>
<required>false</required>
</propertyStringDefinition>
<typeDocumentDefinition>
<id>bibjsonsample:medium</id>
<baseId>system:document</baseId>
<propertyReference>bibjsonsample:bibjson</propertyReference>
<propertyReference>bibjsonsample:locations</propertyReference>
<contentStreamAllowed>allowed</contentStreamAllowed>
</typeDocumentDefinition>
</schema>
The schema for the bibjsonsample
app is imported via the POST /api/system/apps/{app}/schema
endpoint.
More details and further examples on schema handling are provided in the following tutorial: Managing the Schema
3.11.4. Specifying Values during Import
Two example objects will be created as instances of the abbBibjsonsample:medium
object type. Both of them are assigned a BibJSON value for the appbibjsonsample:bibjson
property.
For the individual sub-values of the structured data property, the system can identify integers, booleans and strings. The successfully executed import returns the entire set of metadata for each object, enriched with the system properties.
The first example object is a book. The bibliographic information stored in the appBibjsonsample:bibjson
property contains one integer value specified in line 21. All other sub-values are stored as strings. In addition to the appBibjsonsample:bibjson
property, two storage locations for printed versions are specified.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"objects": [{
"properties": {
"objectTypeId": {
"value": "appBibjsonsample:medium"
},
"appBibjsonsample:bibjson": {
"value": {
"type": "book",
"title": "My Book Title",
"author": [
{"name": "Heinrich Schuetzel"},
{"name": "Maximilian Sturz"}
],
"year": "1995",
"owner": "My Library",
"id": "ID_of_book",
"url": "http://mylibrary.com/ebooks/36513466534",
"publisher": "Example Verlag Mustershagen",
"edition": {
"number": 2,
"language": "English"
},
"identifier":[
{
"id": "0002-9327",
"type": "issn"
}
]
}
},
"appBibjsonsample:locations": {
"value": [
"central library, CN-3214-5324",
"branch library east, 43-654b"
]
}
}
}]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{
"objects": [
{
"properties": {
"system:objectId": {
"value": "aab2b4d9-e829-45dd-981a-2f19a688592d"
},
"system:baseTypeId": {
"value": "system:document"
},
"system:objectTypeId": {
"value": "appBibjsonsample:medium"
},
"system:createdBy": {
"value": "275c826c-6a61-4e89-9512-8d935a1631e5"
},
"system:creationDate": {
"value": "2021-06-14T13:10:52.280Z"
},
"system:lastModifiedBy": {
"value": "275c826c-6a61-4e89-9512-8d935a1631e5"
},
"system:lastModificationDate": {
"value": "2021-06-14T13:10:52.280Z"
},
"system:versionNumber": {
"value": 1
},
"system:tenant": {
"value": "default"
},
"system:traceId": {
"value": "5681d3bddb4279de"
},
"appBibjsonsample:bibjson": {
"value": {
"type": "book",
"title": "My Book Title",
"author": [
{
"name": "Heinrich Schuetzel"
},
{
"name": "Maximilian Sturz"
}
],
"year": "1995",
"owner": "My Library",
"id": "ID_of_book",
"url": "http://mylibrary.com/ebooks/36513466534",
"publisher": "Example Verlag Mustershagen",
"edition": {
"number": 2,
"language": "English"
},
"identifier": [
{
"id": "0002-9327",
"type": "issn"
}
]
}
},
"appBibjsonsample:locations": {
"value": [
"central library, CN-3214-5324",
"branch library east, 43-654b"
]
}
}
}
]
}
The second example object is a collection of articles without corresponding printed versions. The structure of the JSON value for the appBibjsonsample:bibjson
property looks completely different.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
{
"objects": [
{
"properties": {
"system:objectId": {
"value": "3d4a67be-3341-4317-bb57-c48ea7ab0a1a"
},
"system:baseTypeId": {
"value": "system:document"
},
"system:objectTypeId": {
"value": "appBibjsonsample:medium"
},
"system:createdBy": {
"value": "275c826c-6a61-4e89-9512-8d935a1631e5"
},
"system:creationDate": {
"value": "2021-06-14T13:11:57.770Z"
},
"system:lastModifiedBy": {
"value": "275c826c-6a61-4e89-9512-8d935a1631e5"
},
"system:lastModificationDate": {
"value": "2021-06-14T13:11:57.770Z"
},
"system:versionNumber": {
"value": 1
},
"system:tenant": {
"value": "default"
},
"system:traceId": {
"value": "22839c5775801e9c"
},
"appBibjsonsample:bibjson": {
"value": {
"metadata": {
"collection": "ym_concepts",
"label": "yuuvis(R) Momentum Core Concepts",
"description": "Documentation for yuuvis(R) Momentum Core in a structured, theoretical way, with links to the tutorial section.",
"id": "ID_of_collection",
"owner": "OS",
"created": "2020-06-09T15:04:12.944Z",
"modified": "2021-06-10T11:05:17.166Z",
"source": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/-4BkAg",
"records": 2
},
"records": [
{
"collection": "ym_concepts",
"type": "article",
"title": "Schema - Defining Object Types",
"id": "ID_of_schema_article",
"link": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/AYFkAg",
"author": [
{
"name": "Heinrich Schuetzel"
},
{
"name": "George Trader"
},
{
"name": "Johann Fluss"
}
],
"created": "2020-06-09T15:04:12.944Z",
"modified": "2021-06-10T08:53:23.532Z"
},
{
"collection": "ym_concepts",
"type": "article",
"title": "Search Query Language",
"id": "ID_of_query_article",
"link": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/gIFkAg",
"author": [
{
"name": "Andrea Schumann"
},
{
"name": "Franz Lissner"
},
{
"name": "Hans Kammer"
},
{
"name": "Johann Fluss"
}
],
"created": "2020-06-16T14:03:01.833Z",
"modified": "2021-06-02T09:54:12.643Z"
}
]
}
}
}
}
]
}
3.11.5. Search Queries
The individual sub-values within the JSON value for the appBibjsonsample:bibjson
property are queryable.
In this chapter, some example search queries are explained.
Example 1
This query statement requests a search for all objects of type appBibjsonsample:medium
. The full set of metadata will be returned for each of them. In the example context of this tutorial, only two objects match the query: The book and the collection that were imported before.
SELECT * FROM appBibjsonsample:medium
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
{
"objects": [
{
"properties": {
"system:traceId": {
"value": "5681d3bddb4279de"
},
"system:objectTypeId": {
"value": "appBibjsonsample:medium"
},
"appBibjsonsample:bibjson": {
"value": {
"type": "book",
"title": "My Book Title",
"author": [
{
"name": "Heinrich Schuetzel"
},
{
"name": "Maximilian Sturz"
}
],
"year": "1995",
"owner": "My Library",
"id": "ID_of_book",
"url": "http://mylibrary.com/ebooks/36513466534",
"publisher": "Example Verlag Mustershagen",
"edition": {
"number": 2,
"language": "English"
},
"identifier": [
{
"id": "0002-9327",
"type": "issn"
}
]
}
},
"system:versionNumber": {
"value": 1
},
"system:createdBy": {
"value": "275c826c-6a61-4e89-9512-8d935a1631e5"
},
"system:creationDate": {
"value": "2021-06-14T13:10:52.280Z"
},
"system:lastModificationDate": {
"value": "2021-06-14T13:10:52.280Z"
},
"system:baseTypeId": {
"value": "system:document"
},
"system:tenant": {
"value": "default"
},
"appBibjsonsample:locations": {
"value": [
"central library, CN-3214-5324",
"branch library east, 43-654b"
]
},
"system:lastModifiedBy": {
"value": "275c826c-6a61-4e89-9512-8d935a1631e5"
},
"system:objectId": {
"value": "aab2b4d9-e829-45dd-981a-2f19a688592d"
}
}
},
{
"properties": {
"system:traceId": {
"value": "22839c5775801e9c"
},
"system:objectTypeId": {
"value": "appBibjsonsample:medium"
},
"appBibjsonsample:bibjson": {
"value": {
"metadata": {
"collection": "ym_concepts",
"label": "yuuvis(R) Momentum Core Concepts",
"description": "Documentation for yuuvis(R) Momentum Core in a structured, theoretical way, with links to the tutorial section.",
"id": "ID_of_collection",
"owner": "OS",
"created": "2020-06-09T15:04:12.944Z",
"modified": "2021-06-10T11:05:17.166Z",
"source": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/-4BkAg",
"records": 2
},
"records": [
{
"collection": "ym_concepts",
"type": "article",
"title": "Schema - Defining Object Types",
"id": "ID_of_schema_article",
"link": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/AYFkAg",
"author": [
{
"name": "Heinrich Schuetzel"
},
{
"name": "George Trader"
},
{
"name": "Johann Fluss"
}
],
"created": "2020-06-09T15:04:12.944Z",
"modified": "2021-06-10T08:53:23.532Z"
},
{
"collection": "ym_concepts",
"type": "article",
"title": "Search Query Language",
"id": "ID_of_query_article",
"link": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/gIFkAg",
"author": [
{
"name": "Andrea Schumann"
},
{
"name": "Franz Lissner"
},
{
"name": "Hans Kammer"
},
{
"name": "Johann Fluss"
}
],
"created": "2020-06-16T14:03:01.833Z",
"modified": "2021-06-02T09:54:12.643Z"
}
]
}
},
"system:lastModificationDate": {
"value": "2021-06-14T13:11:57.770Z"
},
"system:versionNumber": {
"value": 1
},
"system:baseTypeId": {
"value": "system:document"
},
"system:tenant": {
"value": "default"
},
"system:createdBy": {
"value": "275c826c-6a61-4e89-9512-8d935a1631e5"
},
"system:creationDate": {
"value": "2021-06-14T13:11:57.770Z"
},
"system:lastModifiedBy": {
"value": "275c826c-6a61-4e89-9512-8d935a1631e5"
},
"system:objectId": {
"value": "3d4a67be-3341-4317-bb57-c48ea7ab0a1a"
}
}
}
],
"numItems": 2,
"hasMoreItems": false,
"totalNumItems": 2
}
Example 2
In order to return only the bibliographic information in the result list of the search request, select the appBibjsonsample:bibjson
property.
SELECT appBibjsonsample:bibjson FROM appBibjsonsample:medium
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
{
"objects": [
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"type": "book",
"title": "My Book Title",
"author": [
{
"name": "Heinrich Schuetzel"
},
{
"name": "Maximilian Sturz"
}
],
"year": "1995",
"owner": "My Library",
"id": "ID_of_book",
"url": "http://mylibrary.com/ebooks/36513466534",
"publisher": "Example Verlag Mustershagen",
"edition": {
"number": 2,
"language": "English"
},
"identifier": [
{
"id": "0002-9327",
"type": "issn"
}
]
}
}
}
},
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"metadata": {
"collection": "ym_concepts",
"label": "yuuvis(R) Momentum Core Concepts",
"description": "Documentation for yuuvis(R) Momentum Core in a structured, theoretical way, with links to the tutorial section.",
"id": "ID_of_collection",
"owner": "OS",
"created": "2020-06-09T15:04:12.944Z",
"modified": "2021-06-10T11:05:17.166Z",
"source": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/-4BkAg",
"records": 2
},
"records": [
{
"collection": "ym_concepts",
"type": "article",
"title": "Schema - Defining Object Types",
"id": "ID_of_schema_article",
"link": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/AYFkAg",
"author": [
{
"name": "Heinrich Schuetzel"
},
{
"name": "George Trader"
},
{
"name": "Johann Fluss"
}
],
"created": "2020-06-09T15:04:12.944Z",
"modified": "2021-06-10T08:53:23.532Z"
},
{
"collection": "ym_concepts",
"type": "article",
"title": "Search Query Language",
"id": "ID_of_query_article",
"link": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/x/gIFkAg",
"author": [
{
"name": "Andrea Schumann"
},
{
"name": "Franz Lissner"
},
{
"name": "Hans Kammer"
},
{
"name": "Johann Fluss"
}
],
"created": "2020-06-16T14:03:01.833Z",
"modified": "2021-06-02T09:54:12.643Z"
}
]
}
}
}
}
],
"numItems": 2,
"hasMoreItems": false,
"totalNumItems": 2
}
Example 3
It is even possible to return specified sub-values of the JSON structure stored in the appBibjsonsample:bibjson
property. If you specify an index within a list, the values for the list elements with lower indices will be replaced by null in the return statement as can be seen in line 9.
SELECT appBibjsonsample:bibjson.title,appBibjsonsample:bibjson.author[1].name,appBibjsonsample:bibjson.metadata.id FROM appBibjsonsample:medium
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"objects": [
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"title": "My Book Title",
"author": [
null,
{
"name": "Maximilian Sturz"
}
]
}
}
}
},
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"metadata": {
"id": "ID_of_collection"
}
}
}
}
}
],
"numItems": 2,
"hasMoreItems": false,
"totalNumItems": 2
}
Example 4
If you know the path of the sub-value within the JSON you want to query, you can directly specify it. The example query configures a search for a specific medium identified by its bibliographic ID.
SELECT appBibjsonsample:bibjson.title FROM appBibjsonsample:medium WHERE appBibjsonsample:bibjson.id = 'ID_of_book'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"objects": [
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"title": "My Book Title",
"author": [
null,
{
"name": "Maximilian Sturz"
}
]
}
}
}
}
],
"numItems": 1,
"hasMoreItems": false,
"totalNumItems": 1
}
Example 5
If you want to search for an object with a specific sub-value but unknown path, a *
wildcard can be used. Each object containing the string ID_of_schema_article
as a sub-value for the appBibjsonsample:bibjson
property will match the query.
SELECT appBibjsonsample:bibjson.metadata.id FROM appBibjsonsample:medium WHERE appBibjsonsample:bibjson.* = 'ID_of_schema_article'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"objects": [
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"metadata": {
"id": "ID_of_collection"
}
}
}
}
}
],
"numItems": 1,
"hasMoreItems": false,
"totalNumItems": 1
}
Example 6
The *
wildcard can also be used instead of a specific index within a list. Thus, the condition will be checked for each list entry. Furthermore, full-text search with CONTAINS is possible in case of string sub-values.
SELECT appBibjsonsample:bibjson.title FROM appBibjsonsample:medium WHERE appBibjsonsample:bibjson.author[*].name CONTAINS('Sturz')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"objects": [
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"title": "My Book Title"
}
}
}
}
],
"numItems": 1,
"hasMoreItems": false,
"totalNumItems": 1
}
Example 7
Use ..
in order to replace unknown parts of a path. The query below specifies a search for objects where the appBibjsonsample:bibjson
property contains Schuetzel
in the value for the author[*].name
key which can be located at any hierarchical level within the JSON. Furthermore, only key-value mappings for keys named id will be displayed in the response body.
SELECT appBibjsonsample:bibjson..id FROM appBibjsonsample:medium WHERE appBibjsonsample:bibjson..author[*].name CONTAINS('Schuetzel')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"objects": [
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"id": "ID_of_book",
"identifier": [
{
"id": "0002-9327"
}
]
}
}
}
},
{
"properties": {
"appBibjsonsample:bibjson": {
"value": {
"metadata": {
"id": "ID_of_collection"
},
"records": [
{
"id": "ID_of_schema_article"
},
{
"id": "ID_of_query_article"
}
]
}
}
}
}
],
"numItems": 2,
"hasMoreItems": false,
"totalNumItems": 2
}
3.11.6. Summary
The structureddata
property type allows for the storage of interleaved data structures in a queryable way without defining each single sub-property in the schema. This tutorial gave some explanations on how to define such a property in the schema, how to set a value during object creation and how to address the individual sub-values in search queries, in the example context of a library.
Code examples in GitHub.
3.12. Overwriting the 'required' Property Attribute
This tutorial shows how to reference the same property definition in different object type definitions, in some of them as a required property and in others as a non-required property.
3.12.1. Introduction
The metadata structure of object types has to be defined in the schema. In this definition, properties are referenced that should be connected to the object type. Each property is in turn defined in the schema by the specification of its attributes. The properties can be referenced or not referenced in object type definitions, but their attributes are fixed and cannot be modified. The required attribute is the only exception as it can be overwritten by a propertyReference in object type definitions. This makes it possible to decide for each property individually whether it is required in every single object type definition or not. Since schema structures can even be changed at runtime, yuuvis® Momentum offers a high flexibility in terms of document lifecycle management.
3.12.2. Requirements
To work through this tutorial, the following is required:
-
Set-up yuuvis® Momentum system (see Installation Guide)
-
A user with read and write permissions on a document type in the system (see Access Management)
3.12.3. Overwriting the 'required' Attribute of Properties
All property definitions in the schema need the specification of the required attribute. Its boolean value decides if the corresponding property is mandatory (true
) or optional (false
) for an object. However, the value of the required attribute can be overwritten by a propertyReference
in object type definitions.
Property Definition
In an import management system, documents may be imported with less properties than they will have lateron in their lifecycle. A freshly imported object for example does not necessarily have an editor. Later in the document lifecycle, this information may be required. By overwriting the required attribute of the editor property, it is possible to use the same property throughout the entire lifecycle.
In the example code below, the editor
property is defined. The required attribute of the editor
property is set to true
. If not overwritten by a propertyReference
, the editor
property will be mandatory for any object of a type containing the editor
property in its definition.
1
2
3
4
5
6
<propertyStringDefinition>
<id>editor</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
Overwriting Using a Document Type Definition
In a document type definition, a propertyReference
can be used to set a value for the required
attribute of a property. This value can be different from the value specified in the property definition. In this case, the value of the required
attribute will be specified in the document type definition.
Since the editor
property should be optional for an imported1
document, the required attribute is set to false by means of a propertyReference
.
1
2
3
4
5
6
7
8
9
10
11
12
13
<propertyStringDefinition>
<id>editor</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<typeDocumentDefinition>
<id>imported1</id>
<baseId>system:document</baseId>
<propertyReference required="false">editor</propertyReference>
<contentStreamAllowed>allowed</contentStreamAllowed>
</typeDocumentDefinition>
Overwriting Using a Secondary Object Type Definition
An alternative option to reference a property in an object type definition is to include a floating secondary object type. In the secondary object type definition, a propertyReference
can be used to set a value for the required attribute for a property. The required
attribute value specified in the original property definition is again overwritten.
In the example code below, the editor
property is not included directly in the imported2
document type definition. But it is based on the non-static (floating) secondary object type noeditor
. The definition of noeditor
uses the editor
property and sets its required
attribute to false
by means of a propertyReference
. Thus, for documents of the type imported2
, the editor
property will be available and optional.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<propertyStringDefinition>
<id>editor</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<typeDocumentDefinition>
<id>imported2</id>
<baseId>system:document</baseId>
<contentStreamAllowed>allowed</contentStreamAllowed>
<secondaryObjectTypeId static="false">noeditor</secondaryObjectTypeId>
</typeDocumentDefinition>
<typeSecondaryDefinition>
<id>noeditor</id>
<baseId>system:secondary</baseId>
<propertyReference required="false">editor</propertyReference>
</typeSecondaryDefinition>
Handling Multiple Property References
In a document type definition, it is possible to set a value for the required
attribute of a property, and additionally include multiple secondary object types specifying the required
attribute for the same property as well. If at least one definition implies required=true
, this attribute will be true
for every document of the corresponding type. The value true
dominates over false
regardless of the location of the propertyReference
.
In the example code below, a document type imported3
is defined. The editor
property is included, but the required
attribute is overwritten to false which makes the editor
property optional. However, the two secondary object types noeditor
and witheditor
may have different values specified for the required
attribute of the editor
property.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<propertyStringDefinition>
<id>editor</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<typeDocumentDefinition>
<id>imported3</id>
<baseId>system:document</baseId>
<propertyReference required="false">editor</propertyReference>
<contentStreamAllowed>allowed</contentStreamAllowed>
<secondaryObjectTypeId static="false">noeditor</secondaryObjectTypeId>
<secondaryObjectTypeId static="false">witheditor</secondaryObjectTypeId>
</typeDocumentDefinition>
<typeSecondaryDefinition>
<id>noeditor</id>
<baseId>system:secondary</baseId>
<propertyReference required="false">editor</propertyReference>
</typeSecondaryDefinition>
<typeSecondaryDefinition>
<id>witheditor</id>
<baseId>system:secondary</baseId>
<propertyReference>editor</propertyReference>
</typeSecondaryDefinition>
The definition of the secondary object type noeditor
overwrites the required
attribute of the editor
property to false
. This value equals the specification in the imported3
document type definition. In contrast, the definition of witheditor
includes the editor
property by means of a propertyReference
but does not explicitly specify a value for the required
attribute. This means that the value true
from the property definition will be used for witheditor
.
-
If a document of type
imported3
has none of the two secondary object types, theeditor
property is optional. -
If a document of type
imported3
has the secondary object typenoeditor
, nothing changes. Theeditor
property is still optional. -
But if a document of type
imported3
has the secondary object typewitheditor
, the property editor is mandatory in this object.
3.12.4. Summary
This tutorial gave an introduction into the possibilities provided by the option of overwriting the required
attribute of properties. Since this topic plays a role in the handling of the schema, also the following pages might be interesting to you.
3.13. Preprocessing Metadata using Webhooks
An example Webhook consumer service set up using Java and Spring Boot.
3.13.1. Requirements
In this tutorial, we’ll create a Spring Boot Service using Java, meaning the requirements for the project are derived from Spring Boot. Thus, a JDK version 1.8 or later and Maven 3.2 or later are required.
3.13.2. Setting up the Consumer Service
To implement processing of incoming update metadata using our webhook service, we need to configure an endpoint within a controller class of our Example Webhook Service, in this instance ExampleRestController. The URL we define between the RequestMapping annotation of the controller class and the PostMapping annotation of the endpoint method will need to find its way into the system hook configuration of our yuuvis® Momentum system. We will also define a stub method for working with the incoming metadata, which we will call from within our endpoint method, the object map provided by the system hook.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
@RequestMapping("/api/dms/request")
public class ExampleRestController
{
@PostMapping(value = "/update/metadata", produces = {"application/json"})
public Map<String, Object> updateDmsObjectMetadata(@RequestBody Map<String, Object> dmsApiObjectList,
@RequestHeader(value = "Authorization", required = true) String authorization)
{
doSomething(dmsApiObjectList, authorization);
return dmsApiObjectList;
}
private void doSomething(Map<String, Object> dmsApiObjectList, String authorization)
{
// do something with the metadata
}
}
3.13.3. Configuring the Webhook
To use the webhook service for the intended purpose of intercepting metadata when updating objects, we need to create a new entry in the Webhook list within our systems' systemHookConfiguration.json
file (`\system\systemHookConfiguration.json). The url attribute must refer to the webhook service identifier (derived from the artifact ID in the services' maven file) and direct to one of the endpoints declared in the service.
The services responsible for the webhook execution need to be restarted after changing the systemHookConfiguration.json
file. The corresponding services of each webhook are listed here. For the enrichment of metadata, the pertaining service would be the API-gateway.
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"systemhooks": {
"webhooks": [
{
"enable": true,
"predicate": "spel:true",
"type": "dms.request.update.metadata",
"url": "<protocol>://<webhook service identifier>/api/dms/request/update/metadata",
"useDiscovery": true
}
]
}
}
3.13.4. Summary
In this tutorial, a Java-based method for webhook consumption is outlined. The code presented, including the project structure and additional webhook management, can be found in github. More concrete example webhook use cases are described in the articles linked below.
3.14. Accessing Binary Content during an Import
Access binary content files via webhooks during the import process.
3.14.1. Introduction
If an object is imported to yuuvis® Momentum, a binary content file can be assigned in addition to the object’s metadata. The storage of the binary content file is managed by the repository
service. Afterwards, the metadata are stored in a separate database and are indexed for search.
As soon as the object import process is finished, the binary content file can be accessed. Especially, it can be analysed in order to set some content-related metadata properties for the corresponding object. The metadata update is possible, i.e., via POST or PATCH /api/dms/objects/{objectId}
and triggers the creation of a new object version. However, in some use cases, it might be necessary to set metadata properties depending on an analysis of the corresponding binary content file already for the first version of the imported object. For this purpose, the binary content file can be accessed from a webhook that is called after storing the content and before storing the metadata. This tutorial describes an example solution using an internal endpoint of the repository
service.
3.14.2. Setting up the Webhook Service
The webhook entry point has to be located after storing the binary content file and before storing the metadata in the process chain of an object import. For this purpose, the type dms.request.objects.upsert.database-before
is suitable.
The Preprocessing Metadata using Webhooks tutorial provides a general example on how to configure and set up your own webhook service. A more specific example controller class for a webhook service for our concrete use case is provided in the code block below. For each object imported with a binary content file, the MD5 digest of the corresponding content is calculated. Since an internal endpoint of the repository
service has to be called, the webhook service must run within the yuuvis® Momentum Kubernetes cluster.
As defined in lines 2 and 5, the webhook service will be available via the URL /api/process/checkcontent
. This endpoint accepts the import request body containing all of the objects' metadata, and the request headers (line 6).
Especially in the case of a batch import, it is necessary to iterate over the individual objects (line 13) as the repository can only retrieve the content of one object at a time. For each individual object, the existence of an assigned binary content file is checked (lines 17 and 19). The binary content file is retrieved from the repository (starting in line 28) and its MD5 digest is calculated (line 47). The value is printed to the console (line 55).
Depending on the MD5 digest value, it would be possible to manipulate the individual object’s metadata. However, in this example, the metadata remain unchanged. The objects from the request body are returned without any manipulation (line 66).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@RestController
@RequestMapping("/api")
public class WebhookRestController
{
@PostMapping(value = "/process/checkcontent", produces = "application/json;charset=UTF-8", consumes = "application/json")
public ResponseEntity<?> checkContent(@RequestBody final Map<String, Object> dmsApiObList, @RequestHeader HttpHeaders incomingHeaders) throws Exception
{
try
{
String authorization = incomingHeaders.getFirst(HttpHeaders.AUTHORIZATION);
List<Map<String, Object>> apiObjectList = (List<Map<String, Object>>)dmsApiObList.get("objects");
for (Map<String, Object> apiObject : apiObjectList)
{
String objectId = (String)getMap(getMap(apiObject, "properties"), "system:objectId").get("value");
boolean hasContent = apiObject.get("contentStreams") != null && ((List)apiObject.get("contentStreams")).size() > 0;
if (hasContent)
{
Map<String, Object> requestObject = new LinkedHashMap<>();
LinkedList<Map<String, Object>> requestList = new LinkedList<>();
requestList.add(apiObject);
requestObject.put("objects", requestList);
// @formatter:off
String md5Digest =
restTemplate.execute(
"http://repository/api/dms/objects/" + objectId,
HttpMethod.POST,
(ClientHttpRequest requestCallback) -> {
if (StringUtils.hasLength(authorization))
{
requestCallback.getHeaders().add(HttpHeaders.AUTHORIZATION, authorization);
}
requestCallback.getHeaders().setContentType(MediaType.APPLICATION_JSON);
requestCallback.getBody().write(this.objectMapper.writeValueAsString(requestObject).getBytes("UTF-8"));
},
new ResponseExtractor<String>()
{
@Override
public String extractData(ClientHttpResponse response) throws IOException
{
if (response.getStatusCode().is2xxSuccessful())
{
// calculate MD5 Hash
return DigestUtils.md5DigestAsHex(response.getBody());
}
throw new IllegalStateException("error in getting content: " + response.getRawStatusCode() + " " + response.getStatusText());
}
}
);
// @formatter:on
System.out.println("for objectId[" + objectId + "] the md5-digest of content is[" + md5Digest + "]");
}
}
}
catch (Throwable e)
{
return new ResponseEntity<>(e.getMessage(), HttpStatus.UNPROCESSABLE_ENTITY);
}
// just return input no changes
return new ResponseEntity<Map<String, Object>>(dmsApiObList, HttpStatus.OK);
}
}
3.15. Handling PDF Compound Documents via Interceptors
Learn how to set up a Microservice that can fill the role of an interceptor of any of the available interceptor types. Java code examples of such microservices can also be found here.
3.15.1. Basic Microservice Setup
In this tutorial, we will implement a Spring Boot microservice for the interceptors' obligations that can easily be integrated into the yuuvis® Momentum infrastructure (kubernetes). Learn more about Spring Boot Applications in their official documentation. To integrate with kubernetes, some additional application files need to be implemented in the microservice.
One nice thing about microservices is that you can use any programming language you like—as long as it supports REST which ensures communication with the other services. |
Necessary Microservice Application Files
In this tutorials' code project, we implement some of our suggestions for the architecture of yuuvis® Momentum-integrated microservice. The following classes provide no logic specific to interceptors, but are still essential for the microservice to operate.
-
src/main/java/com/os/services/interceptor/ExampleInterceptorApplication.java
- Runs the application. The annotation@SpringBootApplication
tells Spring Boot to run the application in an embedded Tomcat. -
src/main/java/com/os/services/interceptor/config/DefaultServicesResponseEntityExceptionHandler.java
- Error Handling suggestion. -
src/main/java/com/os/services/interceptor/config/InterceptorConfiguration.java
- Creates a REST template.
3.15.2. Functional Implementation of each Interceptor Type
In the following sections, an arbitrary practical example for each of the three interceptor types is provided for demonstrational purposes. At the end of the article, you will find a link to the Git Repository that houses the complete code project for your inspiration.
Type 'getContent'
Imagine the following situation: A large PDF file consisting of several sub-documents is stored in the system. When one specific document is requested, the respective pages should be extracted and returned as a separate PDF file. A good way to achieve this is using an interceptor, i.e., a service that runs in the background listening for its cue. When it occurs, the interceptor is called by the yuuvis® API system and performs its specific task, thereby rerouting the standard flow of the application.
Creating the 'getContent' REST Controller
Finally, we will need to create a REST endpoint to the service. A REST controller class will handle HTTP requests, producing the REST endpoint.
A traditional MVC controller and a RESTful web service controller in Spring differ significantly regarding the creation of the HTTP response body: In the traditional Model View Controller (MVC) paradigm, the controller would use a view technology in order to render an HTML version of the data and return a view object to be displayed. In Spring, however, the controller creates and returns a new instance of the resource representation class instead which will be written to the HTTP response as JSON. |
Create the class PdfPageSelectorRestController
and annotate it as @RestController
. This will turn the class into a REST controller whose methods return domain objects instead of views (short for @Controller
and @ResponseBody
).
@RestController
@RequestMapping("/api")
public class PdfPageSelectorRestController
{
@Autowired
private PdfPageSelectorService pdfPageSelectorService;
@PostMapping(value = "/dms/objects/{objectId}", headers = "content-type=application/json")
public void getContentByPostRequest(@RequestBody Map<String, Object> dmsApiObjectList, @PathVariable("objectId") String objectId,
@RequestHeader(value = "Authorization", required =false) String authorization,
HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException
{
servletResponse.setContentType(MediaType.APPLICATION_PDF_VALUE);
pdfPageSelectorService.extract(servletResponse.getOutputStream(), dmsApiObjectList, objectId, authorization);
}
}
The controller sets the media type of response to PDF and calls the extract
method of the PDFPageSelectorService
.
Modelling a Sub-Document
As a document is identified by its start and end page, the domain object simply represents these two page numbers.
public class Pages
{
private int startPage;
private int endPage;
public Pages(int startPage, int endPage)
{
this.startPage = startPage;
this.endPage = endPage;
}
//omitted getter/setter methods
}
Creating the Page Extractor
This is the core of the service. Create the class PdfPageSelectorService
and annotate it as @Service
. This indicates that it holds the business logic and will communicate with the repository layer.
The extract
method first gets the page boundaries, i.e., start and end page numbers, from the input by simply removing the page:
prefix and splitting the string at the -
character:
if (range.startsWith("page:"))
{
((Map<String, Object>)contentSreamObject.get(0)).remove("range");
String[] bounds = range.substring("page:".length()).split("-");
int startPage = Integer.parseInt(bounds[0]);
int endPage = Integer.parseInt(bounds[1]);
return new Pages(startPage, endPage);
}
Next, it calls the repository via the REST template and sends a POST request with all object data.
restTemplate.execute(repositoryUrl + "/" + objectId, HttpMethod.POST, (ClientHttpRequest requestCallback) ->
{
if (StringUtils.hasLength(authorization))
{
// delegate auth header
requestCallback.getHeaders().add(HttpHeaders.AUTHORIZATION, authorization);
}
requestCallback.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_PDF));
requestCallback.getHeaders().setContentType(MediaType.APPLICATION_JSON);
requestCallback.getBody().write(this.objectMapper.writeValueAsString(requestObjects).getBytes("UTF-8"));
},
new StreamResponseExtractor(outputStream, pages.getStartPage(), pages.getEndPage()));
Extracting Content from a PDF
The StreamResponseExtractor
then extracts the pages of the sub-document from the streamed PDF (using PDFBox) and writes them to a new PDF file. The PDFBox functionality is wrapped in the PdfTools
helper class.
The advantage of streaming is that large files do not need to be copied first but can be handled on the fly. This is not required though: You could just as well get the file from the repository first and store it locally before processing.
public static void extractPageFromStream(InputStream inputStream, int startPage, int endPage, OutputStream outputStream)
{
try
{
Splitter splitter = new Splitter();
splitter.setStartPage(startPage);
splitter.setEndPage(endPage);
splitter.setSplitAtPage(endPage - startPage + 1);
try (PDDocument document = PDDocument.load(inputStream))
{
List<PDDocument> documents = splitter.split(document);
if (documents.size() != 1)
{
throw new IllegalArgumentException("cannot split document, wrong number of split parts");
}
try (PDDocument doc = documents.get(0))
{
PdfTools.writeDocument(doc, outputStream);
}
}
}
catch (Exception e)
{
LOGGER.info(ExceptionUtils.getMessage(e));
throw new IllegalArgumentException(ExceptionUtils.getMessage(e));
}
}
private static void writeDocument(PDDocument doc, OutputStream outputStream) throws IOException
{
try (COSWriter writer = new COSWriter(outputStream))
{
writer.write(doc);
}
}
Interceptor 'getContent' Configuration
Create the interceptorConfiguration.json
file, add the following configuration (either JavaScript or SpEL) and save it to the configuration server, either by updating the git repository with the new state, or, in systems running the 'native' profile on the config service, simply changing the configuration file in the file-system of the config service itself.
You only need one configuration—whether you prefer JavaScript or SpEL is up to you. |
When configuring a getContent interceptor, we can infer the objects' metadata from the predicate.
{
"interceptors" : [
{
"type" : "getContent",
"predicate" : "js:function process(dmsApiObject){return dmsApiObject[\"contentStreams\"][0][\"range\"]!=null && dmsApiObject[\"contentStreams\"][0][\"range\"].startsWith(\"page:\")}",
"url" : "http://examplewebhook/api/dms/objects/{system:objectId}",
"useDiscovery" : false
}
]
}
{
"interceptors" : [
{
"type" : "getContent",
"predicate" : "spel:contentStreams[0]['range'] != null ? contentStreams[0]['range'] matches '(?i)^page:.*' : false",
"url" : "http://examplewebhook/api/dms/objects/{system:objectId}",
"useDiscovery" : false
}
]
}
Finally, restart the API Service to apply the new configuration to the system.
Type 'search'
Whenever we need to handle documents containing critical information during their development within a content management system, we need to ensure that the accessibility of such documents is restricted for all users without a specific authorization for those documents. To implement such a mechanism in our yuuvis® system, we can make use of the search interceptor type together with a system tag that will need to be set on all documents.
Creating the search REST Controller
The REST controller offering the endpoint for the interceptor mechanism follows in the footsteps of the PdfPageSelectorRestController
, barring the absence of the objectId
in the URL and the changed response content type.
@RestController
@RequestMapping("/api")
public class QueryByTagFilterRestController {
@Autowired
private QueryFilterService queryFilterService;
@PostMapping(value = "/dms/objects/search", headers = "content-type=application/json")
public void searchByPostedQuery(@RequestBody Map<String, Object> incomingQuery,
@RequestHeader(value = "Authorization", required = false) String auth,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) throws IOException {
servletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
queryFilterService.filterQueryByTag(servletResponse.getOutputStream(), incomingQuery, auth);
}
}
Enriching an Incoming Query Object
public Map<String, Object> enrichQueryByTagFilter(Map<String, Object> incomingQuery){
Map<String, Object> queryMap = (Map<String, Object>)incomingQuery.get("query");
String statement = String.valueOf(queryMap.get("statement"));
String filteredStatement = "";
if (statement.contains("WHERE")){
filteredStatement = statement + " AND system:tags[\"test\"].state > 1";
} else {
filteredStatement = statement + " WHERE system:tags[\"test\"].state > 1";
}
queryMap.replace("statement", filteredStatement);
incomingQuery.replace("query", queryMap);
return incomingQuery;
}
Essentially, we will enrich each incoming query from less authorized users on the search service using the interceptor, adding a filtering statement excluding documents where the state of our test tag does not indicate the information can be released systemwide. This means the documents we would want to exclude from the users' visibility need to have the test
tag with a state value lower than 3. Increasing the state beyond this number will result in the filter to no longer apply, thereby making the document public
to all users affected by the interceptor predicate. Please be aware that this Interceptor configuration may break more complex queries, such as those ordering results at the end of the statement, due to out of place WHERE
clauses.
Interceptor 'search' Configuration
Search interceptors receive a JSON denoting the querying users' authorization details, including the granted permissions/roles of the user.
{
"type" : "search",
"predicate" : "spel:!grantedAuthorities.contains('SOME_NEEDED_ROLE')",
"url" : "http://exampleinterceptor/api/dms/objects/search",
"useDiscovery" : true
}
Type 'updateDmsObject'
The last of the available interceptor types enters the stage whenever anyone tries to update an object matching the predicate declared in the interceptor configuration. The Interceptor can modify the incoming update metadata, while also having access to the current version of the object’s metadata.
Creating the 'updateDmsObject' REST Controller
Again, the Rest Controller class will not diverge much from the previous two interceptor types, keeping the object ID path variable of the getContent type and the JSON Request Content Type parameter of the search interceptor type.
@RestController
@RequestMapping("/api")
public class UpdateEnricherRestController {
@Autowired
private UpdateEnricherService updateEnricherService;
@PostMapping(value = "/dms/objects/{objectId}/update", headers = "content-type=application/json")
public void enrichedUpdate(@RequestBody Map<String, Object> dmsApiObjectList,
@PathVariable("objectId") String objectId,
@RequestHeader(value = "Authorization", required = false) String auth,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse) throws IOException {
servletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
updateEnricherService.enrichMetadata(servletResponse.getOutputStream(), dmsApiObjectList, objectId, auth);
}
}
Manipulating Incoming Metadata
We can use our interceptor, for instance, to increment a property tracking the amount of edits of a certain property commited on an object. We can modify the incoming update metadata within the interceptor service to implement this logic in a very flexible manner, allowing for complex interactions with tertiary systems for the metadata enrichment.
public Map<String, Object> enrichMetadataTag(Map<String, Object> incomingMetadata){
List<Map<String, Object>> list = (List<Map<String, Object>>)incomingMetadata.get("objects");
Map<String, Object> dmsApiObject = list.get(0);
Map<String, Object> propertyMap = (Map<String, Object>)dmsApiObject.get("properties");
Map<String, Object> testStringMap = (Map<String, Object>)propertyMap.get("appInterceptor:testString1");
String oldValue = testStringMap.get("value").toString();
testStringMap.replace("value", (oldValue+ " (enriched value)"));
return incomingMetadata;
}
In this demonstration, we opt to enrich a metadata property value present in the body of the update request. We assume that the update already tries to modify the value. That way we can obtain the proposed new value for the property from the propertyMap
within the incomingMetadata
object. If we wanted to modify this value even if it was not present in the update body, we simply need to inject the property into the same property map, as it will be treated as overwriting metadata when forwarding the enriched metadata to the repository service in the next step.
Interceptor 'updateDmsObject' Configuration
Similarly to the getContent
interceptor type, the updateDmsObject
interceptor predicates are based on the current version of the objects' metadata. We use the predicate to verify the document that is meant to be updated is of the specific object type handled by our interceptor.
{
"type" : "updateDmsObject",
"predicate" : spel:contentStreams != null && contentStreams.size() > 0 && properties['system:objectTypeId'] == "appInterceptor:exampleDoc",
"url" : "http://exampleinterceptor/api/dms/objects/{system:objectId}/update",
"useDiscovery" : true
}
3.15.3. Summary
Your service is complete! Find the complete code project described in this tutorial in this GitHub Repository.
4. Client Development
The following services, APIs and libraries can be installed in addition to the core system. They allow to quickly build your own client application. An example client as reference implementation is available as well.
4.1. Web API
The Web API gateway is a collection of endpoints provided by the api-web
service. It provides:
-
The core system’s DMS functionality in a different format
-
client-specific resources management (forms, localization, icons, catalogs, …)
-
Integration possibilities for Business Process Management via
bpm-engine
service -
User information retrieval from a specific database via
userservice
-
User information retrieval from the used identity provider via
tenant-management
service
4.1.1. Endpoints
admin-controller
GET /api-web/api/admin/dms/catalogs
- Retrieve the names of all catalogs available within the tenant.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves the technical names of all catalogs grouped in lists depending on their global, app-specific or tenant-specific storage location.
Tenant-specific catalogs are retrieved only for the active tenant.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
500
Internal Server Error
- Request Example
-
https://<host>/api-web/api/admin/dms/catalogs
no request body
- Response Example
-
200 OK
Response Body{ "personalfile": [ "appPersonalfile:class" ], "global": [ "germancountry", "contracts", "germancountries", "globalnotice", "currency", "class", "clubs", "food", ], "invoice": [ "appInvoice:type" ], "mytenant": [ "germancountry", "contracts", "tenMytenant:My catalog", "germancountries", "globalnotice", "currency", "class", "appInvoice:type", "tenMytenant:processstatus", "appPersonalfile:class" ] }
GET /api-web/api/admin/dms/catalogs/{qname}
- Retrieve a specified catalog.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves the catalog specified by its technical name of either global/app-specific or tenant-specific origin.
Behind the technical name, add the query parameter
global=false
(global=true
) for a tenant-specific (app-specific or global) catalog. The endpoint returns null if no catalog with qname is available in the tenant-specific (app-specific or global) resource.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
401
Unauthorized
404
Not Found
- Request Example
-
https://<host>/api-web/api/admin/dms/catalogs/appInvoice:type?global=true
no request body
- Response Example
-
200 OK
Response Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
POST /api-web/api/admin/dms/catalogs/{qname}
- Create or replace a specified catalog.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Updates the catalog specified by its technical name within the tenant-specific resources.
The new catalog data are passed in the JSON request body.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
- Request Example
-
https://<host>/api-web/api/admin/dms/catalogs/tenMytenant:processstatus
Request Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
- Response Example
-
200 OK
Response Body{ "errors": [], "valid": true }
PATCH /api-web/api/admin/dms/catalogs/{qname}
- Update a specified catalog.
- As of Version
-
2021 Summer
- Request Method
-
PATCH
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Updates the existing tenant-specific catalog identified by its name qname, with the data passed in JSON format in the request body.
In the response body, the modified catalog will be returned.
If no tenant-specific catalog with name qname is available, an error will be thrown.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
404
Not Found
500
Internal Server Error
- Request Example
-
https://<host>/api-web/api/admin/dms/catalogs/tenMytenant:contracts
Request Body[ { "op": "replace", "path": "/entries/1/name", "value": "Rental agreement" }, { "op": "remove", "path": "/entries/3" }, { "op": "add", "path": "/entries/-", "value": { "name": "Purchase contract", "disabled": true } } ]
- Response Example
-
200 OK
Response Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
deprecated as of 2023 Winter: GET /api-web/api/admin/dms/forms/{objecttype}
- Retrieve a non-enriched metadata form for a specified object type.
Deprecated as of 2023 Winter. Please use GET /api-web/api/resources/forms/{type} .
|
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the non-enriched form by object type ID
objecttype
and optional query parameterssituation
andsots
(secondary object types) for the active tenant.Behind the object type ID, add the query parameter
situation=CREATE
(situation=EDIT
) to retrieve the CREATE (EDIT) form. Default is EDIT. Furthermore, addsots=<objectTypeId>
in order to specify a secondary object type of which properties should be included in the retrieved form. Thesots
query parameter can be added multiple times for different secondary object types.Returns
null
if there is no designed form model for the given object type.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/admin/dms/forms/tenMytenant:qadocscripts?situation=EDIT&sots=examplesot1&sot=examplesot2
no request body
- Response Example
-
200 OK
Response Body{ "name": "tenMytenant:qadocscripts", "situation": "EDIT", "script": "any valid script", "elements": [ { "name": "core", "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "name": "appClient:clienttitle", "type": "string", "rows": 1 }, { "name": "appClient:clientdescription", "type": "string", "rows": 1 } ] }, { "name": "data", "type": "o2mGroupStack", "elements": [ { "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:strsingle", "type": "string", "rows": 1 }, { "name": "tenMytenant:strsinglemail", "type": "string", "rows": 1 } ] }, { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:intsingle", "type": "integer" }, { "name": "tenMytenant:intsingledigit", "type": "integer" } ] } ] } ] } ] } ] }
deprecated as of 2023 Winter: POST /api-web/api/admin/dms/forms/{objecttype}
- Create or update a non-enriched metadata form for a specified object type.
Deprecated as of 2023 Winter. Please use POST /api-web/api/resources/forms/{type} .
|
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves the non-enriched form by object type ID
objecttype
and optional query parameterssituation
andsots
(secondary object types) for the active tenant.Behind the object type ID, add the query parameter
situation=CREATE
(situation=EDIT
) to retrieve the CREATE (EDIT) form. Default is EDIT. Furthermore, addsots=<objectTypeId>
in order to specify a secondary object type of which properties should be included in the retrieved form. Thesots
query parameter can be added multiple times for different secondary object types.Returns
null
if there is no designed form model for the given object type.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/admin/dms/forms/tenMytenant:qadocscripts?situation=EDIT&sots=examplesot1&sot=examplesot2
no request body
- Response Example
-
200 OK
Response Body{ "name": "tenMytenant:qadocscripts", "situation": "EDIT", "script": "any valid script", "elements": [ { "name": "core", "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "name": "appClient:clienttitle", "type": "string", "rows": 1 }, { "name": "appClient:clientdescription", "type": "string", "rows": 1 } ] }, { "name": "data", "type": "o2mGroupStack", "elements": [ { "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:strsingle", "type": "string", "rows": 1 }, { "name": "tenMytenant:strsinglemail", "type": "string", "rows": 1 } ] }, { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:intsingle", "type": "integer" }, { "name": "tenMytenant:intsingledigit", "type": "integer" } ] } ] } ] } ] } ] }
deprecated as of 2023 Winter: GET /api-web/api/admin/resources/config/{name}
- Retrieve a specified tenant-specific configuration file.
Deprecated as of 2023 Winter. Please use GET /api-web/api/resources/config/{name} .
|
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves the tenant-specific configuration file specified by
name
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
deprecated as of 2023 Winter: POST /api-web/api/admin/resources/config/{name}
- Create or update a specified tenant-specific configuration file.
Deprecated as of 2023 Winter. Please use POST /api-web/api/resources/config/{name} .
|
- As of Version
-
2020 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Creates or updates the tenant-specific configuration file specified by
name
with the data passed in JSON format in the request body.Response HTTP status codes:
HTTP status code Meaning 201
CREATED
401
Unauthorized
deprecated as of 2023 Winter: GET /api-web/api/admin/icons/{path}
- Retrieve a specified tenant-specific icon.
Deprecated as of 2023 Winter. Please use GET /api-web/api/resources/icons/{path} .
|
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
SVG
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves a tenant-specific icon resource specified by
path
as SVG image.Such icon endpoints are also available in the resource-controller and system-controller. They are intended to serve for the configuration of object type icons. Use the technical name of the corresponding object type as value for
path
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
deprecated as of 2023 Winter: POST /api-web/api/admin/icons/{path}
- Create or update a specified tenant-specific icon.
Deprecated as of 2023 Winter. Please use POST /api-web/api/resources/icons/{type} .
|
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Creates or updates the tenant-specific icon specified by path with the data passed as SVG image in a multipart request body.
Such icon endpoints are also available in the resource-controller and system-controller. They are intended to serve for the configuration of object type icons. Use the technical name of the corresponding object type as value for path, e.g.
tenMytenant:invoice
orappMyapp:contract
.Response HTTP status codes:
HTTP status code Meaning 201
CREATED
400
No icon was specified.
401
Unauthorized
deprecated as of 2023 Winter: GET /api-web/api/admin/resources/text
- Retrieve the tenant-specific localized text resources for a specified locale.
Deprecated as of 2023 Winter. Please use GET /api-web/api/resources/text .
|
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves tenant-specific localized text resources for the
Accept-Language
specified in the request header formatted in ISO norm (e.g.,de
,en
,es
,fr
, …)The response body is a JSON structure where each technical term as a key is mapped to a string value that will occur as a localized term in the graphical user interface.
Each technical term consists of a field identification (e.g.,
twosteptest_proc:test_table
) followed by either_label
or_description
in order to be displayed as field label or field description in the graphical user interface.If a technical term is mapped to null, localization has not yet been applied. The field identification will be displayed as field label in the graphical user interface. A description will not be provided.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/admin/resources/text
no request body
- Response Example
-
200 OK
Response Body{ "tenExample:betreff_label": "Subject", "tenExample:betreff_description": null, "tenExample:strsingle_label": "String", "tenExample:strsingle_description": "unlimited", "tenExample:strregextime_label": "Time", "tenExample:strregextime_description": "Time format is 24 hours with hh:mm", "tenExample:strcataloggermancountries_label": "German countries", "tenExample:strcataloggermancountries_description": "single-field", "tenExample:strcataloggermancountriesro_label": "German countries", "tenExample:strcataloggermancountriesro_description": "single-field, read-only", "tenExample:intsingle_label": "Integer", "tenExample:intsingle_description": "unlimited", "tenExample:intsingledigit_label": "Integer", "tenExample:intsingledigit_description": "digit grouping", "tenExample:decsingle_label": "Decimal", "tenExample:decsingle_description": "unlimited", "tenExample:decsingledigit_label": "Decimal", "tenExample:decsingledigit_description": "digit grouping", "tenExample:datetimesingle_label": "Date & time", "tenExample:datetimesingle_description": "unlimited", "tenExample:datetimesinglerequired_label": "Date & time", "tenExample:datetimesinglerequired_description": "mandatory", "tenExample:datesingle_label": "Date2", "tenExample:datesingle_description": "unlimited", "tenExample:datesinglerequired_label": "Date1", "tenExample:datesinglerequired_description": "mandatory", "tenExample:booleanrequiredtrue_label": "Boolean", "tenExample:booleanrequiredtrue_description": "mandatory", "tenExample:booleannull_label": "Boolean Tri-State", "tenExample:booleannull_description": "Null allowed", "tenExample:extract2_label": "Extract & map", "tenExample:tablesimplefields_label": "Simple fields", "tenExample:tablesimplefields_description": "Table with simple fields", "tenExample:tableclassifications_label": "Fields with classifications", "tenExample:tableclassifications_description": "Table with classification fields", "tenExample:strorganizationsingle_label": "User/Group", "tenExample:strorganizationmulti_label": "Users/Groups", "tenExample:strcatalogfruitsmulti_label": "Fruits", "tenExample:strcatalogfruitmulti_description": "Apple,Banana,Pear,Plum,Pineapple (multi)", "tenExample:tablenotice_label": "Notice", "tenExample:tablecreatedate_label": "Date", "tenExample:tableuser_label": "User", "tenExample:tablereadonly_label": "Write protection", "tenExample:tablenumber_label": "Number", "tenExample:tablenumberdigit_label": "Digit-number", "tenExample:tabledistance_label": "Distance", "tenExample:tabledistancedigit_label": "Digit-distance", "tenExample:tablecreatedatetime_label": "Datetime", "tenExample:tableemail_label": "Email", "tenExample:tableurl_label": "URL", "tenExample:tablephone_label": "Phone", "tenExample:tablecatalog_label": "Catalog", "tenExample:tablereference_label": "Reference", "tenExample:simpleFields_label": "Simple Fields", "tenExample:classifications_label": "Classifications", "tenExample:number_label": "Number", "tenExample:number_description": "Will be filled via script", "tenExample:createdate_label": "Created", "tenExample:createdate_description": "Will be filled via script as well", "tenExample:notice_label": "Notice", "tenExample:notice_description": "To be filled by user", "tenExample:probability_label": "Probability", "tenExample:probability_description": "To be filled by user as well", "tenExample:readonly_label": "Read-only", "tenExample:readonly_description": "It's still unclear who will do it ...", "tenExample:required_label": "Mandatory fields", "tenExample:notrequired_label": "Without obligation", "tenExample:tableGroup_label": "Table group", "tenExample:tableFilling_label": "Table filling", "tenExample:process_label": "Approval process", "tenExample:process:0_label": "Draft in work", "tenExample:process:1_label": "Draft in review", "tenExample:process:2_label": "Draft in rework", "tenExample:process:3_label": "Document ready", "tenExample:process:4_label": "Approved", "tenExample:process:5_label": "Rejected", "tenExample:datetimemulti_label": "Date & time ", "tenExample:datetimemulti_description": "unlimited", "tenExample:strcatalogfruitmulti_label": "Fruits", "tenExample:strcatalogfruitsmulti_description": "Apple,Banana,Pear,Plum,Pineapple (multi)", "tenExample:Table Group_label": "My group", "twosteptest_proc_label": "Two step process", "twosteptest_proc:2nd_task": "Second task", "twosteptest_proc:simplefields_label": "Simple fields", "twosteptest_proc:complexfields_label": "Complex fields", "twosteptest_proc:datetime_label": "Date & time", "twosteptest_proc:date_label": "Date only", "twosteptest_proc:boolean_label": "boolean", "twosteptest_proc:integer_label": "Integer", "twosteptest_proc:decimal_label": "Decimal", "twosteptest_proc:string_label": "String", "twosteptest_proc:stringmultirow_label": "Multi-row string ", "twosteptest_proc:email_label": "Email", "twosteptest_proc:phone_label": "Phone", "twosteptest_proc:url_label": "URL", "twosteptest_proc:user_label": "User", "twosteptest_proc:reference_label": "Reference", "twosteptest_proc:catalogcustom_label": "Custom catalog", "twosteptest_proc:test_table_label": "Notices", "twosteptest_proc:test_table_description": "List of notices", "twosteptest_proc:column_string_label": "Notice", "twosteptest_proc:column_date_label": "Date", "twosteptest_proc:column_user_label": "User", "twosteptest_proc:column_boolean_label": "Editable", "userGroupAssignment:user_label": "User", "userGroupAssignment:user_description": "Assign the user who should ...", "userGroupAssignment:comment_label": "Comment", "userGroupAssignment:comment_description": "Tell the user what to do .." }
deprecated as of 2023 Winter: POST /api-web/api/admin/resources/text/{locale}
- Create or update the tenant-specific localized text resources for the specified locale.
Deprecated as of 2023 Winter. Please use POST /api-web/api/resources/text/{locale} .
|
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Creates or updates the tenant-specific localized text resources for the active tenant and the specified
locale
formatted in ISO norm, e.g.,de
,en
,es
,fr
, ….The request body is a JSON structure where each technical term as a key is mapped to a string value that will occur as a localized term in the graphical user interface.
Each technical term consists of a field identification (e.g.,
twosteptest_proc:test_table
) followed by either_label
or_description
in order to be displayed as field label or field description in the graphical user interface.If a technical term is mapped to
null
, localization has not yet been applied. The field identification will be displayed as field label in the graphical user interface. A description will not be provided.Response HTTP status codes:
HTTP status code Meaning 201
CREATED
400
No text resources were specified.
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/admin/resources/text/en
Request Body{ "tenExample:betreff_label": "Subject", "tenExample:betreff_description": null, "tenExample:strsingle_label": "String", "tenExample:strsingle_description": "unlimited", "tenExample:strregextime_label": "Time", "tenExample:strregextime_description": "Time format is 24 hours with hh:mm", "tenExample:strcataloggermancountries_label": "German countries", "tenExample:strcataloggermancountries_description": "single-field", "tenExample:strcataloggermancountriesro_label": "German countries", "tenExample:strcataloggermancountriesro_description": "single-field, read-only", "tenExample:intsingle_label": "Integer", "tenExample:intsingle_description": "unlimited", "tenExample:intsingledigit_label": "Integer", "tenExample:intsingledigit_description": "digit grouping", "tenExample:decsingle_label": "Decimal", "tenExample:decsingle_description": "unlimited", "tenExample:decsingledigit_label": "Decimal", "tenExample:decsingledigit_description": "digit grouping", "tenExample:datetimesingle_label": "Date & time", "tenExample:datetimesingle_description": "unlimited", "tenExample:datetimesinglerequired_label": "Date & time", "tenExample:datetimesinglerequired_description": "mandatory", "tenExample:datesingle_label": "Date2", "tenExample:datesingle_description": "unlimited", "tenExample:datesinglerequired_label": "Date1", "tenExample:datesinglerequired_description": "mandatory", "tenExample:booleanrequiredtrue_label": "Boolean", "tenExample:booleanrequiredtrue_description": "mandatory", "tenExample:booleannull_label": "Boolean Tri-State", "tenExample:booleannull_description": "Null allowed", "tenExample:extract2_label": "Extract & map", "tenExample:tablesimplefields_label": "Simple fields", "tenExample:tablesimplefields_description": "Table with simple fields", "tenExample:tableclassifications_label": "Fields with classifications", "tenExample:tableclassifications_description": "Table with classification fields", "tenExample:strorganizationsingle_label": "User/Group", "tenExample:strorganizationmulti_label": "Users/Groups", "tenExample:strcatalogfruitsmulti_label": "Fruits", "tenExample:strcatalogfruitmulti_description": "Apple,Banana,Pear,Plum,Pineapple (multi)", "tenExample:tablenotice_label": "Notice", "tenExample:tablecreatedate_label": "Date", "tenExample:tableuser_label": "User", "tenExample:tablereadonly_label": "Write protection", "tenExample:tablenumber_label": "Number", "tenExample:tablenumberdigit_label": "Digit-number", "tenExample:tabledistance_label": "Distance", "tenExample:tabledistancedigit_label": "Digit-distance", "tenExample:tablecreatedatetime_label": "Datetime", "tenExample:tableemail_label": "Email", "tenExample:tableurl_label": "URL", "tenExample:tablephone_label": "Phone", "tenExample:tablecatalog_label": "Catalog", "tenExample:tablereference_label": "Reference", "tenExample:simpleFields_label": "Simple Fields", "tenExample:classifications_label": "Classifications", "tenExample:number_label": "Number", "tenExample:number_description": "Will be filled via script", "tenExample:createdate_label": "Created", "tenExample:createdate_description": "Will be filled via script as well", "tenExample:notice_label": "Notice", "tenExample:notice_description": "To be filled by user", "tenExample:probability_label": "Probability", "tenExample:probability_description": "To be filled by user as well", "tenExample:readonly_label": "Read-only", "tenExample:readonly_description": "It's still unclear who will do it ...", "tenExample:required_label": "Mandatory fields", "tenExample:notrequired_label": "Without obligation", "tenExample:tableGroup_label": "Table group", "tenExample:tableFilling_label": "Table filling", "tenExample:process_label": "Approval process", "tenExample:process:0_label": "Draft in work", "tenExample:process:1_label": "Draft in review", "tenExample:process:2_label": "Draft in rework", "tenExample:process:3_label": "Document ready", "tenExample:process:4_label": "Approved", "tenExample:process:5_label": "Rejected", "tenExample:datetimemulti_label": "Date & time ", "tenExample:datetimemulti_description": "unlimited", "tenExample:strcatalogfruitmulti_label": "Fruits", "tenExample:strcatalogfruitsmulti_description": "Apple,Banana,Pear,Plum,Pineapple (multi)", "tenExample:Table Group_label": "My group", "twosteptest_proc_label": "Two step process", "twosteptest_proc:2nd_task": "Second task", "twosteptest_proc:simplefields_label": "Simple fields", "twosteptest_proc:complexfields_label": "Complex fields", "twosteptest_proc:datetime_label": "Date & time", "twosteptest_proc:date_label": "Date only", "twosteptest_proc:boolean_label": "boolean", "twosteptest_proc:integer_label": "Integer", "twosteptest_proc:decimal_label": "Decimal", "twosteptest_proc:string_label": "String", "twosteptest_proc:stringmultirow_label": "Multi-row string ", "twosteptest_proc:email_label": "Email", "twosteptest_proc:phone_label": "Phone", "twosteptest_proc:url_label": "URL", "twosteptest_proc:user_label": "User", "twosteptest_proc:reference_label": "Reference", "twosteptest_proc:catalogcustom_label": "Custom catalog", "twosteptest_proc:test_table_label": "Notices", "twosteptest_proc:test_table_description": "List of notices", "twosteptest_proc:column_string_label": "Notice", "twosteptest_proc:column_date_label": "Date", "twosteptest_proc:column_user_label": "User", "twosteptest_proc:column_boolean_label": "Editable", "userGroupAssignment:user_label": "User", "userGroupAssignment:user_description": "Assign the user who should ...", "userGroupAssignment:comment_label": "Comment", "userGroupAssignment:comment_description": "Tell the user what to do .." }
- Response Example
-
201 CREATED
no response body
GET /api-web/api/admin/resources/text/languages
- Retrieve a list of all used locales of the tenant.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves a list of all used languages for resources of the active tenant.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/admin/resources/text/languages
no request body
- Response Example
-
200 OK
Response Body[ "fr", "en", "it", "pt", "es", "de", "ru", "sv" ]
bpm-controller
The bpm-engine API is required.
|
GET /api-web/api/bpm/inbox
- Retrieve the tasks for the logged-in user.
- As of Version
-
2023 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the tasks for the logged-in user.
Optional query parameters:
Parameter Type Description visibleTo
string
isCompleted
boolean
includeProcessVariables
boolean
businessKey
string
processDefinitionKey
string
processInstanceId
string
page
integer($int32)
size
integer($int32)
sort
string
id
string
name
string
assignee
string
owner
string
createdBefore
string
createdAfter
string
completedBefore
string
completedAfter
string
briefRepresentation
boolean
Indicates whether to provide additional information in response.
Default:
true
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Indicates a parameter was passed in the wrong format. The status-message contains additional information.
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/bpm/inbox
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "initiator": { "id": "string", "title": "string" }, "processDefinition": { "id": "string", "idPrefix": "string", "name": "string", "description": "string" }, "attachments": [ "string" ], "subject": "string", "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ], "createTime": "string", "formKey": "string", "parentTaskId": "string", "name": "string", "description": "string", "id": "string", "suspended": true, "claimTime": "string" } ], "hasMoreItems": true, "totalNumItems": 0, "numItems": 0 }
GET /api-web/api/bpm/process-definitions
- Retrieve the process definitions the logged-in user is allowed to use.
- As of Version
-
2023 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the process definitions a user is allowed to use to start a process.
This Web API request uses the internal
bpm-engine
requestGET /bpm-engine/api/process-definitions
.Optional query parameters:
Parameter Type Description latest
boolean
Returns only the latest process definition versions.
Default:
true
page
integer($int32)
Result page you want to retrieve (0…N). Default is 0 which means the first page.
Default: 0
size
integer($int32)
Number of objects per page.
Default: 20
Response HTTP status codes:
HTTP status code Meaning 200
OK
403
Forbidden
- Request Example
-
https://<host>/api-web/api/bpm/process-definitions?latest=true&page=0&size=3
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "id": "dms-lite-adhoc:1:9689a57f-2cf7-11ec-84cf-867d35831bc9", "category": "http://www.flowable.org/processdef", "key": "dms-lite-adhoc", "name": "DMS Lite Adhoc Workflow v1", "description": "DMS Lite Ad-Hoc Workflow", "version": 1, "global": false, "startFormDefined": true, "suspended": false }, { "id": "dms-lite-standard:1:889414e6-ff4e-11eb-97f3-86f2decdc2b4", "category": "http://www.flowable.org/processdef", "key": "dms-lite-standard", "name": "DMS Lite Standard Workflow", "description": "DMS Lite Taskflow", "version": 1, "global": false, "startFormDefined": false, "suspended": false }, { "id": "dms-lite-taskflow:1:9689a57e-2cf7-11ec-84cf-867d35831bc9", "category": "http://www.flowable.org/processdef", "key": "dms-lite-taskflow", "name": "DMS Lite Taskflow", "description": "DMS Lite Taskflow", "version": 1, "global": false, "startFormDefined": false, "suspended": false } ], "numItems": 3, "totalNumItems": 3, "hasMoreItems": false }
GET /api-web/api/bpm/processes
- Retrieve the processes for the logged-in user.
- As of Version
-
2023 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the processes for the logged-in user.
Optional query parameters:
Parameter Type Description includeProcessVariables
boolean
Include process variables in the result.
businessKey
string
Only return process instances with the given
businessKey
.isCompleted
boolean
processDefinitionKey
string
Only return process instances with the given process definition key.
page
integer($int32)
Result page you want to retrieve (0…N). Default is 0 which means the first page.
size
integer($int32)
Number of process objects per page.
sort
string
Sorting of results either ascending (
asc
) or descending (desc
). Default sort order is ascending.processInstanceId
string
processDefinitionId
string
nameLikeIgnoreCase
string
startedBy
string
startedBefore
string
startedAfter
string
finishedBefore
string
finishedAfter
string
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Indicates a parameter was passed in the wrong format. The status-message contains additional information.
- Request Example
-
https://<host>/api-web/api/bpm/processes?businessKey=examplekey&includeProcessVariables=true&processDefinitionKey=follow-up
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "id": "string", "subject": "string", "attachments": [ "string" ], "processDefinition": { "id": "string", "idPrefix": "string", "name": "string", "description": "string" }, "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ], "startUserId": "string", "startActivityId": "string", "durationInMillis": 0, "name": "string", "businessKey": "string", "startTime": "string", "endTime": "string", "endActivityId": "string", "deleteReason": "string", "suspended": true } ] }
POST /api-web/api/bpm/processes
- Start a process.
- As of Version
-
2023 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Start a process.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/bpm/processes
Request Body{ "processDefinitionKey": "string", "businessKey": "string", "name": "string", "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ], "attachments": [ "string" ], "subject": "string" }
- Response Example
-
200 OK
Response Body{ "objects": [ { "id": "string", "subject": "string", "attachments": [ "string" ], "processDefinition": { "id": "string", "idPrefix": "string", "name": "string", "description": "string" }, "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ], "startUserId": "string", "startActivityId": "string", "durationInMillis": 0, "name": "string", "businessKey": "string", "startTime": "string", "endTime": "string", "endActivityId": "string", "deleteReason": "string", "suspended": true } ] }
DELETE /api-web/api/bpm/processes/{processInstanceId}
- Delete the specified process instance.
- As of Version
-
2020 Autumn
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Description
-
Deletes the process instance specified by its
processInstanceId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad request
403
Forbidden
404
Not found
409
Conflict
422
Unprocessable entity
- Request Example
-
https://<host>/api-web/api/bpm/processes/af678-34280fe-3bc
no request body
- Response Example
-
200 OK
no response body
GET /api-web/api/bpm/processes/{processInstanceId}/history
- Retrieve the specified process' history.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the history for the specified process instance.
Optional query parameters:
Parameter Type Description includeComments
boolean
Indicates whether comments are included in response.
Default:
false
Response HTTP status codes:
HTTP status code Meaning 200
OK
403
Forbidden
404
Not found
- Request Example
-
https://<host>/api-web/api/bpm/processes/af678-34280fe-3bc/history
no request body
- Response Example
-
200 OK
Response Body{ "tasks": [ { "assignee": { "id": "string", "title": "string" }, "owner": { "id": "string", "title": "string" }, "initiator": { "id": "string", "title": "string" }, "processDefinition": { "id": "string", "idPrefix": "string", "name": "string", "description": "string" }, "attachments": [ "string" ], "subject": "string", "formKey": "string", "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ], "resolvedValues": { "additionalProp1": "string", "additionalProp2": "string", "additionalProp3": "string" }, "taskForm": { "additionalProp1": {}, "additionalProp2": {}, "additionalProp3": {} }, "taskMessages": [ {} ] } ], "comments": [ { "id": "string", "author": { "id": "string", "title": "string" }, "message": "string", "time": "string", "processInstanceId": "string", "taskId": "string" } ] }
GET /api-web/api/bpm/tasks
- Retrieve the tasks for the logged-in user.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the tasks for the logged-in user.
Optional query parameters:
Parameter Type Description includeProcessVariables
boolean
businessKey
string
processDefinitionKey
string
processInstanceId
string
page
integer($int32)
size
integer($int32)
sort
string
id
string
name
string
assignee
string
owner
string
createdBefore
string
createdAfter
string
completedBefore
string
completedAfter
string
visibleTo
string
isCompleted
boolean
briefRepresentation
boolean
Indicates whether to provide additional information in response.
Default:
true
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Indicates a parameter was passed in the wrong format. The status-message contains additional information.
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/bpm/tasks
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "initiator": { "id": "string", "title": "string" }, "processDefinition": { "id": "string", "idPrefix": "string", "name": "string", "description": "string" }, "attachments": [ "string" ], "subject": "string", "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ], "createTime": "string", "formKey": "string", "parentTaskId": "string", "name": "string", "description": "string", "id": "string", "suspended": true, "claimTime": "string" } ], "hasMoreItems": true, "totalNumItems": 0, "numItems": 0 }
GET /api-web/api/bpm/tasks/{taskId}
- Retrieve the specified task.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the tasks for the logged-in user.
Optional query parameters:
Parameter Type Description includeProcessVariables
boolean
Indicates whether process variables are included in response.
Default:
false
briefRepresentation
boolean
Indicates whether to provide additional information in response.
Default:
false
Response HTTP status codes:
HTTP status code Meaning 200
OK
404
Not found
- Request Example
-
https://<host>/api-web/api/bpm/tasks/4345abc-acb3485739-ef3
no request body
- Response Example
-
200 OK
Response Body{ "assignee": { "id": "string", "title": "string" }, "owner": { "id": "string", "title": "string" }, "initiator": { "id": "string", "title": "string" }, "processDefinition": { "id": "string", "idPrefix": "string", "name": "string", "description": "string" }, "attachments": [ "string" ], "subject": "string", "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ], "createTime": "string", "formKey": "string", "parentTaskId": "string", "name": "string", "description": "string", "id": "string", "suspended": true, "claimTime": "string" }
PUT /api-web/api/bpm/tasks/{taskId}
- Execute an action on the specified task.
- As of Version
-
2020 Autumn
- Request Method
-
PUT
- Response Format
-
JSON
- Description
-
Updates a task specified by its
taskId
. The task action is defined in JSON format in the request body.Response HTTP status codes:
HTTP status code Meaning 200
Indicates the action was executed.
400
Indicates the action cannot be performed due to a conflict. Either the task was updates simultaneously or the task was claimed by another user, in case of the claim action.
404
Indicates the requested task was not found.
- Request Example
-
https://<host>/api-web/api/bpm/tasks/4345abc-acb3485739-ef3
Response Body{ "action": "save", "attachments": [ "string" ], "subject": "string", "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ] }
- Response Example
-
200 OK
Response Body{ "assignee": { "id": "string", "title": "string" }, "owner": { "id": "string", "title": "string" }, "initiator": { "id": "string", "title": "string" }, "processDefinition": { "id": "string", "idPrefix": "string", "name": "string", "description": "string" }, "attachments": [ "string" ], "subject": "string", "variables": [ { "name": "string", "type": "string", "value": {}, "scope": "string" } ], "createTime": "string", "formKey": "string", "parentTaskId": "string", "name": "string", "description": "string", "id": "string", "suspended": true, "claimTime": "string" }
POST /api-web/api/bpm/tasks/{taskId}/candidates
- Update task candidates.
- As of Version
-
2024 Spring
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Extends the list of candidates for the running task specified by
taskId
. The new candidates are specified in the JSON request body directly via their user ID or indirectly via roles.Response HTTP status codes:
HTTP status code Meaning 204
The task was found and the list of candidates was updated.
401
The calling user is not authorized.
403
The user is not allowed to add candidates to the task.
404
The requested task was not found.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/tasks/187/candidates
Request body{ "users": [ "string" ], "roles": [ "string" ] }
- Response Example
-
204 OK
Response Body{ "assignee": { "id": "string", "title": "string" }, "owner": { "id": "string", "title": "string" }, "initiator": { "id": "string", "title": "string" }, "processDefinition": { "id": "string", "idPrefix": "string", "name": "string", "description": "string" }, "attachments": [ "string" ], "subject": "string", "variables": [ { "name": "string", "type": "string", "value": {} } ], "createTime": "string", "formKey": "string", "parentTaskId": "string", "name": "string", "description": "string", "id": "string", "suspended": true, "claimTime": "string" }
POST /api-web/api/bpm/tasks/{taskId}/comment
- Create a comment for the specified task.
- As of Version
-
2023 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Creates a comment for the task specified by
taskId
. Send the message as string in the request body.Response HTTP status codes:
HTTP status code Meaning 201
Indicates the comment was created and the result is returned.
400
Indicates the comment is missing from the request.
404
Indicates the requested task was not found.
- Request Example
-
https://<host>/api-web/api/bpm/tasks/4345abc-acb3485739-ef3/comment
Request BodyThis is the example message.
- Response Example
-
201 CREATED
Response Body{ "id": "string", "author": "string", "message": "This is the example message.", "time": "string", "processInstanceId": "string", "taskId": "4345abc-acb3485739-ef3" }
dms-controller
These endpoints are accessible for any authenticated user in the default configuration. Most of them internally call the core API.
GET /api-web/api/dms/catalogs/{qname}
- Retrieve a specified catalog.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the catalog specified by its name qname.
The tenant-specific resource will be checked first. If a catalog with name qname is available, it will be returned. Otherwise the global resource will be checked. If there is a catalog with name qname, it will be returned. The endpoint returns null if no catalog with qname was found in both global and tenant-specific resource.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/dms/catalogs/contracts
no request body
- Response Example
-
200 OK
Response Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
POST /api-web/api/dms/catalogs/{qname}
- Create or update the specified catalog for the active tenant.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Updates the tenant-specific catalog specified by its technical name
qname
with the data passed in the request body in JSON format.If no tenant-specific catalog with the specified technical name is available, it will be created.
Response HTTP status codes:
HTTP status code Meaning 201
OK
400
Bad request
401
Unauthorized
403
Forbidden
- Request Example
-
https://<host>/api-web/api/dms/catalogs/contracts
Request Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
- Response Example
-
200 OK
Response Body{ "errors": [], "valid": true }
PATCH /api-web/api/dms/catalogs/{qname}
- Update the specified catalog for the active tenant.
- As of Version
-
2021 Summer
- Request Method
-
PATCH
- Response Format
-
JSON
- Description
-
Updates the existing tenant-specific catalog identified by its name
qname
or creates a modified copy of an existing global catalog, with the data passed in JSON format in the request body.The tenant-specific resource will be checked first. If a catalog with name
qname
is available, it will be updated. Otherwise the global resource will be checked. If there is a catalog with nameqname
, it will be copied to the tenant-specific resource. This copy will be updated.In the response body, the modified tenant-specific catalog will be returned.
If no catalog with name
qname
is available in both tenant-specific and global resources, an error will be thrown.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
404
Not found
500
Internal Server Error
- Request Example
-
https://<host>/api-web/api/dms/catalogs/contracts
Request Body[ { "op": "replace", "path": "/entries/1/name", "value": "Rental agreement" }, { "op": "remove", "path": "/entries/3" }, { "op": "add", "path": "/entries/-", "value": { "name": "Purchase contract", "disabled": true } } ]
- Response Example
-
200 OK
Response Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
GET /api-web/api/dms/catalogs/{qname}/validate
- Get the entries that are already used.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Checks if entries of the catalog specified by
qname
are already in use. Returns an empty list if no catalog entries are used.Optional query parameters:
Parameter Type Description entries
list of strings
List of entry names to be validated.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/dms/catalogs/contracts/validate
no request body
- Response Example
-
200 OK
Response Body[ "string" ]
GET /api-web/api/dms/forms/{objecttype}
- Retrieve a metadata form for the specified object type.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the default form for the object type specified by object type ID
objecttype
and optional query parameterssituation
andsots
(secondary object types) for the active tenant.Returns
null
if there is no designed form model for the given object type and situation.Behind the object type ID, add the query parameter
situation=CREATE
(situation=EDIT
) to retrieve the CREATE (EDIT) form. Default isEDIT
. Furthermore, addsots=<objectTypeId>
in order to specify a secondary object type of which properties should be included in the retrieved form. If the SOT is defined in an app or tenant schema, theobjectTypeId
has to contain the corresponding prefix, e.g.,tenMytenant:mysot1
orappMyapp:mysot1
. Thesots
query parameter can be added multiple times for different secondary object types.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/dms/forms/tenMytenant:qadocscripts?situation=EDIT&sots=examplesot1&sot=examplesot2
no request body
- Response Example
-
200 OK
Response Body{ "name": "tenMytenant:qadocscripts", "situation": "EDIT", "script": "any valid script", "elements": [ { "name": "core", "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "name": "appClient:clienttitle", "type": "string", "rows": 1 }, { "name": "appClient:clientdescription", "type": "string", "rows": 1 } ] }, { "name": "data", "type": "o2mGroupStack", "elements": [ { "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:strsingle", "type": "string", "rows": 1 }, { "name": "tenMytenant:strsinglemail", "type": "string", "rows": 1 } ] }, { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:intsingle", "type": "integer" }, { "name": "tenMytenant:intsingledigit", "type": "integer" } ] } ] } ] } ] } ] }
POST /api-web/api/dms/objects
- Create a DMS object.
- As of Version
-
2020 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Creates a DMS object with the data passed in the multipart request body including the metadata in JSON structure and optionally a binary content file.
The metadata of the created object are returned in the response body.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
POST /api-web/dms/objects HTTP/1.1 Accept: application/json, application/*+json Content-Type: multipart/form-data;boundary=Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH Content-Length: 83258 Host: 127.0.0.1:7400 --Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH Content-Disposition: form-data; name="data"; filename="blob" Content-Type: application/json;charset=UTF-8 { "system:objectTypeId": "appPersonalfile:pfdocumentdlm", "system:tags": [["appclient:dlm:prepare",0]] } --Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH Content-Disposition: form-data; name="files"; filename="JPG_Test-min.jpg" Content-Type: image/jpeg --Jn3QCX9rHAFQaofW6vsdoz5CsD5_P0PZhH
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
DELETE /api-web/api/dms/objects
- Delete multiple DMS objects.
- As of Version
-
2023 Winter
- Request Method
-
DELETE
- Response Format
-
JSON
- Description
-
Deletes multiple DMS objects specified by their
system:objectId
in the JSON request body. The processing is internally handled synchronously.The number of DMS objects per request is limited to 100.
Optional query parameters:
Parameter Type Description greedy
boolean
If
true
(default), the deletion process continues even if one or more DMS objects cannot be deleted. It deletes as many DMS objects as possible.If
false
, the entire request fails if one object cannot be deleted.Response HTTP status codes:
HTTP status code Meaning 207
Multi-Status
- Request Example
-
https://<host>/api-web/api/dms/objects?greedy=true
Request Body[ "string" ]
- Response Example
-
207 Multi-Status
Response BodyJSON list of processed objects with their metadata before the deletion
PATCH /api-web/api/dms/objects
- Update the metadata of multiple DMS objects.
- As of Version
-
2023 Winter
- Request Method
-
PATCH
- Response Format
-
JSON
- Description
-
Updates the metadata of all DMS objects specified by their
system:objectId
in the JSON request body. Only the properties specified in the request body and some automatically determined system properties are updated. All further properties remain unchanged.A (non-required) property value can be removed by sending
null
as new value.If even one object could not be updated, the whole request fails.
The number of DMS objects per request is limited to 100.
Response HTTP status codes:
HTTP status code Meaning 200
OK
- Request Example
-
https://<host>/api-web/api/dms/objects
Request Body{ "patches": [ { "id": "cdc7095f-a5ce-486d-92a7-6d0955d969ee", "data": { "appClient:clientdescription": "test 0001", "appPersonalfile:pfsubject": "Meeting A" } }, { "id": "12345678-90ab-cdef-1234-567890ab", "data": { "appClient:clientdescription": "note 123", "appPersonalfile:pfsubject": "null" } } ] }
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
GET /api-web/api/dms/objects/{id}
- Get the metadata of the specified DMS object.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the metadata of the DMS object specified by its object ID
id
.Optional query parameters:
Parameter Type Description includePermissions
boolean
Should permissions be included.
Default:
true
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/dms/objects/4711-44321-666777888
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
DELETE /api-web/api/dms/objects/{id}
- Delete the specified object.
- As of Version
-
2020 Autumn
- Request Method
-
DELETE
- Response Format
-
JSON
- Description
-
Deletes the DMS object specified by its object ID
id
.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad request
403
Forbidden
404
Not found
409
Conflict
422
Unprocessable entity
- Request Example
-
https://<host>/api-web/api/dms/objects/4711-44321-666777888
no request body
- Response Example
-
200 OK
no response body
PATCH /api-web/api/dms/objects/{id}
- Update the specified DMS object.
- As of Version
-
2020 Autumn
- Request Method
-
PATCH
- Response Format
-
JSON
- Description
-
Updates the metadata and/or tags of an existing DMS object specified by its object ID
id
with the data passed JSON format in the request body.Internally, the core API endpoint
PATCH /api/dms/objects/{objectId}
is called. Thus, only those properties that are part of the request body are changed. Properties that are missing in the request body are not changed by the update.The modified DMS object is returned in the response body in JSON format.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
Request Body
{ "additionalProp1": {}, "additionalProp2": {}, "additionalProp3": {} }
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
GET /api-web/api/dms/objects/{id}/contents/file
- Retrieve the binary content file of the specified object.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the binary content file assigned to the object specified by its object ID
id
.Optional query parameters:
Parameter Type Description version
integer($int32)
The version of the DMS object.
asdownload
boolean
If set to
true
, the content disposition header response value is set toattachment
. This should trigger a download by the browser.Default:
true
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/dms/objects/4711-44321-666777888/contents/file
no request body
- Response Example
-
200 OK
Response Body[ "string" ]
POST /api-web/api/objects/{id}/contents/file
- Update the binary content file of the specified object.
- As of Version
-
2020 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Updates the binary content file assigned to the object specified by its object ID
id
with the file passed in the request body.The response body contains the metadata of the corresponding object.
Response HTTP status codes:
HTTP status code Meaning 200
OK
304
Not Modified
401
Unauthorized
422
Unprocessable entity
- Request Example
-
https://<host>/api-web/api/dms/objects/234df-aca4-fe423/contents/file
Request Body[ "string" ]
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
GET /api-web/api/dms/objects/{id}/versions
- Retrieve the metadata of all versions of the specified DMS object.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the metadata of all versions of the DMS object specified by its object ID
id
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/dms/objects/4711-44321-666777888/versions
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
GET /api-web/api/dms/objects/{id}/versions/{version}
- Retrieve the metadata of the specified DMS object version.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the metadata of the version
version
of the DMS object specified by its object IDid
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/dms/objects/4711-44321-666777888/versions/2
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
POST /api-web/api/dms/objects/{objectId}/versions/{versionNr}/actions/restore
- Restore the specified old version of the DMS object.
- As of Version
-
2022 Spring
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Restores the older version
version
of the DMS object specified by its object IDid
.Optional query parameters:
Parameter Type Description restoreParentId
boolean
Indicates whether to keep the current value for the
system:parentId
property of the child object even after restoring an old version.Default:
true
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/dms/objects/4711-44321-666777888/versions/2/actions/restore
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
POST /api-web/api/dms/objects/export
- Search DMS objects and retrieve the result list as CSV.
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
CSV
- Description
-
Retrieves a list of DMS objects matching the search query passed in the request body in CSV format.
Datetime properties are formatted as ISO standard. Decimals are formatted corresponding to the locale for the currently logged-in user that is specified in the request header. If no locale is specified for the request,
en
is used as default.Further formatting can be configured in the
api-web-prod.yml
configuration file.The query JSON in the request body has to match the format for search via Web API gateway.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/dms/objects/export
Request Body{ "fields": [ "string" ], "types": [ "string" ], "lots": [ "string" ], "term": "string", "filters": [ { "lo": "string", "f": "string", "v1": {}, "v2": {}, "o": "string", "useNot": false } ], "tableFilters": [ { "table": "string", "row": 0, "columnFilters": [ { "lo": "string", "f": "string", "v1": {}, "v2": {}, "o": "string", "useNot": false } ], "lo": "string", "useNot": false } ], "aggs": [ "string" ], "scope": "string", "sort": [ { "order": "string" } ], "from": 0, "size": 20 }
- Response Example
-
200 OK
text/csv
in the response body
POST /api-web/api/dms/objects/search
- Search DMS objects.
- As of Version
-
2020 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Retrieves a list of DMS objects matching the search query passed in the request body in JSON format.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/dms/objects/search
Request Body{ "fields": [ "string" ], "types": [ "string" ], "lots": [ "string" ], "term": "string", "filters": [ { "lo": "string", "f": "string", "v1": {}, "v2": {}, "o": "string", "useNot": false } ], "tableFilters": [ { "table": "string", "row": 0, "columnFilters": [ { "lo": "string", "f": "string", "v1": {}, "v2": {}, "o": "string", "useNot": false } ], "lo": "string", "useNot": false } ], "aggs": [ "string" ], "scope": "string", "sort": [ { "order": "string" } ], "from": 0, "size": 20 }
- Response Example
-
200 OK
Response Body{ "objects": [ { "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-05T12:22:41.820Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 31 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-05T12:22:55.900Z", "5a7a096a8c517759" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appPersonalfile:pfsubject": { "value": "Meeting A" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "test note" }, "appClient:clientdescription": { "value": "test 0001" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } }, { "properties": { "system:objectId": { "value": "12345678-90ab-cdef-1234-567890ab" }, "system:baseTypeId": { "value": "system:document" }, "system:objectTypeId": { "value": "appPersonalfile:pfdocumentdlm" }, "system:secondaryObjectTypeIds": { "value": [ "appClientsystem:leadingType", "appClient:clientdefaults", "appPersonalfile:pfsicknotesot" ] }, "system:createdBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:creationDate": { "value": "2023-09-07T12:32:37.500Z" }, "system:lastModifiedBy": { "value": "85b6c5ef-7e87-4e71-bbba-4148a042c7c4", "title": "Root, Test (root)" }, "system:lastModificationDate": { "value": "2023-09-08T07:40:10.470Z" }, "system:versionNumber": { "value": 26 }, "system:tenant": { "value": "testyuuvis" }, "system:traceId": { "value": "97a35859dbb4c436" }, "system:tags": { "value": [ [ "appclient:dlm:prepare", 1, "2023-09-07T12:32:49.790Z", "78d6e14d5b3d8a2e" ] ] }, "system:parentId": { "value": "a91c4029-2572-4649-a315-35a501d7b610" }, "system:parentObjectTypeId": { "value": "appPersonalfile:pfpersonalfile" }, "appClientsystem:leadingTypeId": { "value": "appPersonalfile:pfsicknotesot" }, "appClient:clienttitle": { "value": "patch test" }, "appClient:clientdescription": { "value": "note 123" }, "appPersonalfile:pfdays": { "value": 2 }, "appPersonalfile:pfsickcertificate": { "value": false }, "appPersonalfile:pfhalfday": { "value": false }, "appPersonalfile:pfcompensation": { "value": false } } } ], "numItems": null, "hasMoreItems": null, "totalNumItems": null }
GET /api-web/api/dms/permissions
- Retrieve the available object types the logged-in user can use.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the object types that are available for the individual actions on DMS objects for the currently logged-in user. Available actions are:
-
CREATE
-
WRITE
-
READ
-
DELETE
-
With this information, client applications can present a selection list of object types that are relevant for the logged-in user. Thus, users will see only those object types that are available to them. Those selection lists may differ for the individual actions.
The response body is a JSON structure listing all object types for the corresponding action as shown in the example below.
The object type IDs are defined in a corresponding schema.
The permissions are assigned to users via roles.
Internally, the endpoint calls the search service’s endpoint GET /search/api/search/dsl/check
.
+ Response HTTP status codes:
+
HTTP status code | Meaning |
---|---|
200 |
OK |
401 |
Unauthorized |
- Request Example
-
https://<host>/api-web/api/dms/permissions
no request body
- Response Example
-
200 OK
Response Body{ "CREATE": { "folderTypeIds": [ "appPersonalfile:pfpersonalfile" ], "secondaryObjectTypeIds": [ "system:secondary", "emailsot", "appClientsystem:leadingType", "tenKolibri:qadocdossiersot" ], "objectTypeIds": [ "email", "appClient:minidoc", "appPersonalfile:pfdocument", "tenKolibri:preobject" ] }, "READ": { "folderTypeIds": [ "appPersonalfile:pfpersonalfile", "appPhotoarchive:paphotoalbum" ], "secondaryObjectTypeIds": [ "system:secondary", "system:rmDestructionRetention", "emailsot", "emailextension", "appClientsystem:leadingType", "tenKolibri:qadocdossiersot", "tenKolibri:qadoccatalogssot", "tenKolibri:qadoccontentrequiredsot", "tenKolibri:qadocscriptssot" ], "objectTypeIds": [ "doctableofnotices", "email", "preemail", "appClient:minidoc", "appPersonalfile:pfidphoto", "appPersonalfile:pfdocument", "appPersonalfile:pfsicknote", "appPersonalfile:pfvacancy", "appPersonalfile:pfdocumentdlm", "tenKolibri:qadoccatalogs", "tenKolibri:qadocscripts", "tenKolibri:qadocscriptsmulti", "tenKolibri:preobject" ] }, "WRITE": { "folderTypeIds": [ "appPersonalfile:pfpersonalfile" ], "secondaryObjectTypeIds": [ "system:secondary", "emailsot", "appClientsystem:leadingType", "tenKolibri:qadocdossiersot" ], "objectTypeIds": [ "doctableofnotices", "email", "appClient:minidoc", "appPersonalfile:pfdocument", "tenKolibri:preobject" ] }, "DELETE": { "folderTypeIds": [ "tenKolibri:qadossier" ], "secondaryObjectTypeIds": [ "tenKolibri:qadocscriptssot" ], "objectTypeIds": [ "doctableofnotices", "tenKolibri:preobject" ] } }
POST /api-web/api/dms/schema/refresh
- Refresh a schema.
- As of Version
-
2023 Autumn
- Request Method
-
POST
- Response Format
-
HTTP status code
- Description
-
Refresh the global schema, the tenant schema or an app schema.
Optional query parameters:
Parameter Type Description global
boolean
Should global schema be refreshed.
Default:
true
app
string
The name of the app which schema should be refreshed.
tenant
string
The name of the tenant which schema should be refreshed.
- Request Example
-
https://<host>/api-web/api/dms/schema/refresh
no request body
- Response Example
-
200 OK
no response body
idm-controller
Endpoints of the Web API gateway for user information and role retrieval.
The tenant-management API is required.
|
GET /api-web/api/idm/roles
- Retrieve the roles from the connected identity provider.
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves all roles of the tenant. The relult list can be filtered by a search string. Technical roles are always filtered out.
Optional query parameters:
Parameter Type Description search
string
A string contained in role name or description.
tenant
string
Tenant name to retrieve roles for a different tenant. Can only be used by users with the
YUUVIS_SYSTEM_INTEGRATOR
role, otherwise ignored.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/idm/roles?search=test
no request body
- Response Example
-
200 OK
Response Body[ { "name": "TEST_ROLE", "description": "Example role" }, { "name": "EXAMPLE_ROLE", "description": "Role containing word test in its description" } ]
POST /api-web/api/idm/roles
- Create a role in Keycloak.
- As of Version
-
2023 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
YUUVIS_SYSTEM_INTEGRATOR
orYUUVIS_TENANT_ADMIN
role - Description
-
Create a role in the connected identity provider.
Only available if Keycloak is used as identity provider. The role is not introduced in a yuuvis® Momentum role set. Optional query parameters:
Parameter Type Description tenant
string
Tenant name to create a role for a different tenant. Can only be used by users with the
YUUVIS_SYSTEM_INTEGRATOR
role, otherwise ignored.Response HTTP status codes:
HTTP status code Meaning 201
Created
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/idm/roles
Request Body{ "name": "TEST_ROLE", "description": "Example role" }
- Response Example
-
200 OK
Response Body{ "errors": [], "valid": true }
DELETE /api-web/api/idm/roles/{role-name}
- Delete a role in Keycloak.
- As of Version
-
2023 Autumn
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
YUUVIS_SYSTEM_INTEGRATOR
orYUUVIS_TENANT_ADMIN
role - Description
-
Delete a role in the connected identity provider.
Only available if Keycloak is used as identity provider. The role is not deleted in a yuuvis® Momentum role set. Optional query parameters:
Parameter Type Description tenant
string
Tenant name if role shoud be deleted for a different tenant. Can only be used by users with the
YUUVIS_SYSTEM_INTEGRATOR
role, otherwise ignored.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/idm/roles/TEST_ROLE
no request body
- Response Example
-
200 OK
no response body
GET /api-web/api/idm/search
- Retrieve tenant roles and users from the identity provider.
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves all users and roles. The result list can be filtered by a search string. Current user, technical users, disabled users and technical roles are always filtered out.
Optional query parameters:
Parameter Type Description search
string
A string contained in role name or description or in user attributes.
size
integer($int32)
Maximum number of items for each category (
roles
andusers
) to be returned.Default: 10
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/idm/search
no request body
- Response Example
-
200 OK
Response Body{ "users": [ { "username": "string", "id": "string", "foreignid": "string", "type": "string", "title": "string", "email": "string", "firstname": "string", "lastname": "string", "domain": "string", "tenant": "string", "authorities": [ "string" ], "substituteOf": [ "string" ], "accountNonExpired": true, "accountNonLocked": true, "credentialsNonExpired": true, "enabled": true, "displayName": "string" } ], "roles": [ { "name": "string", "description": "string" } ] }
GET /api-web/api/idm/users
- Retrieve tenant users from the identity provider.
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves all users of the tenant. The result list can be filtered by applying conditions that have to be matched.
The conditions are specified via the following optional query parameters.
Users with technical roles are always filtered out.
Optional query parameters:
Parameter Type Description search
string
Retrieve only users for which the specified string is contained in user name, first name, last name or e-mail.
excludeMe
boolean
onlyActive
boolean
If
true
, the currently logged-in user is excluded from the result list. (default:true
)roles
list of strings
Retrieve only users that have at least one of the provided roles.
page
integer
Result page you want to retrieve (0…N). Default is 0 which means the first page.
size
integer($int32)
Limit the number of users per page. (default: 20)
sort
list of strings
Sorting of results either ascending (
asc
) or descending (desc
). Default sort order is ascending.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/idm/users
no request body
- Response Example
-
200 OK
Response Body[ { "username": "string", "id": "string", "foreignid": "string", "type": "string", "title": "string", "email": "string", "firstname": "string", "lastname": "string", "domain": "string", "tenant": "string", "authorities": [ "string" ], "substituteOf": [ "string" ], "accountNonExpired": true, "accountNonLocked": true, "credentialsNonExpired": true, "enabled": true, "displayName": "string" } ]
GET /api-web/api/idm/users/{userId}
- Retrieve attributes of the specified user.
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves user-specific data for the user specified by
userId
. Technical roles are always filtered out.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/idm/users/string
no request body
- Response Example
-
200 OK
Response Body{ "username": "string", "id": "string", "foreignid": "string", "type": "string", "title": "string", "email": "string", "firstname": "string", "lastname": "string", "domain": "string", "tenant": "string", "authorities": [ "string" ], "substituteOf": [ "string" ], "accountNonExpired": true, "accountNonLocked": true, "credentialsNonExpired": true, "enabled": true, "displayName": "string" }
GET /api-web/api/idm/whoami
- Retrieve attributes of the logged-in user.
- As of Version
-
2023 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Returns a result list configuration by type.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/idm/users/whoami
no request body
- Response Example
-
200 OK
Response Body{ "username": "string", "id": "string", "foreignid": "string", "type": "string", "title": "string", "email": "string", "firstname": "string", "lastname": "string", "domain": "string", "tenant": "string", "authorities": [ "string" ], "substituteOf": [ "string" ], "accountNonExpired": true, "accountNonLocked": true, "credentialsNonExpired": true, "enabled": true, "displayName": "string" }
resource-controller
Endpoints of the Web API gateway for resource files management.
GET /api-web/api/resources/config/{name}
- Retrieve the specified configuration.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Modified behavior as of 2023 Winter. For the configuration specified by
name
, the endpoint retrieves the-
global configuration file,
-
tenant-specific configuration file,
-
app-specific configuration file OR
-
merged configuration file for the active tenant.
The merged configuration file is composed of tenant-specific, app-specific and global configurations.
The actual target configuration is specified via query parameters.
Optional query parameters:
Parameter Type Description raw
boolean
If
false
or unspecified, the merged client configuration will be used.If
true
, an unmerged configuration is retrieved.filter
string
Filter for merged config (Only available if NOT
raw
and user isYUUVIS_SYSTEM_INTEGRATOR
)-
If not specified, tenant AND global resource (AND resolved resource, if specified) are retrieved.
-
If
filter=global
, only the global resource is retrieved. -
If
filter=tenant
, only the tenant-specific resource is retrieved. -
If
filter=resolved
, only 1 resource based on hierarchy (resolved OR tenant OR global) is retrieved.
tenant
string
Tenant name (Only use if
raw
is set)app
string
App (Only use if
raw
is set)Response HTTP status codes:
HTTP status code Meaning 200
OK
404
Not found
-
- Request Example
-
https://<host>/api-web/api/resources/config/main-config
no request body
- Response Example
-
200 OK
Response Body{ "tenant": { "core": { "apiBase": { "core": "/api", "api-web": "/api-web/api", "predict": "/predict-api", "viewer": "/viewer", "logout": "/logout", "oauth": "/oauth" }, "gridOptions": { "pageSize": 50, "pageSizeOptions": [ 13, 23, 33 ], "rowHeight": 70, "rowHeightOptions": [ 23, 33, 43 ] }, "languages": [ { "iso": "de", "label": "Deutsch" }, { "iso": "de-CH", "label": "Deutsch (Schweiz)" }, { "iso": "en", "label": "English", "fallback": true } ], "logging": { "level": "debug" }, "features": { "dashboardWorkspaces": true } }, "client": { "docu": { "link": "https://help.optimal-systems.com/yuuvis_develop/display/YMY/Adding+Documentation", "language": [ "de", "en" ] } } } }
POST /api-web/api/resources/config/{name}
- Update the specified configuration file.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available for users with the roles configured in
api-web.technical-roles
in theapi-web-prod.yml
configuration file. Default:YUUVIS_SYSTEM_INTEGRATOR
andYUUVIS_TENANT_ADMIN
. - Description
-
Creates or updates the client configuration file specified by
name
with the data passed in JSON format in the request body. If no query parameter is set, the corresponding global configuration file is created/updated.Optional query parameters:
Parameter Type Description tenant
string
Update the tenant-specific configuration instead of the global one. In the default configuration, only available for users with the
YUUVIS_TENANT_ADMIN
role.app
string
Update the app-specific configuration instead of the global one. In the default configuration, only available for users with the
YUUVIS_SYSTEM_INTEGRATOR
role.Response HTTP status codes:
HTTP status code Meaning 201
CREATED
DELETE /api-web/api/resources/config/{name}
- Delete the specified configuration file.
- As of Version
-
2023 Winter
- Request Method
-
DELETE
- Response Format
-
JSON
- Required Permission
-
Available for users with the roles configured in
api-web.technical-roles
in theapi-web-prod.yml
configuration file. Default:YUUVIS_SYSTEM_INTEGRATOR
andYUUVIS_TENANT_ADMIN
. - Description
-
Deletes the client configuration file specified by
name
with the data passed in JSON format in the request body. If no query parameter is set, the corresponding global configuration file is deleted.Optional query parameters:
Parameter Type Description tenant
string
Delete the tenant-specific configuration instead of the global one. In the default configuration, only available for users with the
YUUVIS_SYSTEM_INTEGRATOR
role.app
string
Delete the app-specific configuration instead of the global one. In the default configuration, only available for users with the
YUUVIS_SYSTEM_INTEGRATOR
role.Response HTTP status codes:
HTTP status code Meaning 200
OK
404
Configuration resource not found
GET /api-web/api/resources/forms/{type}
- Retrieve the metadata form for the specified object type.
- As of Version
-
2023 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the non-enriched form by object type ID
type
and optional query parameterssituation
andsots
(secondary object types).Behind the object type ID, add the query parameter
situation=CREATE
(situation=EDIT
) to retrieve the CREATE (EDIT) form. Default isEDIT
. Furthermore, addsots=<objectTypeId>
in order to specify a secondary object type of which properties should be included in the retrieved form. Thesots
query parameter can be added multiple times for different secondary object types.Returns
null
if there is no designed form model for the given object type.Optional query parameters:
Parameter Type Description situation
string
Create or edit a form. (default:
EDIT
)sots
list of strings
List of the secondary object types
Response HTTP status codes:
HTTP status code Meaning 200
OK
404
Not found
- Request Example
-
https://<host>/api-web/api/resources/forms/qadocscripts?situation=EDIT&sots=examplesot1&sot=examplesot2
no request body
- Response Example
-
200 OK
Response Body{ "name": "tenMytenant:qadocscripts", "situation": "EDIT", "script": "any valid script", "elements": [ { "name": "core", "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "name": "appClient:clienttitle", "type": "string", "rows": 1 }, { "name": "appClient:clientdescription", "type": "string", "rows": 1 } ] }, { "name": "data", "type": "o2mGroupStack", "elements": [ { "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:strsingle", "type": "string", "rows": 1 }, { "name": "tenMytenant:strsinglemail", "type": "string", "rows": 1 } ] }, { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:intsingle", "type": "integer" }, { "name": "tenMytenant:intsingledigit", "type": "integer" } ] } ] } ] } ] } ] }
POST /api-web/api/resources/forms/{type}
- Update the metadata form for the specified object type.
- As of version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available for users with the roles configured in
api-web.technical-roles
in theapi-web-prod.yml
configuration file. Default:YUUVIS_SYSTEM_INTEGRATOR
andYUUVIS_TENANT_ADMIN
- Description
-
Saves non-enriched form. Specify the fully qualified name of the form’s object type in the
type
path parameter.Optional query parameters:
Parameter Type Description sots
array[string]
List of the secondary object types
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
500
Internal Server Error
- Request Example
-
https://<host>/api-web/api/resources/forms/tenKolibri:email
Request Body{ "name": "tenMytenant:qadocscripts", "situation": "EDIT", "script": "any valid script", "elements": [ { "name": "core", "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "name": "appClient:clienttitle", "type": "string", "rows": 1 }, { "name": "appClient:clientdescription", "type": "string", "rows": 1 } ] }, { "name": "data", "type": "o2mGroupStack", "elements": [ { "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:strsingle", "type": "string", "rows": 1 }, { "name": "tenMytenant:strsinglemail", "type": "string", "rows": 1 } ] }, { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:intsingle", "type": "integer" }, { "name": "tenMytenant:intsingledigit", "type": "integer" } ] } ] } ] } ] } ] }
- Response Example
-
200 OK
Response Body{ "errors": [], "valid": true }
DELETE /api-web/api/resources/forms/{type}
- Delete the metadata form for the specified object type.
- As of version
-
2023 Winter
- Request Method
-
DELETE
- Response Format
-
JSON
- Required Permission
-
Available for users with the roles configured in
api-web.technical-roles
in theapi-web-prod.yml
configuration file. Default:YUUVIS_SYSTEM_INTEGRATOR
andYUUVIS_TENANT_ADMIN
- Description
-
Deletes non-enriched form. Specify the fully qualified name of the form’s object type in the
type
path parameter.Optional query parameters:
Parameter Type Description sots
array[string]
List of the secondary object types
Response HTTP status codes:
HTTP status code Meaning 200
OK
404
Form resource not found.
- Request Example
-
https://<host>/api-web/api/resources/forms/tenKolibri:email
no request body
- Response Example
-
200 OK
GET /api-web/api/resources/icons/{type}
- Retrieve the specified icon.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
SVG
- Description
-
Retrieves the SVG image used as icon for the specified object type ID
type
.Optional query parameters:
Parameter Type Description fallback
string
In case for the object type referenced by the
type
path parameter, no icon is available. The fallback icon is retrieved. It is referenced by object type ID as well.Response HTTP status codes:
HTTP status code Meaning 200
OK
404
Not found
- Request Example
-
https://<host>/api-web/api/resources/icons/tenKolibri:email?fallback=appInvoice:document
POST /api-web/api/resources/icons/{type}
- Update the specified icon.
- As of version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
Available for users with the roles configured in
api-web.technical-roles
in theapi-web-prod.yml
configuration file. Default:YUUVIS_SYSTEM_INTEGRATOR
andYUUVIS_TENANT_ADMIN
- Description
-
This request updates the icon for the object type specified by its object type ID
type
.Response HTTP status codes:
HTTP status code Meaning 201
CREATED
400
No icon was specified.
- Request Example
-
https://<host>/api-web/api/resources/icons/tenKolibri:email
Request Body<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"> <path d="M15 3H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V9l-6-6m4 16H5V5h9v5h5m-2 4H7v-2h10m-3 5H7v-2h7"/> </svg>
- Response Example
-
201 CREATED
DELETE /api-web/api/resources/icons/{type}
- Delete the specified icon.
- As of version
-
2023 Winter
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
Available for users with the roles configured in
api-web.technical-roles
in theapi-web-prod.yml
configuration file. Default:YUUVIS_SYSTEM_INTEGRATOR
andYUUVIS_TENANT_ADMIN
- Description
-
This request updates the icon for the object type specified by its object type ID
type
.Response HTTP status codes:
HTTP status code Meaning 201
OK
404
No icon was found.
- Request Example
-
https://<host>/api-web/api/resources/icons/tenKolibri:email
no request body
- Response Example
-
200 OK
GET /api-web/api/resources/text
- Retrieve the localized text resources for a specified locale.
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
HTTP status code
- Description
-
Modified behavior as of 2023 Winter.
Retrieves localized text resources for the
Accept-Language
specified in the request header formatted in ISO norm (e.g.,de
,en
,es
,fr
, …). Depending on optional query parameters, the endpoint retrieves the-
global localization file (
raw=true
), -
tenant-specific localization file (
raw=true&tenant=myfirsttenant
), -
app-specific localization file (
raw=true&app=myexampleapp
) OR -
merged localization file for the active tenant (
raw=false
).
The merged localization file is composed of tenant-specific, app-specific and global localizations.
Optional query parameters:
Parameter Type Description raw
boolean
If
false
or unspecified, the merged localization for the active tenant will be retrieved.If
true
, an unmerged configuration is retrieved.tenant
string
Only available if
raw
is set. Specify a tenant name for which you want to retrieve the tenant-specific localization file.app
string
Only available if
raw
is set. Specify an app name for which you want to retrieve the app-specific localization file.The response body is a JSON structure where each technical term as a key is mapped to a string value that will occur as a localized term in the graphical user interface.
Each technical term consists of a field identification (e.g.,
twosteptest_proc:test_table
) followed by either_label
or_description
in order to be displayed as field label or field description in the graphical user interface.If a technical term is mapped to null, localization has not yet been applied. The field identification will be displayed as field label in the graphical user interface. A description will not be provided.
Response HTTP status codes:
HTTP status code Meaning 200
OK
-
- Request Example
-
https://<host>/api-web/api/resources/text/en
no request body
- Response Example
-
200 OK
Response Body{ "tenExample:betreff_label": "Subject", "tenExample:betreff_description": null, "tenExample:strsingle_label": "String", "tenExample:strsingle_description": "unlimited", "tenExample:strregextime_label": "Time", "tenExample:strregextime_description": "Time format is 24 hours with hh:mm", "tenExample:strcataloggermancountries_label": "German countries", "tenExample:strcataloggermancountries_description": "single-field", "tenExample:strcataloggermancountriesro_label": "German countries", "tenExample:strcataloggermancountriesro_description": "single-field, read-only", "tenExample:intsingle_label": "Integer", "tenExample:intsingle_description": "unlimited", "tenExample:intsingledigit_label": "Integer", "tenExample:intsingledigit_description": "digit grouping", "tenExample:decsingle_label": "Decimal", "tenExample:decsingle_description": "unlimited", "tenExample:decsingledigit_label": "Decimal", "tenExample:decsingledigit_description": "digit grouping", "tenExample:datetimesingle_label": "Date & time", "tenExample:datetimesingle_description": "unlimited", "tenExample:datetimesinglerequired_label": "Date & time", "tenExample:datetimesinglerequired_description": "mandatory", "tenExample:datesingle_label": "Date2", "tenExample:datesingle_description": "unlimited", "tenExample:datesinglerequired_label": "Date1", "tenExample:datesinglerequired_description": "mandatory", "tenExample:booleanrequiredtrue_label": "Boolean", "tenExample:booleanrequiredtrue_description": "mandatory", "tenExample:booleannull_label": "Boolean Tri-State", "tenExample:booleannull_description": "Null allowed", "tenExample:extract2_label": "Extract & map", "tenExample:tablesimplefields_label": "Simple fields", "tenExample:tablesimplefields_description": "Table with simple fields", "tenExample:tableclassifications_label": "Fields with classifications", "tenExample:tableclassifications_description": "Table with classification fields", "tenExample:strorganizationsingle_label": "User/Group", "tenExample:strorganizationmulti_label": "Users/Groups", "tenExample:strcatalogfruitsmulti_label": "Fruits", "tenExample:strcatalogfruitmulti_description": "Apple,Banana,Pear,Plum,Pineapple (multi)", "tenExample:tablenotice_label": "Notice", "tenExample:tablecreatedate_label": "Date", "tenExample:tableuser_label": "User", "tenExample:tablereadonly_label": "Write protection", "tenExample:tablenumber_label": "Number", "tenExample:tablenumberdigit_label": "Digit-number", "tenExample:tabledistance_label": "Distance", "tenExample:tabledistancedigit_label": "Digit-distance", "tenExample:tablecreatedatetime_label": "Datetime", "tenExample:tableemail_label": "Email", "tenExample:tableurl_label": "URL", "tenExample:tablephone_label": "Phone", "tenExample:tablecatalog_label": "Catalog", "tenExample:tablereference_label": "Reference", "tenExample:simpleFields_label": "Simple Fields", "tenExample:classifications_label": "Classifications", "tenExample:number_label": "Number", "tenExample:number_description": "Will be filled via script", "tenExample:createdate_label": "Created", "tenExample:createdate_description": "Will be filled via script as well", "tenExample:notice_label": "Notice", "tenExample:notice_description": "To be filled by user", "tenExample:probability_label": "Probability", "tenExample:probability_description": "To be filled by user as well", "tenExample:readonly_label": "Read-only", "tenExample:readonly_description": "It's still unclear who will do it ...", "tenExample:required_label": "Mandatory fields", "tenExample:notrequired_label": "Without obligation", "tenExample:tableGroup_label": "Table group", "tenExample:tableFilling_label": "Table filling", "tenExample:process_label": "Approval process", "tenExample:process:0_label": "Draft in work", "tenExample:process:1_label": "Draft in review", "tenExample:process:2_label": "Draft in rework", "tenExample:process:3_label": "Document ready", "tenExample:process:4_label": "Approved", "tenExample:process:5_label": "Rejected", "tenExample:datetimemulti_label": "Date & time ", "tenExample:datetimemulti_description": "unlimited", "tenExample:strcatalogfruitmulti_label": "Fruits", "tenExample:strcatalogfruitsmulti_description": "Apple,Banana,Pear,Plum,Pineapple (multi)", "tenExample:Table Group_label": "My group", "twosteptest_proc_label": "Two step process", "twosteptest_proc:2nd_task": "Second task", "twosteptest_proc:simplefields_label": "Simple fields", "twosteptest_proc:complexfields_label": "Complex fields", "twosteptest_proc:datetime_label": "Date & time", "twosteptest_proc:date_label": "Date only", "twosteptest_proc:boolean_label": "boolean", "twosteptest_proc:integer_label": "Integer", "twosteptest_proc:decimal_label": "Decimal", "twosteptest_proc:string_label": "String", "twosteptest_proc:stringmultirow_label": "Multi-row string ", "twosteptest_proc:email_label": "Email", "twosteptest_proc:phone_label": "Phone", "twosteptest_proc:url_label": "URL", "twosteptest_proc:user_label": "User", "twosteptest_proc:reference_label": "Reference", "twosteptest_proc:catalogcustom_label": "Custom catalog", "twosteptest_proc:test_table_label": "Notices", "twosteptest_proc:test_table_description": "List of notices", "twosteptest_proc:column_string_label": "Notice", "twosteptest_proc:column_date_label": "Date", "twosteptest_proc:column_user_label": "User", "twosteptest_proc:column_boolean_label": "Editable", "userGroupAssignment:user_label": "User", "userGroupAssignment:user_description": "Assign the user who should ...", "userGroupAssignment:comment_label": "Comment", "userGroupAssignment:comment_description": "Tell the user what to do .." }
POST /api-web/api/resources/text/{locale}
- Update the localized text resources for a specified locale.
- As of version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
Available for users with the roles configured in
api-web.technical-roles
in theapi-web-prod.yml
configuration file. Default:YUUVIS_SYSTEM_INTEGRATOR
andYUUVIS_TENANT_ADMIN
- Description
-
This request updates a localized text resource for the specified
locale
. Additionally, via query parameter, the request can be executed EITHER for a specifictenant
OR a specificapp
.Optional query parameters:
Parameter Type Description tenant
string
Tenant
app
string
App
Only one of the two query parameters can be set per request.
Response HTTP status codes:
HTTP status code Meaning 201
CREATED
400
No text resources were specified.
- Request Example
-
https://<host>/api-web/api/resources/text/de
Request Body{ "system:baseTypeId_label": "Basistype ID", "system:objectTypeId_label": "Object-type ID", "system:createdBy_label": "Creator", "system:creationDate_label": "Created on", "system:lastModifiedBy_label": "Editor", "system:lastModificationDate_label": "Edited on", "system:versionNumber_label": "Version", "system:contentStreamLength_label": "File size", "system:contentStreamMimeType_label": "File type", "system:contentStreamFileName_label": "File name", "system:contentStreamId_label": "Content ID", "system:contentStreamRange_label": "Content range", "system:contentStreamRepositoryId_label": "Content stream repository", "system:digest_label": "Digest", "system:archivePath_label": "Archive path", "system:rmExpirationDate_label": "Retention date", "system:rmStartOfRetention_label": "Retention start", "system:rmDestructionDate_label": "Destruction date", "system:rmDestructionRetention_label": "Retention", "system:parentVersionNumber_label": "Folder version", "follow-up_label": "Follow-up", "follow-up_description": "This is a reminder to react on this object.", "review_label": "Review", "twosteptest_proc_label": "Two step process", "twosteptest_proc_description": "This little process tests task forms", "1st_task_label": "First task", "1st_task_description": "With this first task, a draft is to be prepared.", "2nd_task_label": "Second task", "2nd_task_description": "With this second task, the design is to be reviewed.", "appClient_label": "Client standards", "appClient:minidoc_label": "Smallest document", "appClient:minidoc_description": "01 Across all", "appClient:clientdefaults_label": "Object header", "appClient:clienttitle_label": "Name", "appClient:clientdescription_label": "Description", "appClientsystem:leadingType_label": "Leading object-type", "appClientsystem:leadingTypeId_label": "Type", "appClient:titledescription_label": "Name & Description", "appAcl:aclowner_label": "Access list", "appAcl:acl_label": "Access list", "appEmail_label": "Email (exchange)", "appEmail:email_label": "Email (exchange)", "appEmail:email_description": "01 Across all", "appEmail:from_label": "from", "appEmail:to_label": "to", "appEmail:cc_label": "cc", "appEmail:bcc_label": "bcc", "appEmail:subject_label": "Subject", "appEmail:attachmentcount_label": "Attachments", "appEmail:attachmentnames_label": "Attachment names", "appEmail:received_label": "Receive date", "appEmail:exchangeid_label": "Exchange ID", "appEmail:messageid_label": "Message ID", "appEmail:mode_label": "Mode", "appEmail:maildigest_label": "Email digest", "appEmail:meta_label": "Meta", "appEmail:datagroup_label": "Email data", "appInvoice_label": "Invoice processing", "appInvoice:zipreinvoice_label": "Invoice (general)", "appInvoice:zipreinvoice_description": "07 Invoice Management", "appInvoice:ziinvoicesot_label": "Invoice (ZUGFeRD)", "appInvoice:ziinvoicesot_description": "07 Invoice Management", "appInvoice:ziId_label": "Document ID", "appInvoice:ziName_label": "Document name", "appInvoice:ziTypeCode_label": "Type code", "appInvoice:ziPaymentReference_label": "Payment reference", "appInvoice:ziIssueDateTime_label": "Issue date", "appInvoice:ziDeliveryOccurence_label": "Delivery occurence", "appInvoice:ziDeliveryNoteId_label": "Delivery note ID", "appInvoice:ziDeliveryNoteDate_label": "Delivery note date", "appInvoice:ziOrderNoteId_label": "Order number", "appInvoice:ziOrderNoteDate_label": "Order date", "appInvoice:ziNotes_label": "Notes", "appInvoice:ziSellerId_label": "Seller ID", "appclient:dlm:prepare:0_label": "prepared", "appclient:dlm:prepare:1_label": "finished", "doctableofnotices_label": "DocTabelOfNotice", "tablecatalog_label": "Static catalog", "tablecreatedate_label": "Date", "tablecreatedatetime_label": "DateTime", "tabledistance_label": "Distance", "tabledistancedigit_label": "Distance digit", "tableemail_label": "Email", "tablenotice_label": "Notice", "tablenumber_label": "Number", "tablenumberdigit_label": "Number digit", "tableofnotices_label": "Table of notices", "tablephone_label": "Phone", "tablereadonly_label": "Boolean", "tablereference_label": "Reference", "tableurl_label": "URL", "tableuser_label": "User", "doctableofnotices_description": "01 Across all", "Table Group_label": "Meine Gruppe", "system:secondary_bale": "Alle sekundären Documente", "appInvoice:ziBuyerCity_label_label": "Stadt", "system:objectId_description": null, "system:baseTypeId_description": null, "system:objectTypeId_description": null, "system:secondaryObjectTypeIds_description": null, "system:createdBy_description": null, "system:creationDate_description": null, "system:lastModifiedBy_description": null, "system:lastModificationDate_description": null, "system:parentId_description": null, "system:parentObjectTypeId_description": null, "system:versionNumber_description": null, "system:tenant_description": null, "system:traceId_description": null, "system:tags_description": null, "system:contentStreamLength_description": null, "system:contentStreamMimeType_description": null, "system:contentStreamFileName_description": null, "system:contentStreamId_description": null, "system:contentStreamRange_description": null, "system:contentStreamRepositoryId_description": null, "system:digest_description": null, "system:archivePath_description": null, "system:rmExpirationDate_description": null, "system:rmStartOfRetention_description": null, "system:rmDestructionDate_description": null, "testsubject_label": null, "testsubject_description": null, "from_description": null, "to_description": null, "cc_description": null, "subject_description": null, "attachmentcount_description": null, "hasattachment_description": null, "attachmentnames_description": null, "received_description": null, "extract_label": "extract", "extract_description": null, "notice_description": null, "tableofnotices_description": null, "appClientcatalogs:catalogname_label": "Catalog name", "appClientcatalogs:catalogname_description": null, "appClientcatalogs:catalogvalue_label": "Catalog value", "appClientcatalogs:catalogvalue_description": null, "appClientcatalogs:active_label": "active", "appClientcatalogs_label": "Catalogs", "appClientcatalogs:active_description": null, "appClientcatalogs:catalogs_label": "Catalogs", "appClientcatalogs:catalogs_description": "01 Across all", "appClientcatalogs:lables_label": null, "appClientcatalogs:lables_description": null, "appClientcatalogs:labels_label": "Labels" }
- Response Example
-
201 CREATED
no response body
DELETE /api-web/api/resources/text/{locale}
- Delete the localized text resources for a specified locale.
- As of version
-
2023 Winter
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
Available for users with the roles configured in
api-web.technical-roles
in theapi-web-prod.yml
configuration file. Default:YUUVIS_SYSTEM_INTEGRATOR
andYUUVIS_TENANT_ADMIN
- Description
-
This request deletes a localized text resource for the specified
locale
. Additionally, via query parameter, the request can be executed EITHER for a specifictenant
OR a specificapp
.Optional query parameters:
Parameter Type Description tenant
string
Tenant
app
string
App
Only one of the two query parameters can be set per request.
Response HTTP status codes:
HTTP status code Meaning 200
OK
404
No text resources were found.
- Request Example
-
https://<host>/api-web/api/resources/text/de
no request body
- Response Example
-
200 OK
PATCH /api-web/api/resources/text/{locale}
- Update parts of the localized text resources for a specified locale.
- As of Version
-
2024 Summer
- Request Method
-
PATCH
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
andYUUVIS_SYSTEM_INTEGRATOR
roles. - Description
-
Updates the localization resource specified by
locale
with the data in the JSON request body. Only the keys specified in the request body are updated. All further keys remain unchanged.Optional query parameters:
tenant
string Specify a tenant name for which you want to update the tenant-specific localization file. app
string
Specify an app name for which you want to update the app-specific localization file.
If neither
app
nortenant
is specified, the global localization file will be updated.Response HTTP status codes:
HTTP status code Meaning 202
Accepted
400
No text resources were specified.
404
No text resources were found for update.
- Request Example
-
https://<host>/api-web/api/resources/text/en
Request Body{ "tenExample:betreff_label": "Subject", "tenExample:strregextime_label": "Time", "tenExample:strregextime_description": "Time format is 24 hours with hh:mm", "tenExample:strcataloggermancountries_label": "German countries" }
- Response Example
-
200 OK
Response Body{ "tenExample:betreff_label": "Subject", "tenExample:betreff_description": null, "tenExample:strsingle_label": "String", "tenExample:strsingle_description": "unlimited", "tenExample:strregextime_label": "Time", "tenExample:strregextime_description": "Time format is 24 hours with hh:mm", "tenExample:strcataloggermancountries_label": "German countries", "tenExample:strcataloggermancountries_description": "single-field", "tenExample:strcataloggermancountriesro_label": "German countries", "tenExample:strcataloggermancountriesro_description": "single-field, read-only", "tenExample:intsingle_label": "Integer", "tenExample:intsingle_description": "unlimited", "tenExample:intsingledigit_label": "Integer", "tenExample:intsingledigit_description": "digit grouping", "tenExample:decsingle_label": "Decimal", "tenExample:decsingle_description": "unlimited", "tenExample:decsingledigit_label": "Decimal", "tenExample:decsingledigit_description": "digit grouping", "tenExample:datetimesingle_label": "Date & time", "tenExample:datetimesingle_description": "unlimited", "tenExample:datetimesinglerequired_label": "Date & time", "tenExample:datetimesinglerequired_description": "mandatory", "tenExample:datesingle_label": "Date2", "tenExample:datesingle_description": "unlimited", "tenExample:datesinglerequired_label": "Date1", "tenExample:datesinglerequired_description": "mandatory", "tenExample:booleanrequiredtrue_label": "Boolean", "tenExample:booleanrequiredtrue_description": "mandatory", "tenExample:booleannull_label": "Boolean Tri-State", "tenExample:booleannull_description": "Null allowed", "tenExample:extract2_label": "Extract & map", "tenExample:tablesimplefields_label": "Simple fields", "tenExample:tablesimplefields_description": "Table with simple fields", "tenExample:tableclassifications_label": "Fields with classifications", "tenExample:tableclassifications_description": "Table with classification fields", "tenExample:strorganizationsingle_label": "User/Group", "tenExample:strorganizationmulti_label": "Users/Groups", "tenExample:strcatalogfruitsmulti_label": "Fruits", "tenExample:strcatalogfruitmulti_description": "Apple,Banana,Pear,Plum,Pineapple (multi)", "tenExample:tablenotice_label": "Notice", "tenExample:tablecreatedate_label": "Date", "tenExample:tableuser_label": "User", "tenExample:tablereadonly_label": "Write protection", "tenExample:tablenumber_label": "Number", "tenExample:tablenumberdigit_label": "Digit-number", "tenExample:tabledistance_label": "Distance", "tenExample:tabledistancedigit_label": "Digit-distance", "tenExample:tablecreatedatetime_label": "Datetime", "tenExample:tableemail_label": "Email", "tenExample:tableurl_label": "URL", "tenExample:tablephone_label": "Phone", "tenExample:tablecatalog_label": "Catalog", "tenExample:tablereference_label": "Reference", "tenExample:simpleFields_label": "Simple Fields", "tenExample:classifications_label": "Classifications", "tenExample:number_label": "Number", "tenExample:number_description": "Will be filled via script", "tenExample:createdate_label": "Created", "tenExample:createdate_description": "Will be filled via script as well", "tenExample:notice_label": "Notice", "tenExample:notice_description": "To be filled by user", "tenExample:probability_label": "Probability", "tenExample:probability_description": "To be filled by user as well", "tenExample:readonly_label": "Read-only", "tenExample:readonly_description": "It's still unclear who will do it ...", "tenExample:required_label": "Mandatory fields", "tenExample:notrequired_label": "Without obligation", "tenExample:tableGroup_label": "Table group", "tenExample:tableFilling_label": "Table filling", "tenExample:process_label": "Approval process", "tenExample:process:0_label": "Draft in work", "tenExample:process:1_label": "Draft in review", "tenExample:process:2_label": "Draft in rework", "tenExample:process:3_label": "Document ready", "tenExample:process:4_label": "Approved", "tenExample:process:5_label": "Rejected", "tenExample:datetimemulti_label": "Date & time ", "tenExample:datetimemulti_description": "unlimited", "tenExample:strcatalogfruitmulti_label": "Fruits", "tenExample:strcatalogfruitsmulti_description": "Apple,Banana,Pear,Plum,Pineapple (multi)", "tenExample:Table Group_label": "My group", "twosteptest_proc_label": "Two step process", "twosteptest_proc:2nd_task": "Second task", "twosteptest_proc:simplefields_label": "Simple fields", "twosteptest_proc:complexfields_label": "Complex fields", "twosteptest_proc:datetime_label": "Date & time", "twosteptest_proc:date_label": "Date only", "twosteptest_proc:boolean_label": "boolean", "twosteptest_proc:integer_label": "Integer", "twosteptest_proc:decimal_label": "Decimal", "twosteptest_proc:string_label": "String", "twosteptest_proc:stringmultirow_label": "Multi-row string ", "twosteptest_proc:email_label": "Email", "twosteptest_proc:phone_label": "Phone", "twosteptest_proc:url_label": "URL", "twosteptest_proc:user_label": "User", "twosteptest_proc:reference_label": "Reference", "twosteptest_proc:catalogcustom_label": "Custom catalog", "twosteptest_proc:test_table_label": "Notices", "twosteptest_proc:test_table_description": "List of notices", "twosteptest_proc:column_string_label": "Notice", "twosteptest_proc:column_date_label": "Date", "twosteptest_proc:column_user_label": "User", "twosteptest_proc:column_boolean_label": "Editable", "userGroupAssignment:user_label": "User", "userGroupAssignment:user_description": "Assign the user who should ...", "userGroupAssignment:comment_label": "Comment", "userGroupAssignment:comment_description": "Tell the user what to do .." }
system-controller
Endpoints of the Web API gateway for the management of global configuration data, accessible with the role specified for /api-web/api/system/**
endpoints in the authentication-prod.yml
configuration file.
The endpoints are used by yuuvis® architect. If you want to use this service, do not change the default access condition that is matched with the YUUVIS_SYSTEM_INTEGRATOR role.
|
GET /api-web/api/system/dms/catalogs
- Retrieve all catalog names.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the technical names of all catalogs grouped in lists depending on their global, app-specific or tenant-specific storage location.
Optional query parameters:
Parameter Type Description tenant
string
Retrieve only the catalogs available for the specified tenant.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
500
Internal Server Error
- Request Example
-
https://<host>/api-web/api/system/dms/catalogs
no request body
- Response Example
-
200 OK
Response Body{ "personalfile": [ "appPersonalfile:class" ], "global": [ "germancountry", "contracts", "germancountries", "globalnotice", "currency", "class", "clubs", "food", ], "invoice": [ "appInvoice:type" ], "mytenant": [ "germancountry", "contracts", "tenMytenant:My catalog", "germancountries", "globalnotice", "currency", "class", "appInvoice:type", "tenMytenant:processstatus", "appPersonalfile:class" ] }
GET /api-web/api/system/dms/catalogs/{qname}
- Retrieve the specified catalog.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the global or app-specific catalog specified by its name
qname
The endpoint returns
null
if no catalog withqname
was found in both global and app-specific resource.Optional query parameters:
Parameter Type Description tenant
string
Retrieve the tenant-specific catalog instead of the global or app-specific one.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not Found
- Request Example
-
https://<host>/api-web/api/system/dms/catalogs/appInvoice:type
no request body
- Response Example
-
200 OK
Response Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
POST /api-web/api/system/dms/catalogs/{qname}
- Create or update the specified catalog.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Updates the global or app-specific catalog identified by its name
qname
with the data passed in JSON format in the request body.If no global or app-specific catalog with name
qname
is available, it will be created.The response body is a JSON structure with the list errors containing possibly occured error messages, and the boolean valid that is
true
for a successfully validated JSON in the request body.Optional query parameters:
Parameter Type Description tenant
string
Update the tenant-specific catalog instead of the global or app-specific one.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
401
Unauthorized
403
Forbidden
- Request Example
-
https://<host>/api-web/api/system/dms/catalogs/processstatus?tenant=mytenant
Request Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
- Response Example
-
200 OK
Response Body{ "errors": [], "valid": true }
PATCH /api-web/api/system/dms/catalogs/{qname}
- Update the specified catalog.
- As of Version
-
2021 Summer
- Request Method
-
PATCH
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Updates the existing global or app-specific catalog identified by its name
qname
, with the data passed in JSON format in the request body.In the response body, the modified catalog will be returned.
If no global or app-specific catalog with name
qname
is available, an error will be thrown.Optional query parameters:
Parameter Type Description tenant
string
Update the tenant-specific catalog instead of the global or app-specific one.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
404
Not Found
500
Internal Server Error
- Request Example
-
https://<host>/api-web/api/system/dms/catalogs/contracts?tenant=mytenant
Request Body[ { "op": "replace", "path": "/entries/1/name", "value": "Rental agreement" }, { "op": "remove", "path": "/entries/3" }, { "op": "add", "path": "/entries/-", "value": { "name": "Purchase contract", "disabled": true } } ]
- Response Example
-
200 OK
Response Body{ "tenant": "mytenant", "readonly": false, "entries": [ { "name": "Employment contract", "disabled": false }, { "name": "Rental agreement", "disabled": false }, { "name": "User contract", "disabled": false }, { "name": "Purchase contract", "disabled": true } ] }
deprecated as of 2023 Winter: GET /api-web/api/system/dms/forms/{objecttype}
- Retrieve a metadata form for the specified object type.
Deprecated as of 2023 Winter. Please use GET /api-web/api/resources/forms/{type} .
|
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the global or app-specific non-enriched form by object type ID
objecttype
and optional query parameterssituation
andsots
(secondary object types).Behind the object type ID, add the query parameter
situation=CREATE
(situation=EDIT
) to retrieve the CREATE (EDIT) form. Default is EDIT. Furthermore, addsots=<objectTypeId>
in order to specify a secondary object type of which properties should be included in the retrieved form. Thesots
query parameter can be added multiple times for different secondary object types.Returns
null
if there is no designed form model for the given object type.Optional query parameters:
Parameter Type Description situation
string
The situation the form is used. (default:
EDIT
)sots
list of strings
List of the secondary object types
tenant
string
Retrieve the tenant-specific form instead of the global one.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/system/dms/forms/qadocscripts?tenant=mytenant&situation=EDIT&sots=examplesot1&sot=examplesot2
no request body
- Response Example
-
200 OK
Response Body{ "name": "tenMytenant:qadocscripts", "situation": "EDIT", "script": "any valid script", "elements": [ { "name": "core", "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "name": "appClient:clienttitle", "type": "string", "rows": 1 }, { "name": "appClient:clientdescription", "type": "string", "rows": 1 } ] }, { "name": "data", "type": "o2mGroupStack", "elements": [ { "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:strsingle", "type": "string", "rows": 1 }, { "name": "tenMytenant:strsinglemail", "type": "string", "rows": 1 } ] }, { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:intsingle", "type": "integer" }, { "name": "tenMytenant:intsingledigit", "type": "integer" } ] } ] } ] } ] } ] }
deprecated as of 2023 Winter: POST /api-web/api/system/dms/forms/{objecttype}
- Update a metadata form for the specified object type.
Deprecated as of 2023 Winter. Please use POST /api-web/api/resources/forms/{type} .
|
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the global or app-specific non-enriched form by object type ID
objecttype
and optional query parameterssituation
andsots
(secondary object types).Behind the object type ID, add the query parameter
sots=<objectTypeId>
in order to specify a secondary object type of which properties should be included in the retrieved form. The sots query parameter can be added multiple times for different secondary object types, separated by&
characters.Optional query parameters:
Parameter Type Description situation
string
The situation the form is used. (default:
EDIT
)sots
list of strings
List of the secondary object types. Individual values are separated by a
&
character.tenant
string
Update the tenant-specific form instead of the global or app-specific one.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/api-web/api/system/dms/forms/qadocscripts?tenant=mytenant&situation=EDIT&sots=examplesot1&sot=examplesot2
no request body
- Response Example
-
200 OK
Response Body{ "name": "tenMytenant:qadocscripts", "situation": "EDIT", "script": "any valid script", "elements": [ { "name": "core", "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "name": "appClient:clienttitle", "type": "string", "rows": 1 }, { "name": "appClient:clientdescription", "type": "string", "rows": 1 } ] }, { "name": "data", "type": "o2mGroupStack", "elements": [ { "type": "o2mGroup", "layout": { "align": "column" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:strsingle", "type": "string", "rows": 1 }, { "name": "tenMytenant:strsinglemail", "type": "string", "rows": 1 } ] }, { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "name": "tenMytenant:intsingle", "type": "integer" }, { "name": "tenMytenant:intsingledigit", "type": "integer" } ] } ] } ] } ] } ] }
deprecated as of 2023 Winter: GET /api-web/api/system/resources/config/{name}
- Retrieve the specified configuration.
Deprecated as of 2023 Winter. Please use GET /api-web/api/resources/config/{name} .
|
- As of Version
-
2020 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the global configuration file specified by
name
.Optional query parameters:
Parameter Type Description tenant
string
Retrieve the tenant-specific configuration instead of the global one.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
deprecated as of 2023 Winter: POST /api-web/api/system/resources/config/{name}
- Update the specified configuration.
Deprecated as of 2023 Winter. Please use POST /api-web/api/resources/config/{name} .
|
- As of Version
-
2020 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Creates or updates the global configuration file specified by
name
with the data passed in JSON format in the request body.Optional query parameters:
Parameter Type Description tenant
string
Update the tenant-specific configuration instead of the global one.
Response HTTP status codes:
HTTP status code Meaning 201
CREATED
401
Unauthorized
deprecated as of 2023 Winter: GET /api-web/api/system/resources/icons/{path}
- Retrieve a specified icon.
Deprecated as of 2023 Winter. Please use GET /api-web/api/resources/icons/{path} .
|
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
SVG
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves a global, app-specific, or tenant-specific icon resource specified by
path
as SVG image.Such icon endpoints are also available in the admin-controller and system-controller. They are intended to serve for the configuration of object type icons. Use the technical name of the corresponding object type as value for
path
.Optional query parameters:
Parameter Type Description tenant
string
Retrieve the tenant-specific icon instead of the global one.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
deprecated as of 2023 Winter: POST /api-web/api/system/resources/icons/{path}
- Update a specified icon
Deprecated as of 2023 Winter. Please use POST /api-web/api/resources/icons/{type} .
|
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Creates or updates the global or app-specific icon resource specified by path with the data passed as SVG image in a multipart request body.
Such icon endpoints are also available in the admin-controller and resource-controller. They are intended to serve for the configuration of object type icons. Use the technical name of the corresponding object type as a value for path, e.g.
tenMytenant:Invoice
orappMyapp:Contract
.These defined icons are global ones. If not other icons are saved via the admin endpoint for the specific tenant the global icons are delivered with the corresponding resources endpoint.
Optional query parameters:
Parameter Type Description tenant
string
Update the tenant-specific icon instead of the global one.
Response HTTP status codes:
HTTP status code Meaning 201
CREATED
400
No icon was specified.
401
Unauthorized
deprecated as of 2023 Winter: GET /api-web/api/system/resources/text
- Retrieve localized text resources.
Deprecated as of 2023 Winter. Please use GET /api-web/api/resources/text .
|
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves global localized text resources for the
Accept-Language
specified in the request header formatted in ISO norm (e.g.,de
,en
,es
,fr
, …)The response body is a JSON structure where each technical term as a key is mapped to a string value that will occur as a localized term in the graphical user interface.
Each technical term consists of a field identification (e.g.,
twosteptest_proc:test_table
) followed by either_label
or_description
in order to be displayed as field label or field description in the graphical user interface.If a technical term is mapped to
null
, localization has not yet been applied. The field identification will be displayed as field label in the graphical user interface. A description will not be provided.Optional query parameters:
Parameter Type Description tenant
string
Retrieve the tenant-specific text resources instead of the global one.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/system/resources/text
no request body
- Response Example
-
200 OK
Response Body{ "system:baseTypeId_label": "Basistype ID", "system:objectTypeId_label": "Object-type ID", "system:createdBy_label": "Creator", "system:creationDate_label": "Created on", "system:lastModifiedBy_label": "Editor", "system:lastModificationDate_label": "Edited on", "system:versionNumber_label": "Version", "system:contentStreamLength_label": "File size", "system:contentStreamMimeType_label": "File type", "system:contentStreamFileName_label": "File name", "system:contentStreamId_label": "Content ID", "system:contentStreamRange_label": "Content range", "system:contentStreamRepositoryId_label": "Content stream repository", "system:digest_label": "Digest", "system:archivePath_label": "Archive path", "system:rmExpirationDate_label": "Retention date", "system:rmStartOfRetention_label": "Retention start", "system:rmDestructionDate_label": "Destruction date", "system:rmDestructionRetention_label": "Retention", "system:parentVersionNumber_label": "Folder version", "follow-up_label": "Follow-up", "follow-up_description": "This is a reminder to react on this object.", "review_label": "Review", "twosteptest_proc_label": "Two step process", "twosteptest_proc_description": "This little process tests task forms", "1st_task_label": "First task", "1st_task_description": "With this first task, a draft is to be prepared.", "2nd_task_label": "Second task", "2nd_task_description": "With this second task, the design is to be reviewed.", "appClient_label": "Client standards", "appClient:minidoc_label": "Smallest document", "appClient:minidoc_description": "01 Across all", "appClient:clientdefaults_label": "Object header", "appClient:clienttitle_label": "Name", "appClient:clientdescription_label": "Description", "appClientsystem:leadingType_label": "Leading object-type", "appClientsystem:leadingTypeId_label": "Type", "appClient:titledescription_label": "Name & Description", "appAcl:aclowner_label": "Access list", "appAcl:acl_label": "Access list", "appEmail_label": "Email (exchange)", "appEmail:email_label": "Email (exchange)", "appEmail:email_description": "01 Across all", "appEmail:from_label": "from", "appEmail:to_label": "to", "appEmail:cc_label": "cc", "appEmail:bcc_label": "bcc", "appEmail:subject_label": "Subject", "appEmail:attachmentcount_label": "Attachments", "appEmail:attachmentnames_label": "Attachment names", "appEmail:received_label": "Receive date", "appEmail:exchangeid_label": "Exchange ID", "appEmail:messageid_label": "Message ID", "appEmail:mode_label": "Mode", "appEmail:maildigest_label": "Email digest", "appEmail:meta_label": "Meta", "appEmail:datagroup_label": "Email data", "appInvoice_label": "Invoice processing", "appInvoice:zipreinvoice_label": "Invoice (general)", "appInvoice:zipreinvoice_description": "07 Invoice Management", "appInvoice:ziinvoicesot_label": "Invoice (ZUGFeRD)", "appInvoice:ziinvoicesot_description": "07 Invoice Management", "appInvoice:ziId_label": "Document ID", "appInvoice:ziName_label": "Document name", "appInvoice:ziTypeCode_label": "Type code", "appInvoice:ziPaymentReference_label": "Payment reference", "appInvoice:ziIssueDateTime_label": "Issue date", "appInvoice:ziDeliveryOccurence_label": "Delivery occurence", "appInvoice:ziDeliveryNoteId_label": "Delivery note ID", "appInvoice:ziDeliveryNoteDate_label": "Delivery note date", "appInvoice:ziOrderNoteId_label": "Order number", "appInvoice:ziOrderNoteDate_label": "Order date", "appInvoice:ziNotes_label": "Notes", "appInvoice:ziSellerId_label": "Seller ID", "appclient:dlm:prepare:0_label": "prepared", "appclient:dlm:prepare:1_label": "finished", "doctableofnotices_label": "DocTabelOfNotice", "tablecatalog_label": "Static catalog", "tablecreatedate_label": "Date", "tablecreatedatetime_label": "DateTime", "tabledistance_label": "Distance", "tabledistancedigit_label": "Distance digit", "tableemail_label": "Email", "tablenotice_label": "Notice", "tablenumber_label": "Number", "tablenumberdigit_label": "Number digit", "tableofnotices_label": "Table of notices", "tablephone_label": "Phone", "tablereadonly_label": "Boolean", "tablereference_label": "Reference", "tableurl_label": "URL", "tableuser_label": "User", "doctableofnotices_description": "01 Across all", "Table Group_label": "Meine Gruppe", "system:secondary_bale": "Alle sekundären Documente", "appInvoice:ziBuyerCity_label_label": "Stadt", "system:objectId_description": null, "system:baseTypeId_description": null, "system:objectTypeId_description": null, "system:secondaryObjectTypeIds_description": null, "system:createdBy_description": null, "system:creationDate_description": null, "system:lastModifiedBy_description": null, "system:lastModificationDate_description": null, "system:parentId_description": null, "system:parentObjectTypeId_description": null, "system:versionNumber_description": null, "system:tenant_description": null, "system:traceId_description": null, "system:tags_description": null, "system:contentStreamLength_description": null, "system:contentStreamMimeType_description": null, "system:contentStreamFileName_description": null, "system:contentStreamId_description": null, "system:contentStreamRange_description": null, "system:contentStreamRepositoryId_description": null, "system:digest_description": null, "system:archivePath_description": null, "system:rmExpirationDate_description": null, "system:rmStartOfRetention_description": null, "system:rmDestructionDate_description": null, "testsubject_label": null, "testsubject_description": null, "from_description": null, "to_description": null, "cc_description": null, "subject_description": null, "attachmentcount_description": null, "hasattachment_description": null, "attachmentnames_description": null, "received_description": null, "extract_label": "extract", "extract_description": null, "notice_description": null, "tableofnotices_description": null, "appClientcatalogs:catalogname_label": "Catalog name", "appClientcatalogs:catalogname_description": null, "appClientcatalogs:catalogvalue_label": "Catalog value", "appClientcatalogs:catalogvalue_description": null, "appClientcatalogs:active_label": "active", "appClientcatalogs_label": "Catalogs", "appClientcatalogs:active_description": null, "appClientcatalogs:catalogs_label": "Catalogs", "appClientcatalogs:catalogs_description": "01 Across all", "appClientcatalogs:lables_label": null, "appClientcatalogs:lables_description": null, "appClientcatalogs:labels_label": "Labels" }
deprecated as of 2023 Winter: POST /api-web/api/system/resources/text/{locale}
- Update localized text resources for the specified language.
Deprecated as of 2023 Winter. Please use POST /api-web/api/resources/text/{locale} .
|
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Creates or updates the global localized text resources for the active tenant and the specified
locale
formatted in ISO norm, e.g.,de
,en
,es
,fr
, ….The request body is a JSON structure where each technical term as a key is mapped to a string value that will occur as a localized term in the graphical user interface.
Each technical term consists of a field identification (e.g.,
twosteptest_proc:test_table
) followed by either_label
or_description
in order to be displayed as field label or field description in the graphical user interface.If a technical term is mapped to
null
, localization has not yet been applied. The field identification will be displayed as field label in the graphical user interface. A description will not be provided.Optional query parameters:
Parameter Type Description tenant
string
Update the tenant-specific localized text resources instead of the global one.
Response HTTP status codes:
HTTP status code Meaning 201
CREATED
400
No text resources were specified.
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/system/resources/text/en
Request Body{ "system:baseTypeId_label": "Basistype ID", "system:objectTypeId_label": "Object-type ID", "system:createdBy_label": "Creator", "system:creationDate_label": "Created on", "system:lastModifiedBy_label": "Editor", "system:lastModificationDate_label": "Edited on", "system:versionNumber_label": "Version", "system:contentStreamLength_label": "File size", "system:contentStreamMimeType_label": "File type", "system:contentStreamFileName_label": "File name", "system:contentStreamId_label": "Content ID", "system:contentStreamRange_label": "Content range", "system:contentStreamRepositoryId_label": "Content stream repository", "system:digest_label": "Digest", "system:archivePath_label": "Archive path", "system:rmExpirationDate_label": "Retention date", "system:rmStartOfRetention_label": "Retention start", "system:rmDestructionDate_label": "Destruction date", "system:rmDestructionRetention_label": "Retention", "system:parentVersionNumber_label": "Folder version", "follow-up_label": "Follow-up", "follow-up_description": "This is a reminder to react on this object.", "review_label": "Review", "twosteptest_proc_label": "Two step process", "twosteptest_proc_description": "This little process tests task forms", "1st_task_label": "First task", "1st_task_description": "With this first task, a draft is to be prepared.", "2nd_task_label": "Second task", "2nd_task_description": "With this second task, the design is to be reviewed.", "appClient_label": "Client standards", "appClient:minidoc_label": "Smallest document", "appClient:minidoc_description": "01 Across all", "appClient:clientdefaults_label": "Object header", "appClient:clienttitle_label": "Name", "appClient:clientdescription_label": "Description", "appClientsystem:leadingType_label": "Leading object-type", "appClientsystem:leadingTypeId_label": "Type", "appClient:titledescription_label": "Name & Description", "appAcl:aclowner_label": "Access list", "appAcl:acl_label": "Access list", "appEmail_label": "Email (exchange)", "appEmail:email_label": "Email (exchange)", "appEmail:email_description": "01 Across all", "appEmail:from_label": "from", "appEmail:to_label": "to", "appEmail:cc_label": "cc", "appEmail:bcc_label": "bcc", "appEmail:subject_label": "Subject", "appEmail:attachmentcount_label": "Attachments", "appEmail:attachmentnames_label": "Attachment names", "appEmail:received_label": "Receive date", "appEmail:exchangeid_label": "Exchange ID", "appEmail:messageid_label": "Message ID", "appEmail:mode_label": "Mode", "appEmail:maildigest_label": "Email digest", "appEmail:meta_label": "Meta", "appEmail:datagroup_label": "Email data", "appInvoice_label": "Invoice processing", "appInvoice:zipreinvoice_label": "Invoice (general)", "appInvoice:zipreinvoice_description": "07 Invoice Management", "appInvoice:ziinvoicesot_label": "Invoice (ZUGFeRD)", "appInvoice:ziinvoicesot_description": "07 Invoice Management", "appInvoice:ziId_label": "Document ID", "appInvoice:ziName_label": "Document name", "appInvoice:ziTypeCode_label": "Type code", "appInvoice:ziPaymentReference_label": "Payment reference", "appInvoice:ziIssueDateTime_label": "Issue date", "appInvoice:ziDeliveryOccurence_label": "Delivery occurence", "appInvoice:ziDeliveryNoteId_label": "Delivery note ID", "appInvoice:ziDeliveryNoteDate_label": "Delivery note date", "appInvoice:ziOrderNoteId_label": "Order number", "appInvoice:ziOrderNoteDate_label": "Order date", "appInvoice:ziNotes_label": "Notes", "appInvoice:ziSellerId_label": "Seller ID", "appclient:dlm:prepare:0_label": "prepared", "appclient:dlm:prepare:1_label": "finished", "doctableofnotices_label": "DocTabelOfNotice", "tablecatalog_label": "Static catalog", "tablecreatedate_label": "Date", "tablecreatedatetime_label": "DateTime", "tabledistance_label": "Distance", "tabledistancedigit_label": "Distance digit", "tableemail_label": "Email", "tablenotice_label": "Notice", "tablenumber_label": "Number", "tablenumberdigit_label": "Number digit", "tableofnotices_label": "Table of notices", "tablephone_label": "Phone", "tablereadonly_label": "Boolean", "tablereference_label": "Reference", "tableurl_label": "URL", "tableuser_label": "User", "doctableofnotices_description": "01 Across all", "Table Group_label": "Meine Gruppe", "system:secondary_bale": "Alle sekundären Documente", "appInvoice:ziBuyerCity_label_label": "Stadt", "system:objectId_description": null, "system:baseTypeId_description": null, "system:objectTypeId_description": null, "system:secondaryObjectTypeIds_description": null, "system:createdBy_description": null, "system:creationDate_description": null, "system:lastModifiedBy_description": null, "system:lastModificationDate_description": null, "system:parentId_description": null, "system:parentObjectTypeId_description": null, "system:versionNumber_description": null, "system:tenant_description": null, "system:traceId_description": null, "system:tags_description": null, "system:contentStreamLength_description": null, "system:contentStreamMimeType_description": null, "system:contentStreamFileName_description": null, "system:contentStreamId_description": null, "system:contentStreamRange_description": null, "system:contentStreamRepositoryId_description": null, "system:digest_description": null, "system:archivePath_description": null, "system:rmExpirationDate_description": null, "system:rmStartOfRetention_description": null, "system:rmDestructionDate_description": null, "testsubject_label": null, "testsubject_description": null, "from_description": null, "to_description": null, "cc_description": null, "subject_description": null, "attachmentcount_description": null, "hasattachment_description": null, "attachmentnames_description": null, "received_description": null, "extract_label": "extract", "extract_description": null, "notice_description": null, "tableofnotices_description": null, "appClientcatalogs:catalogname_label": "Catalog name", "appClientcatalogs:catalogname_description": null, "appClientcatalogs:catalogvalue_label": "Catalog value", "appClientcatalogs:catalogvalue_description": null, "appClientcatalogs:active_label": "active", "appClientcatalogs_label": "Catalogs", "appClientcatalogs:active_description": null, "appClientcatalogs:catalogs_label": "Catalogs", "appClientcatalogs:catalogs_description": "01 Across all", "appClientcatalogs:lables_label": null, "appClientcatalogs:lables_description": null, "appClientcatalogs:labels_label": "Labels" }
- Response Example
-
201 CREATED
no response body
GET /api-web/api/system/resources/text/languages
- Retrieve a list of supported languages.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves a list of all supported languages for global resources.
Optional query parameters:
Parameter Type Description tenant
string
Retrieve the supported languages for the specified tenant instead of the global ones.
Response HTTP status codes:
HTTP status code Meaning 200
OK
201
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/system/resources/text/languages
no request body
- Response Example
-
200 OK
Response Body[ "fr", "en", "it", "pt", "es", "de", "ru", "sv" ]
user-controller
Endpoints for user settings management, accessible for any authenticated user.
The userservice API is required.
|
GET /api-web/api/users/config/result/{type}
- Retrieve the result list configuration for the logged-in user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Returns a result list configuration by type.
Optional query parameters:
Parameter Type Description sots
list of string
List of secondary object types.
fallback
string
Name of the fallback object type.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad request
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/users/config/result/mytype
no request body
- Response Example
-
200 OK
Response Body{ "type": "string", "isDefault": true, "columns": [ { "id": "string", "sort": { "order": "string" }, "pinned": true } ] }
POST /api-web/api/users/config/result/{type}
- Update the result list configuration for the logged-in user.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Description
-
Updates a result list configuration by type.
Optional query parameters:
Parameter Type Description sots
list of string
List of secondary object types.
Response HTTP status codes:
HTTP status code Meaning 200
OK
- Request Example
-
https://<host>/api-web/api/users/config/result/mytype
Request Body{ "type": "string", "isDefault": true, "columns": [ { "id": "string", "sort": { "order": "string" }, "pinned": true } ] }
- Response Example
-
200 OK
no response body
GET /api-web/api/users/settings
- Retrieve settings for the logged-in user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the general settings of the requested user.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
https://<host>/api-web/api/users/settings
no request body
- Response Example
-
200 OK
Response Body{ "locale": "string" }
POST /api-web/api/users/settings
-Update settings for the logged-in user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
HTTP status code
- Description
-
Saves a general settings for the user.
Response HTTP status codes:
HTTP status code Meaning 200
OK
- Request Example
-
https://<host>/api-web/api/users/settings
Request Body{ "locale": "string" }
- Response Example
-
200 OK
no response body
GET /api-web/api/users/settings/{section}
- Retrieve the specified settings section for the logged-in user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the settings of the requested user matching the
section
name.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
POST /api-web/api/users/settings/{section}
- Update the specified settings section for the logged-in user.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Description
-
Saves a settings for the user by a
section
.Response HTTP status codes:
HTTP status code Meaning 200
OK
4.1.2. Search via Web API
Parameters in Search Requests
The search endpoint POST /api-web/api/dms/objects/search
of the Web API gateway accepts a JSON request body with specific parameters in a specific structure. The following optional parameters can be specified.
Parameter | Type | Description | ||
---|---|---|---|---|
Offset and Size of Result List |
If the parameters should be included in the request, they have to be specified at the beginning of the JSON structure. example
|
|||
|
integer |
The optional parameter from sets the offset for the result list, default is 0. |
||
|
integer |
The optional parameter size allows you to configure the maximum amount of hits to be returned, default is 20. |
||
Full-text Search Term |
||||
|
string |
The parameter is used to request a full-text search. example
If the specified query string consists of multiple words, it is parsed into a series of individual words connected by operators. Per default, individual words are connected by
For each object in the result list, the |
||
|
string |
As of 2023 Winter. Specifies whether to search in text renditions or string metadata or both. Available values: |
||
Sorting |
||||
|
map of strings |
The parameter arranges the result list in ascending ( example
Default sorting:
|
||
Properties in Result List |
||||
|
list of strings |
Defines the objects' properties to be displayed in the result list. example
|
||
Conditions on Metadata |
||||
|
JSON |
Contains conditions for filtering the result list based on the objects' metadata. The structure and subparameters are described below. |
||
|
JSON |
Contains conditions for filtering by a table property. Its structure is similar to the |
||
Aggregation |
||||
|
list strings |
Specify a list of one or more property IDs (combined by
|
||
Secondary Object Type(s) |
||||
|
A list of secondary object types combined by OR. At least one of these secondary object types must be assigned to the DMS objects to be included in the result list. |
|
||
|
A list of leading object types combined by |
|
Filtering
The subparameter lo
is used to combine several logical conditions (default value: AND
). If there is only one logical condition or the conditions are combined by AND
, the subparameter lo
can be omitted.
Each entry in the filters subparameter list configures a condition by means of the following subparameters:
-
Via the subparameter
f
, the ID of a property can be specified. The value of this property should match the condition. -
The subparameter
o
describes the relationship between the subparameterf
and the value to comparev
. The list of allowed comparison operators is given below.If
o
is not specified, the default operatorcontains
is used. In themain.json
configuration file, the default operator con be changed toin
(default up to 2023 Autumn). -
The subparameter
v
contains the values to compare. The following types of comparing values are possible:Type Example string
"Meier"
numeric
50
date/datetime
"2016-01-01T00:00:00.000Z"
logical
"true", "false"
Regardless of the type, it is possible to use a null value to indicate that the corresponding property does not have any value.
-
The subparameter
useNot
reverses the meaning of the preceding logical comparison. While, e.g.,"f": "system:versionNumber", "eq": 1, "v": 1
returns all objects with version number 1, the additional subparameter
"notUse": "true"
ensures that all objects are returned that do NOT have this version number.
Available Comparison Operators:
Operator | Description | Example |
---|---|---|
|
Returns objects with values that are equal to |
|
|
Returns objects that match at least one of the provided values (value has to be an array), i.e., list of terms combined by An array of values to compare must be specified. Default comparison operator up to 2023 Autumn. Can be configured in |
|
|
Returns objects with values greater than |
|
|
Returns objects with values greater than or equal to |
similar to |
|
Returns objects with values less than |
similar to |
|
Returns objects with values less than or equal to |
similar to |
|
Returns objects with values within the specified interval: greater than |
|
|
Returns objects with values within the specified interval: greater than or equal to |
similar to |
|
Returns objects with values within the specified interval: greater than |
similar to |
|
Returns objects with values within the specified interval: greater than or equal to |
similar to |
|
Used to search for a specific pattern with wildcards. The A maximum number of 10 |
|
|
As of 2023 Autumn. Performs full-text search for the specified field. Default comparison operator as of 2023 Winter. Can be configured in |
|
"filters":
[ {
"lo": "<logical operator>",
"filters":
[
{
"f": "<field1>",
"v1": <comparing value1>,
"o": "<comparison operator1>",
"useNot": <"true" or "false">
},
{
"f": "<field2>",
"v2": <comparing value2>,
"o": "<comparison operator2>"
}
...
]
}
]
As of 2022 Winter, the tableFilters
section can be specified. Its structure is similar to the filters
section as shown in the following example code. Specify the ID of the table property to which you want to apply conditions as value for table. In the columnFilters
list, specify the individual conditions that are connected with a logical AND
. Thus, they have to be matched in the SAME TABLE ROW.
{
"size": 50,
"lots": ["appMyapp:invoice"],
"fields": [
"appClient:clienttitle",
"system:objectId",
"appMyapp:accountassignment"
],
"tableFilters": [
{
"table": "appMyapp:accountassignment",
"columnFilters": [
{
"f": "account",
"o": "eq",
"v1": "123456"
} ,
{
"f": "grossamount",
"o": "gt",
"v1": "1000"
}
]
}
]
}
Example Request and Response
The following code blocks show an example request body using all parameters described above and a corresponding example response body.
Each search request for DMS objects always returns a list of DMS objects called objects. If only one object matches the search query, the result is a single-element list. If no object matches the query, the response body contains an empty objects list.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
curl -X 'POST' \
'https://kolibri.enaioci.net/api-web/api/dms/objects/search' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"from": 4,
"size": 10,
"term": "Martin",
"sort": [
{
"field" : "system:versionNumber",
"order" : "desc"
}
],
"fields":
[
"system:createdBy",
"system:creationDate",
"system:objectTypeId",
"system:versionNumber"
],
"types": [
"appPersonalfile:dossier"
],
"filters":
[
{
"lo": "OR",
"filters":
[
{
"f": "system:versionNumber",
"v1": 1,
"o": "eq",
"useNot": true
},
{
"f": "system:tenant",
"v1": "kolibri",
"o": "eq"
}
]
},
{
"f": "system:creationDate",
"o": "gtelte",
"v1": "2010-01-01T00:00:00.000Z",
"v2": "2021-01-10T00:00:00.000Z"
},
{
"f": "system:lastModifiedBy",
"v1": "?685*",
"o": "like"
}
],
"aggs": [
"appClientsystem:leadingTypeId"
],
"sots": [
"appClient:clientdefaults"
],
"lots": [
"appClientsystem:leadingTypeId"
]
}'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{
"objects": [
{
"properties": {
"system:createdBy": {
"title": "Schubert, Martin",
"value": "2612df3a-1cf8-4da3-968c-0a4a10b48921" },
"system:creationDate": {
"value": "2020-11-16T10:23:56.740Z"
},
"system:objectTypeId": {
"value": "tenKolibri:qadoctableofnotices"
},
"system:versionNumber": {
"value": 14
}
}
},
{
"properties": {
"system:createdBy": {
"title": "Schubert, Martin",
"value": "2612df3a-1cf8-4da3-968c-0a4a10b48921" },
"system:creationDate": {
"value": "2020-09-02T13:03:25.680Z"
},
"system:objectTypeId": {
"value": "appPersonalfile:pfdocumentdlm"
},
"system:versionNumber": {
"value": 10
}
}
},
{
"properties": {
"system:createdBy": {
"title": "Wayne, Bruce",
"value": "e823c59a-e073-40e1-af0a-e95e08a8e36c"
},
"system:creationDate": {
"value": "2020-10-22T10:49:24.290Z"
},
"system:objectTypeId": {
"value": "appEmail:email"
},
"system:versionNumber": {
"value": 9
}
}
},
{
"properties": {
"system:createdBy": {
"title": "Lauterbach, Ralf",
"value": "0b09ef34-2954-451c-9ebc-a898020bd004"
},
"system:creationDate": {
"value": "2020-07-22T11:08:03.870Z"
},
"system:objectTypeId": {
"value": "appClient:minidoc"
},
"system:versionNumber": {
"value": 8
}
}
},
{
"properties": {
"system:createdBy": {
"title": "Miller, Brad",
"value": "a2f7e1aa-ff42-4140-b9ec-5de4cc61f1a5"
},
"system:creationDate": {
"value": "2020-12-17T08:30:26.380Z"
},
"system:objectTypeId": {
"value": "tenKolibri:qadoctableofnotices"
},
"system:versionNumber": {
"value": 8
}
}
},
{
"properties": {
"system:createdBy": {
"title": "Schubert, Martin",
"value": "2612df3a-1cf8-4da3-968c-0a4a10b48921"
},
"system:creationDate": {
"value": "2020-02-13T18:48:03.860Z"
},
"system:objectTypeId": {
"value": "appPhotoarchive:paphoto"
},
"system:versionNumber": {
"value": 8
}
}
},
],
"numItems": 5,
"hasMoreItems": true,
"totalNumItems": 160
}
4.1.3. Localization Management
The schema definition contains technical names for fields and object types. These fields are not really "readable" for users. To provide users with more meaningful terms in any language they may need, you have to create the respective language files. With the installation of the system, some global default settings are given for English and German language regarding the internal system fields.
The JSON-format for labels
The localization is in JSON format and contains key-value pairs. The key is the technical name of an object type or a field ending with _label and _description. The value is displayed by the client instead of the technical names referenced in the key.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{
"system:folder_label": "All folders",
"system:folder_description" : "01 Across all",
"system:document_label": "All Documents",
"system:document_description": "01 Across all",
"system:secondary_bale": "All secondary documents",
"system:secondary_description": "01 Across all",
"system:baseTypeId_label": "Basistype ID",
"system:objectTypeId_label": "Object type ID",
"system:secondaryObjectTypeIds_label": "Characteristics",
"system:parentObjectTypeId_label": "Folder type",
"system:objectId_label": "Object ID",
"system:parentId_label": "Folder ID",
"system:createdBy_label": "Creator",
"system:creationDate_label": "Created on",
"system:lastModifiedBy_label": "Editor",
"system:lastModificationDate_label": "Edited on",
"system:versionNumber_label": "Version",
"system:acl_label": "Access list",
"system:tenant_label": "Tenant",
"system:traceId_label": "Trace ID",
"system:tags_label": "Tags",
"system:contentStreamLength_label": "File size",
"system:contentStreamMimeType_label": "File type",
"system:contentStreamFileName_label": "File name",
"system:contentStreamId_label": "Content ID",
"system:contentStreamRange_label": "Content range",
"system:contentStreamRepositoryId_label": "Content stream repository",
"system:digest_label": "Digest",
"system:archivePath_label": "Archive path",
"system:rmExpirationDate_label": "Retention date",
"system:rmStartOfRetention_label": "Retention start",
"system:rmDestructionDate_label": "Destruction date",
"system:rmDestructionRetention_label": "Retention",
"system:parentVersionNumber_label": "Folder version",
"follow-up_label": "Follow-up",
"expiryDateTime_label": "Follup-up date",
"businessKey_label": "Object",
"whatAbout_label": "Subject",
"startTime_label": "Start time",
"task_label": "Reminder",
"type_label": "Type",
"undefined_label": "",
"document_label": "Document",
"document_description": "01 Across all",
"appClient_label": "Client standards",
"appClient:minidoc_label": "Smallest document",
"appClient:minidoc_description": "01 Across all",
"appClient:clientdefaults_label": "Object header",
"appClient:clienttitle_label": "Title",
"appClient:clientdescription_label": "Description",
"appClientsystem:leadingType_label": "Type",
"appClientsystem:leadingTypeId_label": "Type"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{
"system:folder_label": "Alle Ordner",
"system:folder_description": "01 Übergreifend",
"system:document_label": "Alle Dokumente",
"system:document_description": "01 Übergreifend",
"system:secondary_label": "Alle sekundären Dokumente",
"system:secondary_description": "01 Übergreifend",
"system:baseTypeId_label": "Basistyp",
"system:objectTypeId_label": "Typ",
"system:secondaryObjectTypeIds_label": "Characteristika",
"system:parentObjectTypeId_label": "Ordnertyp",
"system:objectId_label": "Objekt-ID",
"system:parentId_label": "Ordner-ID",
"system:createdBy_label": "Ersteller",
"system:creationDate_label": "Erstellt am",
"system:lastModifiedBy_label": "Bearbeiter",
"system:lastModificationDate_label": "Bearbeitet am",
"system:versionNumber_label": "Version",
"system:acl_label": "Zugriffsliste",
"system:tenant_label": "Mandant",
"system:traceId_label": "Trace-ID",
"system:tags_label": "Tags",
"system:contentStreamLength_label": "Dateigröße",
"system:contentStreamMimeType_label": "Dateityp",
"system:contentStreamFileName_label": "Dateiname",
"system:contentStreamId_label": "Dateistrom-ID",
"system:contentStreamRange_label": "Dateistrombereich",
"system:contentStreamRepositoryId_label": "Dateistrom-Repository",
"system:digest_label": "Digest",
"system:archivePath_label": "Archivpfad",
"system:rmExpirationDate_label": "Aufbewahrungsdatum",
"system:rmStartOfRetention_label": "Aufbewahrungsstart",
"system:rmDestructionDate_label": "Aussonderungsdatum",
"system:rmDestructionRetention_label": "Aufbewahrung",
"system:parentVersionNumber_label": "Ordner-Version",
"follow-up_label": "Wiedervorlage",
"expiryDateTime_label": "Wiedervorlagedatum",
"businessKey_label": "Objekt",
"whatAbout_label": "Betreff",
"startTime_label": "Startzeitpunkt",
"task_label": "Erinnerung Wiedervorlage",
"type_label": "Type",
"undefined_label": "",
"document_label": "Dokument",
"document_description": "01 Übergreifend",
"appClient_label": "Client-Standards",
"appClient:minidoc_label": "Kleinstes Dokument",
"appClient:minidoc_description": "01 Übergreifend",
"appClient:clientdefaults_label": "Objektkopf",
"appClient:clienttitle_label": "Titel",
"appClient:clientdescription_label": "Beschreibung",
"appClientsystem:leadingType_label": "Typ",
"appClientsystem:leadingTypeId_label": "Typ"
}
For object types, the _description
is used to group them in the object type selection dialog, e.g., for search or creation:
Recommendation: Group all extending object types in a group names 'Extension'. This may help the user in differentiating in object types that can be used for instantiating an object and those that can extend an existing object.
For field names, the _description
is shown below the form field.
Adjusting Localization Procedures
-
Open the resource-controller.
-
Click the URL
..api/resource/text/{locale}
to open the management form. -
Click Try it out.
-
Copy the JSON-formatted data into the resource input field and enter the DIN value for the corresponding language, e.g.,
de
for Deutsch, anden
for English. -
If you want to update the labels for a tenant that you are not logged in to, provide a tenant name as a parameter. In the default configuration, this option is available only for users with the role
YUUVIS_SYSTEM_INTEGRATOR
. -
If you want to update the app text resources, provide the app name as a parameter.
-
Click Execute to save the data.
-
Check the response message area to make sure that the data really has been saved as described.
-
Open the resource-controller.
-
Click on the URL
../resources/text
to open the management form. -
Click Try it out.
-
Type the DIN value for the corresponding language, e.g.,
de
for Deutsch, anden
for English. -
You will get merged text. As default you will get global and app text resources merged with tenant resources for the requested locale with fallback to the default locale that is configured for
api-web
. -
Only users with the role YUUVIS_SYSTEM_INTEGRATOR can request the resources for a tenant that they are not logged-in to. If the
raw
parameter istrue
, the fallback to the default locale is not possible. -
Click Execute to display all key-value pairs for labels and descriptions in the Response Body.
4.1.4. Icon Management
In order to enhance the user experience of your client, you can configure icons for the different object types that will be displayed together with objects instantiated of the corresponding types. The icons are stored via the core system’s configservice
either in the global or in the tenant-specific resources. The corresponding endpoints are Web API Gateway Endpoints and thus also available via Swagger UI. The icons are expected as SVG files not larger than 512 KB.
The endpoint GET /api-web/api/system/resources/icon/{path}
retrieves the icon resource if available. If not available, a fallback icon can be returned.
Each icon is introduced into the system together with an object type ID to identify it in retrieval calls. The retrieval (GET) endpoint expects an object type ID and returns the corresponding icon (if available). If the specified object type ID is not available in the corresponding resource(s), a default icon will be returned. Alternatively, a fallback icon can be specified in addition to the desired icon. If the fallback icon was not found, the default icon will be returned.
Icons in yuuvis® client as reference implementation
The icons are not configured automatically during the installation process, but have to be introduced manually afterwards. Use the technical names of object types as keys for the icon identification. For the fallback icons, the following three keys are available:
key for fallback icon | object types for which the fallback is configured |
---|---|
|
all folder object types |
|
all document object types without floating secondary object types referenced in the schema definition |
|
all document object types with floating secondary object types referenced in the schema definition |
Recommended Icons
We recommend to use the icons of material icons as they will blend in with the design of all the other icons used in our client framework. A basic set of icons is already included in the framework library, which is delivered together with the reference client.
Managing Icons via Swagger UI
-
Open the resource-controller.
-
Click on the endpoint
POST /api-web/resources/icon/{type}
to open the management form. -
Only users with the role
YUUVIS_SYSTEM_INTEGRATOR
can update or add icons for a tenant that they are not logged in to. -
Click Try it out
-
Select a file for the icon. It must be an SVG file and not larger than 512 KByte.
-
Enter the fully qualified technical name of an object type, e.g.,
email
ortenKolibri:invoice
. -
Click Execute to save the data.
-
Check the response message area to make sure that the data really has been saved as described.
4.1.5. Configuration of 'api-web' Service
It is possible to specify configuration parameters in a file called api-web-prod.yml
that is located in the Git root directory like the profile-related configuration files used by the core services.
The following parameters can be specified:
Parameter | Description | Default | |||
---|---|---|---|---|---|
|
Section of parameters for the export of search result lists via the endpoint |
||||
|
Separator between individual values. |
|
|||
|
Used encoding. |
UTF-8 |
|||
|
Maximum number of objects to be included in the exported result list. |
100 |
|||
|
(as of 2023 Spring) Boolean value that specifies if byte order mark should be used (
|
|
|||
|
Comma-separated list of strings that specify the names of the roles that should be considered as technical roles. As such, they are filtered out, e.g., by the endpoints |
|
|||
|
An ISO language code that specifies the default locale for requests to the Web-API gateway. |
|
|||
|
(as of 2023 Spring) List of templates for creating display name for users instead of user IDs. If you want to avoid the userId to appear in your client application, you can display the value of one or multiple of the following user attributes instead:
Configure a template with comma-separated references on those attributes as shown in the example below. If you list multiple templates, the first one for which all referenced attributes are available will be used. If all configured templates contain at least one attribute for which no value is available for the corresponding user, the default applies. Example configuration
|
corresponding ID value |
4.1.6. Client-side SOT Handling via 'sothook' Service
The sothook
service is connected to yuuvis® Momentum via two webhooks. As an implementation for proper handling of an object’s lifecycle, it is required for the operation of the Web API.
Configuration
apiVersion: v1
kind: Service
metadata:
labels:
app: yuuvis
yuuvis: "true"
name: sothook
name: sothook
namespace: yuuvis
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 10779
selector:
name: sothook
type: ClusterI
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: yuuvis
labels:
app: yuuvis
name: sothook
name: sothook
spec:
replicas: 1
selector:
matchLabels:
name: sothook
template:
metadata:
labels:
app: yuuvis
name: sothook
spec:
initContainers:
- name: init-sothook
image: busybox
command: ["sh", "-c", "until wget -q --spider http://configservice/manage/health; do echo waiting for configservice; sleep 11; done;"]
imagePullPolicy: IfNotPresent
containers:
- name: sothook
image: docker.yuuvis.org/yuuvis/sandbox/sot-hook:1.0.0-RC01
imagePullPolicy: Always
env:
- name: JAVA_OPTS
value: -Xmx256m
- name: SPRING_PROFILES_ACTIVE
value: prod,kubernetes
- name: SPRING_CLOUD_CONFIG_URI
value: "http://configservice/config"
ports:
- containerPort: 10779
restartPolicy: Always
imagePullSecrets:
- name: flexsecret
In the cluster, the app/clientsystem/systemHookConfiguration.json
file must be adapted in the configservice
- in the webhook array, these two entries must be added:
{
"enable": true,
"predicate": "spel:T(java.util.List).of(100,101).contains(options['action']) && properties['system:secondaryObjectTypeIds'] != null && properties['system:secondaryObjectTypeIds']['value'].contains('appClientsystem:leadingType')",
"type": "dms.request.objects.upsert.database-before",
"url": "http://sothook/api/dms/request/import/databasebefore",
"useDiscovery": true
},
{
"enable": true,
"predicate": "spel:T(java.util.List).of(300).contains(options['action']) && properties['system:secondaryObjectTypeIds'] != null && properties['system:secondaryObjectTypeIds']['value'].contains('appClientsystem:leadingType')",
"type": "dms.request.objects.upsert.database-before",
"url": "http://sothook/api/dms/request/updatemetadata/databasebefore",
"useDiscovery": true
}
Deprecated (valid up to version 2022 Summer): In the cluster, the system/systemHookConfiguration.json
file must be adapted in the configservice
- in the webhook array, these two entries must be added:
{
"enable": true,
"predicate": "spel:(options==null || options['currentVersion']==null)",
"type": "dms.request.import.storage.before",
"url": "http://sothook/api/dms/request/import",
"useDiscovery": true
},
{
"enable": true,
"predicate": "spel:options!=null && options['currentVersion']!=null && options['currentVersion']['properties']['system:secondaryObjectTypeIds'] != null && options['currentVersion']['properties']['system:secondaryObjectTypeIds']['value'].contains('appClientsystem:leadingType')",
"type": "dms.request.update.metadata",
"url": "http://sothook/api/dms/request/update/metadata",
"useDiscovery": true
}
4.2. User Profile API
This API is provided by the userservice
. It allows accessing and managing custom user information, settings and content.If the path parameter userId is specified in a request URL, the corresponding endpoint operates on the data of the user specified by this ID. In order to work with the data of the currently authorized user, the path alias /me can be used instead of /users/{userId}
. For example, a GET /api/me
request leads to the same result as calling the GET /api/users/{userId}
endpoint.
Accessing or managing the data of users other than the currently authorized user may require administrative rights (as configured in the service parameter app.security.admin-role ). If the service is accessed with administrative rights, no further checks on existence of users are performed. This allows more flexibility to users and apps with admin rights. For instance, it is possible to remove the data of users stored by userservice that have left the system and are no longer in the security system, or to prepare data for users that are about to be added to the system.
|
4.2.1. Endpoints
User Contents Endpoints
Manage custom content (for example, profile pictures). This service stores and delivers content stream and the mime-type of stored content items.
GET /userservice/api/users/{userId}/contents
- Retrieve a list of all existing contents stored by the specified user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieve a list of all existing contents stored by the user specified by
userId
.Optional query parameters:
Parameter Type Description page
integer
Result page you want to retrieve (0…N). Default is 0 which means the first page.
size
integer($int32)
Limit the number of users per page. (default: 20)
sort
list of strings
Sorting of results either ascending (
asc
) or descending (desc
). Default sort order is ascending. Multiple sort criteria are supported.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
- Request Example
-
https://<host>/userservice/api/users/12345678-abcd-ef90-b620-0e92d5b7140c/contents?page=0&size=50&sort=desc
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "id": "myapp.layout" } ], "numItems": 50, "totalNumItems": 1234, "hasMoreItems": true }
DELETE /userservice/api/users/{userId}/contents
- Delete all existing contents stored by the specified user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
HTTP status code
- Description
-
Deletes all existing contents stored for the user specified by
userId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
- Request Example
-
https://<host>/userservice/api/users/12345678-abcd-ef90-b620-0e92d5b7140c/contents
no request body
- Response Example
-
200 OK
no response body
GET /userservice/api/users/{userId}/contents/{contentId}
- Retrieve the specified content for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the content specified by
contentId
that is stored for the user specified byuserId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
204
No content found that matches the identifier
401
Unauthorized
403
Forbidden
POST /userservice/api/users/{userId}/contents
- Update the specified content for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Description
-
Saves the content specified by
contentId
that is stored for the user specified byuserId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
DELETE /userservice/api/users/{userId}/contents
- Delete the specified content for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Description
-
Deletes the content specified by
contentId
that is stored for the user specified byuserId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
HEAD /userservice/api/users/{userId}/contents
- Retrieve the specified content for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
HEAD
- Response Format
-
HTTP status code
- Description
-
Retrieves the content specified by
contentId
that is stored for the user specified byuserId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
204
No content found that matches the identifier
401
Unauthorized
403
Forbidden
User Settings Endpoints
Manage custom settings (for example, layout settings) in form of JSON documents.
GET /userservice/api/users/{userId}/settings
- Retrieve all settings for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves a list of all existing settings on the user specified by
userId
.Optional query parameters:
Parameter Type Description page
integer
Result page you want to retrieve (0…N). Default is 0 which means the first page.
size
integer($int32)
Limit the number of users per page. (default: 20)
sort
list of strings
Sorting of results either ascending (
asc
) or descending (desc
). Default sort order is ascending. Multiple sort criteria are supported.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/userservice/api/users/12345678-abcd-ef90-b620-0e92d5b7140c/contents?page=0&size=50&sort=desc
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "id": "myapp.layout" } ], "numItems": 50, "totalNumItems": 1234, "hasMoreItems": true }
DELETE /userservice/api/users/{userId}/settings
- Delete all settings for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
DELETE
- Response Format
-
JSON
- Description
-
Deletes all existing settings on the user specified by
userId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/userservice/api/users/12345678-abcd-ef90-b620-0e92d5b7140c/settings
no request body
- Response Example
-
200 OK
no response body
GET /userservice/api/users/{userId}/settings/{settingId}
- Retrieve the specified settings section for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the set of settings specified by
settingId
that is stored for the user specified byuserId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
204
No settings found that matches the identifier
401
Unauthorized
403
Forbidden
POST /userservice/api/users/{userId}/settings/{settingId}
- Update the specified settings section for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Description
-
Saves the settings section specified by
settingsId
that are stored for the user specified byuserId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
DELETE /userservice/api/users/{userId}/settings/{settingId}
- Delete the specified settings section for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Description
-
Deletes the settings section specified by
settingsId
that are stored for the user specified byuserId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
HEAD /userservice/api/users/{userId}/settings/{settingId}
- Retrieve the specified settings section for the specified user.
- As of Version
-
2021 Summer
- Request Method
-
HEAD
- Response Format
-
JSON
- Description
-
Retrieves the set of settings specified by
settingId
that is stored for the user specified byuserId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
204
No settings found that matches the identifier
401
Unauthorized
403
Forbidden
4.2.2. Configuration
Database Connection
The userservice
users the database connection that is configured via environment variables as described in the installation guide.
Service Configuration
The following parameters are part of the service configuration:
Parameter | Description |
---|---|
|
References the role (by name) that provides administrative rights and may be used in |
|
Defines the maximum storage space available for all contents of one user. |
|
Defines the maximum storage space for one single content item. |
|
Defines the maximum storage space available for all settings of one user. |
|
Defines the maximum storage space for one single setting item. |
The following spring properties are ready configured for the installation and should be left unchanged to ensure that the userservice
parameters are effective. Otherwise, it would cause unintended behavior.
-
spring.servlet.multipart.max-file-size
-
spring.servlet.multipart.max-request-size
Docker Deployment
Within the docker environment, the userservice
will run in two separate docker containers.
Instead of deploying docker containers manually, we strongly recommend to use docker-compose. With docker-compose you can easily manage one or several deployments on your docker host, without copy-pasting docker commands manually. You will find pre-defined service stacks for connecting to different databases in our repository.
Running 'userservice' for Testing
Depending on the database you want to connect to the userservice
, choose the correct deployment commands.
Deployment via docker-compose for PostgreSQL
Start the service with a PostgreSQL database for testing purposes with following steps:
-
In a console supporting docker, go to project docker directory.
-
Build a docker-compose image with
docker-compose -f docker-compose-postgres.yml build
. -
Start this image with
docker-compose -f docker-compose-postgres.yml up
.
Deployment via docker-compose for Microsoft SQL Server
Start the service with a Microsoft SQL Server database for testing purposes with following steps:
-
In a console supporting docker, go to project docker directory.
-
Build a docker-compose image with
docker-compose -f docker-compose-mssql.yml build
. -
Start this image with
docker-compose -f docker-compose-mssql.yml up
.
Deployment via docker-compose for CockroachDB
Start the service with a CockroachDB for testing purposes with following steps:
-
In a console supporting docker, go to project docker directory.
-
Build a docker-compose image with
docker-compose -f docker-compose-cockroach.yml build
. -
Start this image with
docker-compose -f docker-compose-cockroach.yml up
.
4.3. Content Viewer API
The yuuvis® Momentum viewer
service offers to display several common file types directly within a yuuvis® Momentum client application. It serves within the yuuvis® Momentum reference client and can readily be integrated in a custom client. It is designed to allow for easy integration of further viewers in addition to the free ones included already.
Currently, the Web API gateway offers several endpoints.
As of 2021 Autumn, it is possible to authenticate via bearer token to the viewer
service. Especially, a preview for binary content files can be retrieved.
4.3.1. Supported Types
All following formats are supported by the viewer
service. Some others like Microsoft Office files are supported by the rendition service or potentially the dashlet365
service if available.
For unsupported file types, the viewer
service sends an error page with download link, allowing for the content to be downloaded and viewed by an external application.
Audio and Video
The audio and video files are natively played by the browser with HTML5 video tag (that is a subject of the HTML5 video specification). All played files are streamed to prevent unnecessary data downloads. The autoplay is set to false
.
1
2
3
4
5
6
7
8
9
10
11
[
{
"mimeType": ["audio/mp3", "audio/webm", "audio/ogg", "audio/mpeg", "video/mp4", "video/webm", "video/ogg", "application/ogg"],
"viewer": "api/video/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}"
}
]
Image
All supported image mimeTypes
are rendered in the standard HTML img
tag. The image viewer provides additional features like full screen, zoom, and rotate.
-
All images are automatically transformed as base64 encoded images.
-
The dimensions are limited to a maximum of 8K resolution to improve performance and prevent errors on extremely large TIFF files.
1
2
3
4
5
6
7
8
9
10
11
[
{
"mimeType": ["image/tiff", "image/jpeg", "image/png", "image/apng", "image/gif", "image/svg+xml", "image/webp"],
"viewer": "api/img/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}"
}
]
All supported e-mail mimeTypes
are rendered by a custom e-mail HTML viewer. The EML files are parsed by a mailparser, MSG files are parsed by a custom parser inspired by MSGReader. The e-mail viewer provides additional features like attachment preview and download.
1
2
3
4
5
6
7
8
9
10
11
[
{
"mimeType": ["message/rfc822", "application/vnd.ms-outlook"],
"viewer": "api/mail/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}"
}
]
Text (JSON, XML, markdown, java, HTML, …)
All supported text mimeTypes
are rendered by the 3rd party monaco viewer. The monaco viewer provides additional features like language formatting, line numbers, and text search.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
[
{
"mimeType": ["application/json"],
"viewer": "api/monaco/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}&language=javascript"
},
{
"mimeType": ["text/plain"],
"viewer": "api/monaco/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}&language=plaintext"
},
{
"mimeType": ["text/xml",
"application/xml"],
"viewer": "api/monaco/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}&language=xml"
},
{
"mimeType": ["text/java"],
"viewer": "api/monaco/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}&language=java"
},
{
"mimeType": ["text/javascript",
"application/javascript"],
"viewer": "api/monaco/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}&language=javascript"
},
{
"mimeType": ["text/html"],
"viewer": "api/monaco/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}&language=html"
},
{
"mimeType": ["text/markdown",
"text/x-web-markdown",
"text/x-markdown"],
"viewer": "api/monaco/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}&language=markdown"
}
]
PDF and Microsoft Office
All supported PDF and MS Office mimeTypes
are rendered by the 3rd party component PDF.js which is a Mozilla project. The MS Office files are transformed to PDF via rendition
service. The PDF viewer provides additional features like formatting, lazy loading, and text search.
The ranging support provided by PDF.js is supported by the Web API Gateway as well.
Search Term Highlighting
The full-text search provided by yuuvis® Momentum is insensitive to diacritics whereas the |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
[
{
"mimeType": [
"application/pdf"
],
"viewer": "api/pdf/web/viewer.html?file=&path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}"
},
{
"mimeType": [
"application/msword",
"application/vnd.ms-excel",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/vnd.openxmlformats-officedocument.presentationml.template",
"application/vnd.openxmlformats-officedocument.presentationml.slideshow",
"application/vnd.ms-word.document.macroEnabled.12",
"application/vnd.ms-word.template.macroEnabled.12",
"application/vnd.ms-excel.sheet.macroEnabled.12",
"application/vnd.ms-excel.template.macroEnabled.12",
"application/vnd.ms-excel.addin.macroEnabled.12",
"application/vnd.ms-excel.sheet.binary.macroEnabled.12",
"application/vnd.ms-powerpoint.addin.macroEnabled.12",
"application/vnd.ms-powerpoint.presentation.macroEnabled.12",
"application/vnd.ms-powerpoint.template.macroEnabled.12",
"application/vnd.ms-powerpoint.slideshow.macroEnabled.12"
],
"viewer": "api/pdf/web/viewer.html?file=&path=${path}&pathPdf=${pathPdf}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}"
}
]
4.3.2. Customizing
The viewer service can be extended as described in this section.
Localization
The viewer service offers a few strings with information for your users. You can change these or add some more language strings by setting them up in the translation section of the plug-in file that can be uploaded for use in the client.
{
"translations": {
"en": {
"yuv.viewer.not.authorized": "Not authorized to preview file.",
"yuv.viewer.not.found": "File not found.",
"yuv.viewer.not.supported": "Format not supported.",
"yuv.viewer.not.supported.download.content": "Unable to display format. You can click this link to download the file."
},
"de": {
"yuv.viewer.not.authorized": "Fehlende Authorisierung zur Anzeige der Datei.",
"yuv.viewer.not.found": "Datei nicht gefunden.",
"yuv.viewer.not.supported": "Dieses Format ist nicht unterstützt.",
"yuv.viewer.not.supported.download.content": "Dieses Format kann nicht angezeigt werden. Ein Klick auf den Link lädt die Datei herunter."
}
}
}
The 'viewer' Service API
For the viewer
to process a request, a path pointing to the file to be displayed must be accessible. The mimeType
or fileExtension
should be provided as well.
api/video/?path=${path}&mimeType...
api/img/?path=${path}&mimeType...
api/mail/?path=${path}&mimeType...
api/monaco/?path=${path}&mimeType...
api/pdf/web/viewer.html?file=&path=${path}&mimeType...
The following parameters are available:
Parameter | Type | Description |
---|---|---|
|
string |
the direct path from where the file can be loaded (required) |
|
string |
the file’s mimeType (optional) |
|
string |
the file’s name extension (optional) |
|
string |
sets the document locale to the html tag (default is |
|
string |
sets class dark to the body (default = |
|
string |
sets the accent color as css variable to the html tag (default = |
URL/?path=${path}&mimeType=${mimeType}&fileExtension{fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}
Custom Viewer Configuration
The viewer
service configuration can be extended by adding a few lines to the plug-in configuration. Custom viewers can be implemented as static HTML files (in assets
folder) or as custom microservice (for example dashlet365
).
1
2
3
4
5
6
7
8
9
10
11
12
13
"viewers": [
{
"mimeType": ["application/json"],
"fileExtension": ["json"],
"viewer": "assets/json-viewer/?path=${path}&mimeType=${mimeType}&fileExtension=${fileExtension}&lang=${lang}&theme=${theme}&accentColor=${accentColor}&language=javascript"
}
]
-
mimeType
may also be a string array, containing multiple mime types. -
fileExtension
is not mandatory. Provide only ifmimeType
is ambiguous. -
viewer
represents URL (string or function that returns string) that will be loaded in preview (iframe)
Additionally, the provided parameters will be passed to the custom viewer.
1
2
3
4
5
6
7
8
9
10
11
12
13
"viewers": [
{
"mimeType": ["application/json"],
"fileExtension": ["json"],
"viewer": "() => parameters.path"
}
]
"viewers": [ { "mimeType": [ "application/msword", "application/vnd.ms-excel", "application/vnd.ms-powerpoint", "application/vnd.openxmlformats-officedocument", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "application/vnd.openxmlformats-officedocument.presentationml.template", "application/vnd.openxmlformats-officedocument.presentationml.slideshow" ], "viewer": "() => { var edit = api.session.user.hasRole('YUUVIS_DEFAULT') && !location.pathname.match('/versions/'); return '/dashlet365/?id=${id}' + (edit ? '' : '_' + dmsObject.version) + '&version=${version}&mimeType=${mimeType}&path=${path}&fileExtension=${fileExtension}&locale=${lang}&allowedExtensions=doc,docx,xls,xlsx,ppt,pptx&editMode=' + edit + '&displayName=' + api.session.user.get().firstname; }" } ]
4.4. Office 365 Integration
4.4.1. Function
Viewing Mode
Binary content files of the Microsoft Office file types and many others can be displayed in viewing mode. The preview is provided via the VIEWER Service in combination with a specific dashlet that is automatically installed via a Helm chart.
In viewing mode, no dedicated authentication license is required for Microsoft Office 365.
Editing Mode
If you have an authentication license for Microsoft Office 365, you have the possibility to edit binary content files of the types DOCX, PPTX, and XLSX directly in your yuuvis® Momentum client application. Changes are saved in a new version of the binary content file and a new object version is created in yuuvis® Momentum.
The editing mode is available for all users with a write permission on the corresponding object. In order to avoid the creation of offline copies, the binary content file that is edited via the OFFICE365 service never leaves the yuuvis® Momentum system during the processing. Thus, it is not possible to open it in a desktop editor directly from the web application. However, it is possible to download the binary content to your local file system from the client and open it from there in a desktop editor.
4.4.2. Certification
Our Office 365 integration is certified by Microsoft for our Software as a Service solution that is hosted by us. Customers with a self-hosted yuuvis® Momentum solution have to obtain their own certification for the Office 365 integration if needed.
4.4.3. Installation and Configuration
The service is installed and automatically configured by means of the client Helm chart. In its values.yaml file, specify user name and password for Microsoft Office 365 via the parameters yuuvis.client.office364.officeUser
and yuuvis.client.office365.officePassword
.
In order to integrate the Office 365 functionality in a client application based on the developer libraries, set up a plug-in configuration.
4.5. Developer Libraries
We offer the following developer libraries, which may be used when developing a custom client application in Angular.
-
The core library provides a set of services to interact with a yuuvis® Momentum backend.
-
The framework library provides yuuvis® developers with a collection of UI components, like hit lists, to create their own client applications.
-
The command-palette library provides support features for the navigation by keyboard.
-
As of 2022 Autumn, the widget-grid and widget-grid-widgets libraries allow for the creation of a custom dashboard.
4.5.1. Library Documentation
A documentation generated from the source code itself is provided at https://yuuvis-cc.yuuvis.org/. Notice the drop-down for switching between both documentations.
4.5.2. Library Installation
The developer libraries are open source, available on NPM. With @yuuvis/project we also provide schematics to be used with Angular CLI. It will support developers by integrating the libraries into their project: www.npmjs.com/package/@yuuvis/project
It is also possible to install the libraries separately:
-
Install the core library: www.npmjs.com/package/@yuuvis/core
-
Install the framework library: www.npmjs.com/package/@yuuvis/framework
Furthermore, the following libraries can be installed:
-
The command-palette library can be installed to enable further support of navigation by keyboard: www.npmjs.com/package/@yuuvis/command-palette
-
The widget-grid library can be installed for creating custom dashboards. Widgets can be registered and afterwards configured by the users: www.npmjs.com/package/@yuuvis/widget-grid
The feature is still in a testing phase. We preserve to apply any changes to its functionality. -
The widget-grid-widgets library contains a set of suitable widgets to be used with the widget-grid library: www.npmjs.com/package/@yuuvis/widget-grid-widgets
The feature is still in a testing phase. We preserve to apply any changes to its functionality.
Installation Steps
-
First, you need to install the
npm
module.-
For the core library:
npm install @yuuvis/core --save
-
For the framework library (the command installs the core library as well):
npm install @yuuvis/framework --save
-
-
Import
YuvCoreModule
to use @yuuvis/core in your Angular project. You have to importYuvCoreModule.forRoot()
in the root NgModule of your application.import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { YuvCoreModule } from '@yuuvis/core'; @NgModule({ imports: [BrowserModule, YuvCoreModule.forRoot()], bootstrap: [AppComponent] }) export class AppModule
-
Configure
YuvCoreModule
viaassets/default/config/main.json
configuration file. By default it looks like this:"core": { "apiBase": { "core": "/api", "api-web": "/api-web/api" }, "languages": [ { "iso": "de", "label": "Deutsch" }, { "iso": "en", "label": "English", "fallback": true } ], "logging": { "level": "debug"
-
Configure translations set up by a translations module provided by the core library that can be used within your application. This module will be bound to the language a user has set up on the yuuvis® Momentum backend. In order to be able to initialize this module, translation files are required. By default, they are supposed to be located at
assets/default/i18n/
. In this directory, you provide a file for each supported language (en.json
,de.json
, …). If you do not need translations, just provide empty files.You are able to change the default directory for the configuration by providing different locations to the module config when you import
YuvCoreModule
orYuvFrameworkModule
:Example import 'YuvCoreModule'@NgModule({ imports: [ YuvCoreModule.forRoot({ main: ['assets/my-custom-path/config/main.json'], translations: ['assets/my-custom-path/i18n/'] }) ], bootstrap: [AppComponent] }) export class AppModule
Example import 'YuvFrameworkModule'@NgModule({ imports: [ YuvFrameworkModule.forRoot({ main: ['assets/my-custom-path/config/main.json'], translations: ['assets/my-custom-path/i18n/'] }) ], bootstrap: [AppComponent] }) export class AppModule
-
Use the libraries:
-
Core library: Import the services you want to use into your components:
import { UserService } from '@yuuvis/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { constructor(private userService: UserService) {}
-
Framework library: Import the components you want to use into your components.
-
Troubleshooting
Ensure that your project is running on a supported Angular version. If you are not yet on Angular 9, update your project:
ng update @angular/cli@^9 @angular/core@^9
You may also want to update your global Angular CLI to version 9:
npm uninstall -g @angular/cli
npm cache verify
# if npm version is < 5 then use `npm cache clean`
npm install -g @angular/cli@latest
4.5.3. Client outside the yuuvis® Momentum Cluster
By default, client applications built with @yuuvis/core library are supposed to be deployed inside the yuuvis® Momentum cluster. As a main advantage, there is no responsibility for the library to handle the authentication process. Users authenticate directly via the authentication
service.
As of yuuvis® Momentum version 2021 Autumn, the @yuuvis/core library allows for the built of clients that can be deployed outside the yuuvis® Momentum cluster. Such clients authenticate via OpenID Connect to the authentication
service and can thus be hosted fully independently. They can even be configured to support switching between different yuuvis® Momentum clusters. Users select the cluster to which they want to connect.
An example project is provided on GitHub.
The following configuration steps are required to allow for the client deployment outside a yuuvis® Momentum cluster.
Setting up Keycloak
Configure a client inside your Keycloak Realm that will be used to trigger login.
Client ID: 'spa-client' // choose your own name
Client Protocol: 'openid-connect'
Access Type: 'public'
Valid Redirect URIs: // match your environment
Web Origins: '+' // means: everything that's also invalid redirect uris
#Advanced Settings
Proof Key for Code Exchange Code Challenge Method: 'S256'
Setting up Projects
Choose one of the following ways to setup your project.
Setup via Module Configuration
During the import of YuvCoreModule or YuvFrameworkModule, specify the following configuration:
// app.module.ts
imports: [
YuvCoreModule.forRoot({
// ... other config values
oidc: {
host: "https://kolibri.enaioci.net",
tenant: "kolibri",
issuer: "https://kc001.auth.enaioci.net/auth/realms/kolibri",
clientId: "spa-client",
}
})
],
Setup via Dynamic Initialization
In case you do not know about the OIDC properties when your application starts (the OIDC profile needs to be loaded or users select one of several profiles), you can just import YuvCoreModule without OIDC config. The @yuuvis/core library will try the default initialization as if the client were deployed within a yuuvis® Momentum cluster. This will cause some console errors which can be ignored.
Once you are ready to specify the OIDC configuration, you can re-trigger the initialization of the library’s core module:
export class AppComponent {
static OIDC = 'app.oidc.config';
constructor(@Inject(CORE_CONFIG) private coreConfig: CoreConfig, private coreInit: CoreInit) {}
login(target: OpenIdConfig) {
this.coreConfig.oidc = {
host: 'https://kolibri.enaioci.net',
tenant: 'kolibri',
issuer: 'https://kc001.auth.enaioci.net/auth/realms/kolibri',
clientId: 'spa-client'
};
localStorage.setItem(AppComponent.OIDC, JSON.stringify(this.coreConfig.oidc));
this.coreInit.initialize();
}
logout(removeOIDC = false) {
removeOIDC && localStorage.removeItem(AppComponent.OIDC);
this.userService.logout();
}
}
// app.module.ts
imports: [
YuvCoreModule.forRoot({
oidc: JSON.parse(localStorage.getItem(AppComponent.OIDC) || '{}'),
})
],
4.5.4. Customizing the Main Configuration
The default values for the main configuration of the settings are provided in the main.json
file. Users with the appropriate permissions can download the main.json file, modify it and upload it again in order to apply new values to the main configuration. The settings will be applied to all users of the users' tenant.
To customize the main configuration, follow these steps:
-
Retrieve the currently applied main.json file via the Web-API Gateway endpoints
GET /api-web/api/admin/resources/config/{name}
orGET /api-web/api/resources/config/{name}
withmain-config
as value for the name path parameter. -
Modify the
main.json
file as described below. -
Import the modified
main.json
file via the Web-API Gateway endpointPOST /api-web/api/admin/resources/config/{name}
again with main-config as value for the name path parameter. -
Refresh the client in your browser. The new settings will be applied.
The following code block shows the default main.json file defining the main configuration after installation. The individual parameters and their possible values are listed and described in the table below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"core": {
"apiBase": {
"core": "/api",
"api-web": "/api-web/api",
"predict": "/predict-api",
"viewer": "/viewer",
"logout": "/logout",
"oauth": "/oauth"
},
"languages": [
{
"iso": "de",
"label": "Deutsch"
},
{
"iso": "en",
"label": "English",
"fallback": true
}
],
"logging": {
"level": "debug"
}
}
}
We recommend to configure only those parameters in your tentant-specific main.json that differ from the standard ones to reduce possible issues when updating the system.
|
Parameters in the 'main.json' file
Section | Sub-Section / Key | Key | Example Value | Description |
---|---|---|---|---|
|
|
|
|
Do not change these settings! These values are required for the connection to yuuvis® Momentum core and client services. |
|
|
|||
|
|
|||
|
|
|
This is the list of languages from which the users can choose in the reference client. Each list entry contains:
Only one language in the list can have the value true for fallback. For several languages, the specific date, time and number formats are automatically used. |
|
|
|
|||
|
|
|||
|
|
|
Logging levels:
|
|
|
|
YUUVIS_SYSTEM_INTEGRATOR YUUVIS_TENANT_ADMIN (default) |
Name of the role that enables the display of the following administrative information which are hidden for other users:
|
|
|
|
Name of the role that enables to modify the standard configurations of filters and hit lists. The configurations will be applied to all users within the tenant. |
||
|
|
Name of the role that enables the retention management view and allows to set or extend the expiration date for individual document objects. |
||
|
|
|
ID of an existing property that is referenced in all document or folder object type definitions (either directly or via SOT). This property will correspond to the Name field in the client that is available for all object types. |
|
|
|
ID of an existing property that is referenced in all document or folder object type definitions (either directly or via SOT). This property will correspond to the Description field in the client that is available for all object types. |
||
|
|
100 (default) |
(as of 2022 Summer) Maximum number of tasks per page in the client’s Inbox view. |
|
|
100 (default) |
Maximum number of processes per page in the client’s My follow-ups and My processes views. |
||
|
|
Enable ( |
||
|
|
Search with specific term will be limited to scope: |
||
|
|
|
(as of 2022 Winter) Enable ( |
|
|
(as of 2023 Spring) Configuration for the hit list grid that will be used as default for client users who did not save their own hit list configuration. |
|||
|
50 (default) |
Row height in pixel. |
||
|
70 (default) |
Maximum number of results within one page of the hit list. |
||
|
|
|
|
Any valid URL, optionally containing the placeholder The given URL can be called from two places within the client:
|
|
|
List of languages in which the documentation portal is available. Depending on the language set in the reference client, the corresponding iso value is used in the URL instead of the placeholder |
||
|
|
Specify the order of tabs or exclude any tabs in the Object Details view. |
||
|
|
As of 2023 Winter. Specify the order of tabs or exclude any of tabs in Task Details view (Inbox page). |
||
|
|
As of 2023 Winter. Specify the order of tabs or exclude any of tabs in Process Details view (My Processes page). |
Configuring Additional Client Languages
The developer libraries are provided by default with German and English as the application languages. However, the client can be extended with custom language files.
Users with the appropriate permissions can download the <iso>.json
file for any language, modify it and upload it again in order to apply new values to the language configuration. The settings will be applied to all users of the users' tenant or to the users of all tenants.
To display an additional language, it needs to be enabled in the main.json
configuration file via core.languages
.
4.5.5. Schema Rules for Library-based Client
Secondary Object Type Classifications
This chapter relies on knowledge about the usage of Secondary Object Types (SOTs). Here, we consider only SOTs that are referenced as floating (FSOT). Those FSOTs can be assigned to objects during their lifecycle and removed again as well. Thus, additional metadata properties can be assigned to objects at any time, independent of the creation process. Clients based on our developer libraries use this concept to allow for a multi-step object creation process. It is possible to create objects having a general object type with only a few properties. After creation, either the user or a classification job analyses the object (and its binary content file if available) and selects a suitable FSOT that lets the object appear with a leading object type describing the business scope (invoice, delivery note, order, …) and/or inserts appropriate properties.
To ensure proper functioning of form modeling, FSOTs must not be referenced in multiple object type definitions (see below). |
By adding a specific classification attribute to their definition, it is possible to induce a particular behavior in your client. The following table introduces the classifications of SOTs you can use in your schemata.
Term | Short | Value for 'classification' | Description |
---|---|---|---|
Primary floating secondary object type |
PFSOT |
|
With respect to the above-mentioned import process, users can manually select the leading object type for a new object. Technically, the client application assigns a PFSOT that provides properties to identify this specific leading object type (invoice, delivery note, order, …). |
Required floating secondary object type |
RFSOT |
|
If you want to define some sets of properties that should be required for multiple PFSOTs, you can use RFSOTs instead of directly referencing the individual properties in the PFSOTs several times. In case users assign a PFSOT, all RFSOTs are assigned as well and provide their properties, e.g., client-specific defaults with title and description. Especially the RFSOTs |
Extendable floating secondary object type |
EFSOT |
- |
While RFSOTs are automatically assigned together with a PFSOT, EFSOTs can be assigned later on if necessary. Examples are general address data, e-mail address data, and approval process attributes. |
System floating secondary object type |
SFSOT |
|
This classification suppresses the listing of the corresponding SOT for users of your client that do not have any administrative roles. The SFSOTs are not displayed in the Characteristics field in your client, but are listed in the E.g., the RFSOTs |
- |
- |
|
If the FSOT is assigned to an object, it cannot be removed by a user via the client application. |
Classifications available for all Object Types
This chapter relies on knowledge about the definition of object types. By specifying one of the following values for the classification attribute, it is possible to induce a particular behavior in your client.
Value for 'classification' | Description |
---|---|
|
The object type is not available to users in the object creation dialog. |
|
The object type is not available in the filter options for searches and hit lists. |
|
Only available for document object types referencing at least one PFSOT and if the client application is combined with AI functionality. If set, the client application requests the PREDICT-API Endpoints for predictions while creating a new object with a binary content file. In the second step of the object creation dialog, a list of suitable PFSOTs including a percentage value describing the match quality is displayed for the users. |
E.g.:
|
Document lifecycle management is provided via tags that can be assigned, modified or removed at runtime for any object independently on the schema. However, they are displayed in the client only if they are specified in the corresponding object type definition. If specified, the tags can be used for filtering and can be displayed in hit lists. If specified in an SOT definition, the corresponding tag field in the client is available for all objects having the SOT assigned. The tag name and values to be displayed in the client can be localized via keys of the following format: As of 2022 Spring, the tag name (and value where appropriate) is displayed in tag-specific history entries as well. |
|
(as of 2022 Summer) Specify the ID of a globally stored icon in order to display it for the corresponding object type defined in the global schema or in any app or tenant schema. |
Default 'client' and 'clientsystem' App Schemata
A library-based client is handled via two apps called client and clientsystem in yuuvis® Momentum. Both apps have their own app schema. They have to contain the definition of the following two RFSOTs that have to be referenced in all object type definitions:
-
appClient:clientdefaults
– This SOT contains the propertiesclienttitle
andclientdescription
and appends them to each object to which it is assigned. Thus, all objects with a PFSOT have those two properties which makes them perfect for use in mixed hit lists. -
appClientsystem:leadingType
– This SOT contains the propertyleadingTypeId
and appends it to each object to which it is assigned. It identifies the PFSOT from the client application’s point of view.
Per default, the app schemata already contain these two RFSOTs after installation.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/">
<propertyStringDefinition>
<id>clienttitle</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
<maxLength>200</maxLength>
</propertyStringDefinition>
<propertyStringDefinition>
<id>clientdescription</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
<maxLength>200</maxLength>
</propertyStringDefinition>
<typeDocumentDefinition>
<id>minidoc</id>
<baseId>system:document</baseId>
<contentStreamAllowed>allowed</contentStreamAllowed>
<secondaryObjectTypeId>appClientsystem:leadingType</secondaryObjectTypeId>
<secondaryObjectTypeId>appClient:clientdefaults</secondaryObjectTypeId>
</typeDocumentDefinition>
<typeSecondaryDefinition>
<id>clientdefaults</id>
<description>contains title and description fields mainly for mixed hit list and object header</description>
<baseId>system:secondary</baseId>
<propertyReference>clienttitle</propertyReference>
<propertyReference>clientdescription</propertyReference>
<classification>appClient:required</classification>
<classification>appClient:create:false</classification>
</typeSecondaryDefinition>
</schema>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/">
<propertyStringDefinition>
<id>leadingTypeId</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<typeSecondaryDefinition>
<id>leadingType</id>
<description>contains the field that supports a better use of FSOTs</description>
<baseId>system:secondary</baseId>
<propertyReference>leadingTypeId</propertyReference>
<classification>appClient:create:false</classification>
<classification>appClient:search:false</classification>
</typeSecondaryDefinition>
</schema>
Impact of appClient:clientdefaults
:
-
provides the two properties
clienttitle
andclientdescription
which are used in mixed hit lists to identify objects by Name and Description as well as in the header of the object details.
Impact of appClientsystem:leadingType
:
-
Provides the property
appClientsystem:leadingTypeId
-
The value for this property is set via a webhook (see SOTHOOK) as soon as a PFSOT is assigned to an object.
-
Based on the value specified in this property, the client application identifies the leading object type and displays a corresponding icon.
-
Furthermore, it is possible to configure permissions for individual leading object types by specifying conditions for the
appClientsystem:leadingTypeId
in your role set. An example role is shown in the following code block.<role> <name>contract_read</name> <permission> <action>read</action> <condition>appClientsystem:leadingTypeId = 'appMyapp:contract'</condition> </permission> </role>
-
The
appClient:leadingType
object type cannot be used for searching and theappClient:leadingTypeId
field cannot be used in forms.
Example 'minidoc' Object Type
The default client schema contains the minidoc
example object type, which only references the two RFSOTs appClient:clientdefaults
and appClientsystem:leadingType
. In the English default localization, it is offered as Smallest document in the Restrict to object types dialog.
After selecting the Smallest document object type, a binary content file can be added to the object. This is possible because the contentStreamAllowed property is set to allowed in the minidoc object type definition. Then, the Create form is displayed in which the new object’s metadata have to be entered. Here, the two referenced properties clienttitle and clientdescription are available. Per default, their labels are Title and Description.
The creation of the new object is completed by clicking the Create object button. Any binary content files added to the object will then be imported to the yuuvis® Momentum system.
Configuring the Content Preview for the Creation Dialog
In yuuvis® Momentum, the binary content file assigned to an object can be accessed as soon as the object creation is finished successfully. If a preview of the binary content file should be displayed for users, the corresponding object has to exist already. However, you might want to provide a preview of the binary content file already within the object creation dialog. For this purpose, at first, your client application has to create the object with the desired binary content file assigned to it. A generic document object type can be used. If this process is automatized by the client application, the user dialog for object creation can now display the content preview to make the users' decision for a PFSOT and/or the corresponding property values easier.
In the following example code block, a generic document object type preemail and a characterizing PFSOT emailsot are defined. The preemail object type is not offered to users in the object creation dialog. It does not reference any properties directly, but it references the appClientsystem:leadingType, appClient:clientdefaults and emailsot SOTs. The emailsot PFSOT references the properties users may need to handle e-mail objects.
<typeDocumentDefinition>
<id>preemail</id>
<description>...</description>
<baseId>system:document</baseId>
<classification>appClient:search:false</classification>
<classification>appClient:create:false</classification>
<contentStreamAllowed>required</contentStreamAllowed>
<secondaryObjectTypeId>appClientSystem:leadingType</secondaryObjectTypeId>
<secondaryObjectTypeId static="false">appClient:clientdefaults</secondaryObjectTypeId>
<secondaryObjectTypeId static="false">emailsot</secondaryObjectTypeId>
</typeDocumentDefinition>
<typeSecondaryDefinition>
<id>emailsot</id>
<baseId>system:secondary</baseId>
<propertyReference>from</propertyReference>
<propertyReference>to</propertyReference>
<propertyReference>cc</propertyReference>
<propertyReference>subject</propertyReference>
<propertyReference>hasattachment</propertyReference>
<propertyReference>attachmentnames</propertyReference>
<propertyReference>received</propertyReference>
<classification>appClient:primary</classification>
</typeSecondaryDefinition>
The client application automatically uses the preemail type to create the object after users have selected a binary content file. In a second step in the object creation dialog, the content preview is displayed to the users who can now read it in order to specify the properties provided by the emailsot PFSOT. The following screenshot shows an example for a CREATE form modeled in yuuvis® architect on the left, next to a content preview on the right. The data specified in this form is extracted from the e-mail file. The next section describes how to model and script this automatic metadata extraction.
Property Classifications
You can use the following values for the classification attribute in property definitions of the suitable types to control the form field behavior in your client application. The corresponding controls can be added to the Summary aspect area, edit and create forms, hit lists, and filters.
Value for 'classification' | Property type | Description | ||
---|---|---|---|---|
|
string |
An e-mail icon is displayed beside the form field. A click on the icon opens the locally installed e-mail client with the e-mail address specified. The entered value is validated via an internal browser function. Valid addresses have to match the standard.
|
||
|
|
A URL icon is displayed beside the form field. A click on the icon opens the specified URL in a browser. The entered value is validated via an internal browser function. Valid addresses have to match the standard. |
||
|
string |
A phone icon is displayed beside the form field. A click on the icon opens the specified number in the available phone application. In Chrome, a connected Android phone can be used. No validation takes place. |
||
|
string |
Useful for properties that store a user ID and appear with the corresponding user name. As soon as users start typing in the form field, a selection list with user names is provided for which the entered term was found in the user name, name, surname or e-mail address. If users select one of them, the corresponding user ID is stored as property value while the user name is shown in the form as a chip. If roles are specified, only user names of users having at least one of those roles are offered for the corresponding form field. |
||
|
string |
Useful for properties that store an object type ID or an object ID and appear with the corresponding object type or object name. As soon as users start typing in the form field, a selection list with matching object type or object names is provided. If users select one of them, the corresponding object type ID or object ID is stored while the name is shown in the form as a chip. If no name is available, the ID is displayed instead. For object ID property fields, an Anchor icon is additionally displayed beside the form field. A click on this icon opens the referenced object. For object type ID property fields, it is possible to limit the object types that are offered to users in the selection list. For this purpose, specify all object type IDs to be considered in the classification attribute. An empty list allows all object types. Note: It is not possible to specify base types (system:object, system:folder, system:documents). |
||
|
string |
Configuration of a static catalog. Users can only select the values specified in the list. Only one language is supported here. |
||
Pattern to be used in the global schema:
Pattern to be used in an app schema:
Pattern to be used in a tenant schema:
|
string |
Configuration of a dynamic catalog that can be maintained per tenant. Users can only select the values specified in the list. Users with the YUUVIS_MANAGE_SETTINGS role can deactivate and remove values or add new values if the optional parameter readonly is NOT set. Only one language is supported here. The catalog values are stored separately for each tenant. It is possible to set up standard values for each catalog using a specific system controller endpoint of the Web-API Gateway. If no tenant-specific variant has been saved so far, the standard values are used. |
||
|
string |
Retrieves the catalog values from a custom microservice that is called via the specified URL. The URL can be absolute (e.g., https://mydomain/myservice/myfunction?myparameter=mycatalogname) or relative (e.g., /myservice/myfunction?myparameter=mycatalogname).
The internal token with the user information is transferred to the microservice. The language set by the user can be read from the header. The response format must have the following JSON structure:
|
||
|
number |
Numbers are rendered with a delimiter, e.g., 123,456,789.35. Otherwise, no digital grouping is used, e.g., 123456789.35. |
||
|
table |
Enables the user to sort table rows manually by drag & drop. |
||
|
boolean |
Values are represented by a switch with the available positions true (right position), false (left position) and null (middle position). Per default (if switch is not specified), the values for boolean properties are displayed as checkboxes. A null value is represented as crossed-out box. |
||
|
any type |
The property is not displayed in any standard form by the client application. |
||
|
any type |
The property is not displayed in the summary aspect area of objects displayed by the client application. |
4.5.6. Preview of Content Files
In addition to forms containing the metadata of a DMS object, a preview of the binary content file assigned to it can be displayed. In a client application based on our developer libraries, the content preview is retrieved either via the VIEWER Service or PDF renditions.
It is also possible to compare previews for two different binary content files. They can either belong to two different DMS objects or to two different versions of the same object.
Supported Formats
The content preview can be displayed if the file type of the binary content file is supported.
-
If possible, the VIEWER service is always used.
-
If the format is not supported by the VIEWER service, a PDF rendition is requested and displayed if the format is supported.
A PDF rendition can only be retrieved for binary content files assigned to the current version of a DMS object. This means that only the preview of the current version will be displayed, when comparing different versions of a DMS object containing a content file whose format is not supported by the VIEWER Service, but only by the PDF rendition.
If the format is neither supported by VIEWER nor rendition
service, no content preview can be displayed.
4.5.7. Maintaining Dynamic Catalogs
In some metadata fields, you may want to provide a selection list of possible values from which the users have to choose. Those lists are configured via so-called catalogs. In their schema definition, they can be configured to be editable or not directly in your client for users with the proper authorization. A change in the schema definition is not required in order to modify the available values for the so-called dynamic catalogs.
Dynamic catalogs are introduced into the Web-API gateway with version 2021 Summer.
We use the term catalog from a technical perspective and the term list from the user’s perspective. |
The catalog values (corresponding to list elements) cannot be localized. |
The list elements cannot be manipulated by client form scripting. |
Defining Dynamic Catalogs
A property can be classified in the schema definition to be displayed as a dynamic catalog in your client by setting the value dynamic:catalog[<catalog name>]
for the attribute classification
. Per default, the catalog name will be used as display name in your client. It can be localized in order to replace the display name. We recommend using naming conventions as described below which make it easy to distinguish between tenant-specific and global catalogs.
The catalog values are saved in a JSON file in the config server beside the corresponding schema configuration.
Catalogs can be set as readonly via Web-API gateway. Thus, the catalog values cannot be modified via the dms-controller endpoints of the Web-API gateway. Since the client uses the dms-controller endpoints, the corresponding selection list elements in the client will also not be editable. Changes can be applied only via the system-controller endpoints in case of global catalogs and via the admin-controller endpoints in case of tenant-specific catalogs. This catalog management is also possible via yuuvis® architect.
In order to avoid empty selection lists in your client, we recommend to create the JSON configuration of the catalog first and introduce the definition into the schema afterwards.
Tenant-Specific Dynamic Catalogs
If only one specific tenant will use a dynamic catalog, it is recommended to configure this catalog as a tenant-specific property. Its technical name should follow the naming convention ten<tenantname>:<catalogname>. A user with access to the Admin Endpoints and admin-controller Endpoints (default: user with the YUUVIS_TENANT_ADMIN role) is required.
The catalog values are saved in the config server beside the tenant schema configuration.
In the following code block, an example schema definition of the example string property contract is displayed. The property is classified in line 6 to be a dynamic catalog which is displayed as a selection list with the technical name tenMytenant:contracts
in your client. Initially, the list of values offered to users will be empty.
1
2
3
4
5
6
7
<propertyStringDefinition>
<id>contract</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
<classification>dynamic:catalog[tenMytenant:contracts]</classification>
</propertyStringDefinition>
If the example schema is uploaded as a tenant schema via the POST /api/admin/schema endpoint by a user of the example tenant mytenant, the property contract will be available only in the specific tenant mytenant. After restarting your client, the users will get an empty selection list for the field called tenMytenant:contracts.
Global Dynamic Catalogs
If the dynamic catalog should be available to all tenants, it has to be configured as global property. This means that the property definition classified as dynamic catalog has to belong either to the system schema or to an app schema. Its values are stored in the config server besides the global schema or the corresponding app schema.
For catalogs in an app schema, we recommend the naming convention app<appname>:<catalogname>. For global catalogs, we recommend to use no special prefix but only the catalog name <catalogname>.
Also global dynamic catalogs can be defined to be editable for users with the advancedUserRole (default: users with the YUUVIS_MANAGE_SETTINGS role). If the modified catalog values are saved, a tenant-specific copy of the global JSON configuration is saved besides the tenant schema together with the values of tenant-specific catalogs. Whenever a global catalog is retrieved via the Web-API gateway, the tenant-specific copy will be returned for that tenant. If no tenant-specific copy exists, the global configuration is returned. This might happen if the global catalog is not editable or no changes were applied to the global catalog within the active tenant.
Not-Editable Global Catalogs
Users user with access to the System Endpoints and system-controller Endpoints (default: users with the YUUVIS_SYSTEM_INTEGRATOR role) can set up global catalogs with initial standard elements and set the catalogs to readonly.
In this case, you should only use standard values that are suitable for all tenants.
The following code block shows an example property definition cut from an example app schema. If the example schema is uploaded as an app schema via the POST /api/system/apps/{app}/schema endpoint for the example app myapplication, the property contract will not only be available for the specific app myapplication, but to all tenants using this app. After restarting your client, the users will get an empty selection list for the field called appMyapplication:contracts.
<propertyStringDefinition>
<id>contract</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
<classification>dynamic:catalog[appMyapplication:contracts]</classification>
</propertyStringDefinition>
The following code block shows an example property definition cut from an example system schema. If the example schema is uploaded as system schema via the POST /api/system/schema endpoint , the property contract will be available in all tenants and for all applications. After restarting your client, the users will get an empty selection list for the field called contracts.
<propertyStringDefinition>
<id>contract</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
<classification>dynamic:catalog[contracts]</classification>
</propertyStringDefinition>
Editable Global Catalogs
If the catalog parameter readonly is not set, users with the advancedUserRole (default: users with the YUUVIS_MANAGE_SETTINGS role) can change the list elements in your client. With the first update of such a catalog, a new catalog with the same technical name (without additional tenant-specific prefix) is saved for that tenant.
Changes of the global catalog saved via system-controller do not affect the copy. |
Editing Catalog Values
The following actions are supported for editable catalogs/selection lists:
-
Create a new list element.
-
Remove a list element. A warning is given if this element is used by an object.
-
Disable a list element. Such elements are offered for search but not while creating or editing an object.
Editing via Client
Users with the advancedUserRole (default: users with the YUUVIS_MANAGE_SETTINGS role) can maintain pick lists that are based on a property classified as a dynamic catalog without the readonly parameter.
The edit dialog can be opened by clicking the pencil icon next to the field. The screenshot below shows the edit dialog for the example selection list contracts where the four values Employment contract, Rental agreement, User contract, and Purchase contract were already added.
Editing via Web-API Gateway
admin-controller
Users with access to the admin-controller Endpoints (default: user with the YUUVIS_TENANT_ADMIN role) are offered the maintenance actions also in read-only catalogs via the Web-API Gateway GET and POST endpoints https://<domain>/api-web/admin/catalogs/tenMytenant:contracts.
The following example shows a tenant-specific list of four elements stored for the tenant mytenant:
{
"tenant": "Mytenant",
"readonly" true,
"entries": [
{
"name": "Employment contract",
"disabled": false
},
{
"name": "Rental agreement",
"disabled": false
},
{
"name": "User contract",
"disabled": false
},
{
"name": "Purchase contract",
"disabled": false
}
]
}
system-controller
In case of global catalogs, the Web-API Gateway system-controller endpoints GET and POST are used. In the default configuration, the role YUUVIS_SYSTEM_INTEGRATOR is required.
-
For the catalog contracts in the system schema: https://<domain>/api-web/system/catalogs/contracts
-
For the catalog contracts in the app schema myapplication: https://<domain>/api-web/system/catalogs/appMyapllication:contracts?appschemaname=appMyapplication
Global catalogs without an appschemaname are saved in the config service beside the system schema configuration. Otherwise, the catalogs are saved besides the app schema configurations.
dms-controller
The client uses the Web-API Gateway dms-controller endpoints that require per default the YUUVIS_MANAGE_SETTINGS role in case of POST and PATCH requests:
-
The values for the catalog are read with the GET endpoint https://<domain>/api-web/dms/catalogs/tenMytenant:contracts.
-
If the catalog does not exist, it is created with the POST endpoint https://<domain>/api-web/dms/catalogs/tenMytenant:contracts.
-
If the catalog already exists, changes of its values are saved with the PATCH endpoint https://<domain>/api-web/dms/catalogs/tenMytenant:contracts.
Swagger UI
There is a Swagger UI that supports you in using the mentioned endpoints: https://<domain>/api-web/swagger-ui.html. The screenshot below displays a part of the Web-API Gateway Swagger UI showing the first endpoints of the admin-controller.
4.5.8. Styling
If you are creating a new application intended to handle specific data of the yuuvis® backends and you only need the CSS files, you can use the npm package: https://www.npmjs.com/package/@yuuvis/styles.
Shortly, we will publish a website that shows all styles used as an example application on https://yuuvis-cc.yuuvis.org/
Changing the Appearance of Form Controls As with most of the components of the @yuuvis/framework, you are able to overwrite styling using CSS. To globally change the look and feel of components, we recommend to create a new *.scss file that you import in your project’s styles.scss (Make sure to place the import after the imported styles from @yuuvis/framework). The following code snippet changes the position of labels in forms:
1
2
3
4
5
6
7
8
9
10
11
yuv-object-form .yuv-form-input:not(.checkbox) .fe-wrapper {
> label {
order: 0;
}
> .control {
order: 1;
}
> .tag {
order: 2;
}
}
You could also position the labels at the top of the input:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
yuv-object-form .yuv-form-input:not(.checkbox) .fe-wrapper {
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: auto 1fr;
grid-template-areas:
'label tag'
'fe fe';
> label {
grid-area: label;
}
> .control {
grid-area: fe;
}
> .tag {
grid-area: tag;
}
}
4.5.9. Customizing the Dashboard
Feature in ALPHA Phase
As of version 2022 Winter, the feature is still in a testing phase. We preserve the right to apply any changes to its functionality.
|
The @yuuvis/widget-grid developer library allows users to individually customize the client’s dashboard according to their preferences.
A demo application shows how to configure widgets and how to use them to provide saved searches for the client user. Example code on gitHub.
Library Installation and Activation
Install and configure the @yuuvis/widget-grid and @yuuvis/widget-grid-widgets libraries with the widgets you want to enable for your users.
To enable the usage of a customizable dashboard in your client application, set the dashboardWorkspaces parameter to true in the main.json configuration file.
Users can now choose between the default dashboard and an individually designed custom dashboard via the client’s settings menu.
Configuring Workspaces
Users can configure multiple layouts for their dashboard and save them as so-called workspaces. To switch between workspaces, click the buttons with the workspace names in the bottom left corner.
Create a new workspace via the + Plus icon in the bottom left corner or edit the activated workspace via the Pencil icon in the bottom right corner. You can now
-
add new widgets via the + Plus icon in the bottom right corner,
-
change size and position of individual widgets by mouse actions
-
delete individual widgets or
-
edit individual widgets.
The edit mode for individual widgets depends on the widget type.
The custom dashboard configuration is stored via USERSERVICE and is thus available on any device in which users might log-in. However, users can activate the usage of the default dashboard or the customizable dashboard depending on their used device.
Widget Types
The following widget types are provided as default by the libraries. You can easily extend the list with your own widgets according to your needs. Just create a component and register it.
-
Hit list or count tile
-
Display search results for a configured query.
-
-
Stored query
-
Configure the search conditions you frequently need.
-
Specify the object type first if needed. A form with the corresponding metadata fields will open.
-
Specify conditions using the metadata fields if needed.
-
Specify a term for full-text search if needed.
-
Click Next to continue.
-
From the list of metadata fields presented on the left side, select the fields you want to fill via dashboard widget.
-
Click Next to continue.
-
Define the sorting to be applied to hit lists resulting from search requests coming from this widget.
-
Tick the total hits checkbox to display the number of hits as a preview on the dashboard before opening the hit list view.
-
-
Chart
-
Quick search
-
Display a search bar on your dashboard.
-
-
A picture
-
Add any image to your dashboard.
-
-
To do list
-
Display a checkbox list.
-
-
Summation
-
Specify a number-type metadata property available in one or more object types. All objects with this property will be searched and the values are totaled.
-
Additionally, you can apply conditions to the objects that should be included into the summation.
-
In the template field, you can add a measuring unit that will be always displayed with the calculated total number on the custom dashboard.
-
4.5.10. Form Scripting
If you configure custom forms for objects, you can additionally use executable scripts to, e.g., validate data, change data, change field properties - such as "read-only" or "mandatory" - and show context-related messages. Form-related scripts enhance your options by adding further functionalities to support your use cases and processes the best.
In yuuvis® Momentum client, you can use executable scripts to:
-
validate data
-
change data, for example by calculating a value based on other values
-
change field properties, such as read-only and visibility
-
show context-related messages.
Some things to note about script properties:
-
Client scripts in yuuvis® Momentum architect are written in JavaScript (ECMAScript).
-
Client scripts execute in the user’s browser using the browser’s native JavaScript runtime.
-
You can define client scripts by object type and form situation.
When field data changes are made using a script (i.e., without user action) when loading the form, the Save option is not available. In contrast, you can disable fields to protect against user changes. |
Script Scope
The relevant object is given to each client script under the name 'scope.' This object provides the API so the scripts can access the object fields and their properties.
Properties of scope
:
Name | Description |
---|---|
|
Supplies access to the plug-in API, with 'session' (user information), 'dms' (object details, search via DMS-Service), 'http' (connection to any service), 'config', 'util' (helper functions) and 'agent' properties. |
|
Supplies all object fields defined in the object or process activity. The fields offer read-only access using the technical name. Available for releases 2017-09-27 (3.22.x) or later. |
|
Supplies the flattened form model and all object fields defined on the form. The fields can be accessed with the technical name. The form groups cannot be accessed in this way. |
|
Supplies the current form model situation. Scripts can respond to the relevant situation. Possible values are 'CREATE' (create), 'SEARCH' (search) and 'EDIT' (edit index data). |
|
Supplies the ID of the current DMS object if available (available since version 6.4). |
scope.data
A value of a system property of an object can be read using scope.data['system:<property name>']. These are some of the available system properties. You can find more in the browser console when looking for the currently loaded form script and hovering over 'scope' and looking for section 'data':
Name | Description |
---|---|
|
Unique ID of the object |
|
Technical name of the object type, e.g., 'tenMytenant:customer' |
|
Specifies whether an object is of type 'folder' or 'document' |
|
The date and time of cration in the format 'yyyy-mm-ddThh-mm-ss.xxxZ' |
|
The title of the user that created the object in the format <name>,<surname> (<loginname>) |
|
The date and time of last modification in the format 'yyyy-mm-ddThh-mm-ss.xxxZ' |
|
The title of the last user that edited the object in the format <name>,<surname> (<loginname>) |
|
Current version number of the object |
|
This array lists all secondary object types that are part of the current object instance |
|
The tenant name as used when created |
|
Trace ID of the object (todo: write about the meaning) |
|
This ID is given if a document object is filed into a folder. |
1
2
3
4
// assign the current objectId to a reference field and the current userId to an organisation field:
scope.model['tenMytenant:reference'].value = scope.data['system:objectId'];
scope.model['tenMytenant:user'].value = scope.api.session.getUser().id;
For scope.api please refer to "Client Scripting API".
scope.situation
For object types, you can create a default form to be used for the CREATE, EDIT and SEARCH situations. In each situation, any included scripts are active. If a general form is used, but different data management is necessary, it is possible to check which situation is given. For example, how to deactivate a form script to be used in the 'SEARCH' situation.
1
2
if( scope.situation == 'CREATE' ) return; // another situation value is EDIT
// ... additional script code
scope.model
This section describes how to access all form elements of objects or processes.
General object field properties
The following table describes object field properties that can be accessed with 'scope.model'.
Column "Binding"
-
RO (ReadOnly): ReadOnly properties can only be read. Changes to the values of RO properties do not affect the interface.
-
RW (ReadWrite): ReadWrite properties can also be written. Changes to the values of RW properties affect the interface.
Each field has the following properties:
Name | Description | Binding |
---|---|---|
|
The normalized name of the fields. Normalized means the simple field name is lower case. The name must not contain special characters except one ':'. This name is used to map the fields to the 'model.' |
RO* |
|
The display name of the type in the current user locale. Used as a field identifier. |
RO |
|
A field description. Can be used in tooltips for example. |
RO |
|
Describes the data type of the field. The possible values here are documented in the description of field data types. Other field attributes may exist, depending on the data type. |
RO |
|
If the read-only property is set to 'true,' the user cannot change the field value. |
RW** |
|
Flags a field as mandatory. If this property is set, the user must make an entry. |
RW |
|
The current value of the field. |
RW |
|
In case of 'multi' instead of 'single' (equal 'undefined') a list of values can be maintained. A JavaScript array is then always expected in 'value.' Not every data type supports the 'multiselect' property. |
RO |
*RO (ReadOnly): ReadOnly properties can only be read. Value changes of RO properties do not affect the interface.
**RW (ReadWrite): ReadWrite properties can also be written. Value changes of RW properties affect the interface.
The following example validates dynamic field properties for required fields and write permissions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Abbreviate with 'm' in the FormModel of the scope.
// You could just use 'scope.model' everywhere instead of 'm'.
var m = scope.model;
// We want to know if the active state changes
// To do so, we register an onchange handler function
m['tenMytenant:aktiv'].onchange=updateActiveState;
// The logic should also run when there are changes in the area, since we want to
// control the error state of the script here.
m['tenMytenant:area'].onchange=updateActiveState;
// When the weekly hours change, we want to know this for our calculation
m['tenMytenant:weekhours'].onchange=updateWeekdays;
// Here is the logic implementation for what happens when the active state changes
function updateActiveState() {
// Employee initials + status + employee number are required fields,
// when the employee is active.
m['tenMytenant:emplshort'].required = active;
m['tenMytenant:status'].required = active;
m['tenMytenant:personnelno'].required = active;
// The regulations cannot be changed as long as the employee is active.
m['tenMytenant:unbefristet'].readonly = active;
m['tenMytenant:zielvereinbarung'].readonly = active;
m['tenMytenant:altersvorsorge'].readonly = active;
// Example for a deliberately set validation error with relevant error message
// take into account that the error message will be offered for non read-only fields!
if( active && (!m['tenMytenant:area'].value || m['tenMytenant:area'].value=='') ) {
m['tenMytenant:area'].error = {msg:'Ein aktiver Mitarbeiter muss einem Bereich zugeordnet sein.'};
} else {
// If the validation error does not occur, we may have to reset a previously set error:
if (scope.user) {
m['tenMytenant:area'].error = null;
}
m['tenMytenant:aea'].error = null;
}
}
// Here we calculate the weekdays
function updateWeekdays() {
m['tenMytenant:weekdays'].value=m['tenMytenant:weekdays'].value / 8;
}
// Since the active/not active logic should already apply during form initialization,
// we call the function here.
updateActiveState();
Data types
The following table gives an overview of the possible data types per field. The JavaScript data type lists what is expected as the 'value' of an element.
If the 'multiselect' property is set, then the JavaScript data type is an array of the data type.
Name | Description | JavaScript data type | Multi-selection |
---|---|---|---|
STRING |
Any text. See also datatype: STRING. |
String |
Yes |
NUMBER |
Number and floating point number. See also datatype: NUMBER. |
Number |
Yes |
BOOLEAN |
Simple 'on/off' or 'true/false' value. |
Boolean |
No |
DATETIME |
A date or a date with time value. |
Date |
Yes |
ORGANIZATION |
A string field for saving user IDs. The title of the user is shown, or the ID if no title exists. |
String |
Yes |
ID |
A string field for saving object IDs. The IDs can be restricted to the specified object types defined in the classification tag 'id:reference[object type 1, object type 2, …]. The title of the object is shown, or the ID if no title exists, or '!' if the object cannot be accessed. String Yes CATALOG A string field for saving elements of a given array in the classification tag 'catalog[value1, value2, …]' String Yes TABLE A table with columns of the above data types |
Table |
No |
STRING
For fields of type 'string' the following properties are given:
Name | Description | Binding |
---|---|---|
|
The maximum number of characters permitted as a value in this field. |
RO |
|
The minimum number of characters permitted as a value in this field. RO |
|
*RO (ReadOnly): ReadOnly properties can only be read. Changes to values of RO properties do not affect the interface.
**RW (ReadWrite): ReadWrite properties can also be written. Changes to values of RW properties affect the interface.
NUMBERS
For fields of type integer and decimal the following properties are given:
Name | Description | Binding |
---|---|---|
|
The maximum number permitted as a value in this field. |
RO |
|
The minimum number permitted as a value in this field. |
RO |
|
If 'digital' is set the numbers are formatted with a thousand separator, e.g. for Din EN 1,569,345.43 and DE 1.569.345,43 |
RO |
*RO (ReadOnly): ReadOnly properties can only be read. Changes to values of RO properties do not affect the interface.
**RW (ReadWrite): ReadWrite properties can also be written. Changes to values of RW properties affect the interface.
DATE
Sample Script: Specifying a date in the future
When determining a deadline for working on the next process step, you want to make sure the date is not in the past.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var m=scope.model;
// The name of the date field is Deadline
var deadline=m['myTenant:deadline'];
// Register the onchange handler
deadline.onchange=updateDeadlineState;
// Next is the logic for what we want to happen if the state changes
function updateDeadlineState() {
if( isBeforeToday( deadline.value ) ) {
deadline.error = {msg:'Please select a date in the future.'};
} else {
// If the validation error does not occur, we may have to delete a previously-set error
deadline.error = null;
}
}
function isBeforeToday( pDate ) {
// Todo: rework not available moment to a different function:
var date = new Date();
var today = moment(date).startOf('day');
return moment(pDate).isBefore(today);
}
DATETIME
Important to know:
1
2
3
4
5
6
// allowed:
scope.model['tenMytenant:datetime'].value = new Date()
scope.model['tenMytenant:datetime'].value = moment().toDate()
// not allowed, sets the date one day into the past after save:
scope.model['tenMytenant:datetime'].value = moment();
TABLE
As of version 2.4, tables are supported.
Expects a JavaScript 'Object Array' as a 'value.' The properties of each object are defined by the column elements of the table. See the following example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* Example script: Manipulating table data based on index data change.
*/
// Add change listener to field 'myTenant:number'
scope.model.['myTenant:number'].onchange=function() {
// The current user input on field with the internal name 'myTenant:number'
var num = scope.model.['myTenant:number'].value;
// Shortcut to access the table
var table = scope.model.['myTenant:changes'];
if(num>0 ) {
// If 'myTenant:number' is set (greater than 0) we automatically fill the table
if( !table.readonly ) {
// The user may not modify the table
table.readonly=true
}
} else {
// If 'myTenant:number' is not set (less than 0) we let the user fill the table
if( table.readonly ) {
// The user may modify the table
table.readonly=false
}
}
// automatically fills the table if 'myTenant:number' is greater than 0
// and add num rows to the table
if(num>0) {
// Clean up the table by setting a empty array
table.value.length=0; // changes of a single cell must be done in an array variable first,
// and then this array has to be pushed back to the table.
for( i=0; i<num; i++ ) {
// For each 'myTenant:number' add a row
// Each row is an object defined by the internal names of the column elements.
table.value.push(
{
'myTenant:accepted': i%2, // Boolean
'myTenant:created': new Date() , // Date
'myTenant:activedate': new Date(), // Another date
'myTenant:author': 'Marie Curie '+i, // String: Author name with i postfix
'myTenant:prio': i+.42, // Decimal
'myTenant:company' : 'OSVH' // Codesystem - the 'data' values must be used.
}
)
} // end for num
} // end if num>0
}
Callback for tables:
Name | Description |
---|---|
|
This callback is called when the user starts to edit a table row. Like 'onchange,' the first parameter contains the field element (the table itself). The second parameter contains a 'row' object, which describes the row the user wants to edit. |
The 'row' object
The 'row' object is transferred as the second parameter during the 'onrowedit' callback for table fields.
Name | Description | Binding |
---|---|---|
|
Row index: '-1' for newly created rows. The first row has the value '0'. |
RO* |
|
Controls whether the "Copy and create as new row" function is enabled. You can only edit this synchronously inside the onrowedit. |
RW** |
|
Controls whether the "Delete row" feature is enabled. You can only edit this synchronously inside the onrowedit. |
RW |
|
Controls whether the "Save row" feature is enabled. You can only edit this synchronously inside the onrowedit. |
RW |
|
Is 'false' if the edited file was newly created. The property remains 'false' for new rows until the index data is saved. You can use this property to differentiate between a row that has been saved or newly created by the user during the current index data editing. |
RO |
|
Provides access to the model of the current row. With this model, the script can access and modify the values and element properties of the current row. |
RW |
*RO (ReadOnly): ReadOnly properties can only be read. Value changes of RO properties do not affect the interface.
**RW (ReadWrite): ReadWrite properties can also be written. Value changes of RW properties affect the interface.
See how the 'row' object is used in the following example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Example for row edit
// The 'scope.model.['myTenant:notices']' element is a table type with a few columns.
// This example script tries to achieve that only new rows can be edited. New rows are rows that the user has not saved yet.
scope.model.['myTenant:notices'].onrowedit=function(table,row) {
// 'table' is the element, the callback event was triggered.
// In this case the same as scope.model.notices. 'row' is the row object.
// Show some information as a toast notification - just for demonstration
scope.api.util.notifier.info("Editing table row","A row at index "+row.index+" is being edited.");
// First we check whether the row is a new, not yet persisted, row, or an existing row
if(!row.persisted) {
// This is a row created by the user.
// He is allowed to change it. So all table columns are set to be editable
// by setting all row fields' readonly property (the column elements) to false.
Object.keys(row.model).forEach( function(e) { e.readonly=false });
// Delete/save is enabled by default, but the user is not allowed to copy the existing row as a new one.
// So we switch off the copy function.
row.copyEnabled = false;
} else {
// This is an already-saved row, so cell values are no longer editable, we have set them all to read only.
Object.keys(row.model).forEach( function(e) { e.readonly=true });
// Copy/delete/save are all disabled. The user can only 'cancel' the row editing. Nothing else.
row.copyEnabled = false;
row.deleteEnabled = false;
row.saveEnabled = false;
}
}
onChange handler for table cells
You define table rows in the form model (scope.model). Here you can set properties for each row. When the user edits a row, the system creates a temporary copy of the table elements. This copy can be accessed by a form script using the second parameter in the onchange Handler. Changes to the model are immediately visible in the table editing dialog. Changes to the properties of rowmodel are discarded when row editing has ended.
1
2
3
4
5
6
7
scope.model.['myTenant:mytable'].onrowedit = function(table, row){
// On this element we register a value change handler
row.model.['myTenant:number'].onchange = function(el, rowmodel) {
// The rowmodel provides access to the other elements
rowmodel.['myTenant:number'].readonly = ( el.value == 42 );
}
}
1
2
3
4
5
6
7
8
9
var countries = scope.model.['myTenant:addresslist'].onrowedit=function(table,row){
row.model.['myTenant:country'].onchange=function() {
if(row.model.['myTenant:country'].value === 'Germany'){
row.model.['myTenant:zip'].required=true; // depending on value of country set a zip code as mandatory
} else {
row.model.['myTenant:zip'].required=false;
}
}
}
Manipulating multiple row cells
If we deal with more complex table value manipulation, we need to create a copy of the values. Once the values are written, the table is populated and changes will be lost. Once all the cell manipulations are done, we can assign the manipulated values to the table values.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// see Manipulating table data
...
let tableCopy = JSON.parse(JSON.stringify(['myTenant:mytable'].value)); //create a copy
for ( i = 0; i < num; i++ ) {
if (i === 0) {
tableCopy[i].['myTenant:accepted'] = !i%2, // Boolean
tableCopy[i].['myTenant:created'] = new Date(), // Date
tableCopy[i].['myTenant:activedate'] = new Date(), // Another date
tableCopy[i].['myTenant:author'] = 'Pierre Curie '+i, // String: Author name with i postfix
tableCopy[i].['myTenant:prio'] = i+.00, // Decimal
tableCopy[i].['myTenant:company'] = 'OSVH' // Catalog values must be used.
} else {
// For each number add a row
// Each row is an object defined by the internal names of the column elements.
tableCopy.push({
'myTenant:accepted': i%2, // Boolean
'myTenant:created': new Date(), // Date
'myTenant:activedate': new Date(), // Another date
'myTenant:author': 'Marie Curie '+i, // String: Author name with i postfix
'myTenant:prio': i+.42, // Decimal
'myTenant:company': 'OSVH' // String: Element of a catalog
});
}
// do even more fancy data manipulations
} // end for num
table.value = tableCopy;
...
// see Manipulating table data
scope.api.<more>
Please refer to the Client Scripting API documentation for more features you may use for specific requirements like notifying users, getting information about the current user, or calling other services via http.
4.5.11. Client Scripting
This article describes the Client Scripting API used to develop custom clients as well as client-side form scripts. For more information on building custom clients, refer to the client API documentation.
scope.api
The API is available by using scope.api.<more>
scope.api.router
Please note that this function is not supported in the form scripts.
scope.api.router.get() returns the Angular router.
Example:
scope.api.router.navigate('/versions/edfd46a3-daa9-4192-8223-2cc6d4847314?version=2') leads the application to open the 'version' state with this object ID focussing version 2.
scope.api.events
Please note that this function is not supported in the form scripts
Events can be triggered by a component. Listening components can then react.
Type of events
There are several client-specific events. The most common ones are bundled in the const "yuvEvent."
Inside a form script they are bundled in the "scope.api.events.yuuvisEventType" const .
Type | Description | Data |
---|---|---|
LOGOUT |
on logout |
|
CLIENT_LOCALE_CHANGED |
the client locale has changed |
ISO locale string |
DMS_OBJECT_DELETED |
a DMS object was deleted |
the deleted DMS object |
DMS_OBJECT_UPDATED |
a DMS object was updated (index data, content, subscription, …) |
the updated DMS object |
DMS_OBJECTS_MOVED |
DMS objects were moved to another folder object |
the moved DMS objects |
DIALOG_STACK_CHANGED |
the dialog stack has changed |
an object with ID and active status of the dialog |
scope.api.events.trigger()
Please note that this function is not supported in the form scripts.
With this function, you can trigger an event of a type mentioned above.
Parameter | Type | Description |
---|---|---|
type |
string |
type of the event |
data |
any |
(optional) data associated with the event |
1
scope.api.events.trigger(DMS_OBJECT_UPDATED, dmsObject);
scope.api.events.on()
With this function, you can listen to events of the type mentioned above.
Parameter | Type | Description |
---|---|---|
type |
string |
type of the event |
Returns an Observable containing type and data.
scope.api.events.on(scope.api.events.yuuvisEventType.DMS_OBJECT_UPDATED).subscribe(event => {
let dmsObject = event.data;
let eventType = event.type;
});
scope.api.session
Currently, only the following session function is available.
scope.api.session.getUser() (user information)
The function scope.api.session.getUser() returns the user object, in which the following properties about the currently logged-in user are available. They are read-only.
Name | Description |
---|---|
id |
System ID given by the identity service |
username |
Login name |
firstname |
First name |
lastname |
Last name |
title |
Displayed name in the format of lastname, firstname |
E-mail address authorities String array with the roles for which the user is authorized |
|
userSettings.locale |
Application language in ISO code (de, en, …) as configured in the client settings |
Sample script:
1
2
3
4
5
6
// Write information for the current user in a model value
// The model value must be a STRING type.
var u=scope.api.session.getUser();
scope.model['tenMytenant:text'].value=
'- Login name \n'+u.name+'\n'+
'- Roles \n'+u.authorities.join()+'\n'+
scope.api.util
A list of helper functions follows:
scope.api.util.notifier (display messages)
This helper can be used to display messages in the form of a toaster.
Functions:
Name | Description | Color | since version |
---|---|---|---|
success(message[,title]) |
Displays a success message |
Green |
3.3 |
error(message[,title]) |
Displays an error message |
Red |
3.3 |
info(message[,title]) |
Displays an informational message |
Gray |
3.3 |
warning(message[,title]) |
Displays a warning message |
Orange |
4.1 |
1
2
3
4
5
6
7
8
scope.model['tenMytenant:unlimited'].onchange=function() {
if( scope.model['tenMytenant:unlimited'].value ) {
scope.api.util.notifier.success(
scope.model['tenMytenant:firstname'].value +' ' + ...', // Message
'Personal information changed' // optional: use a short title
);
}
}
The success message is displayed in green.
scope.api.util.encodeFileName
Please note that this function is not supported in the form scripts
Encodes a file name safe for sending characters beyond ASCII-7bit using quoted printable encoding.
More information to come.
scope.api.http
You can use HTTP requests to get data from any service of the system, including custom microservices, which are part of the yuuvis® Momentum microservice infrastructure.
The following standard functions are supported: get, post, put and delete.
If you want a format different from JSON, you have to add a third parameter {responseType: 'arraybuffer' | 'blob' | 'json' | 'text'}.
scope.api.http.get
This function works with a mandatory parameter for the url and a second optional one that controls whether to use the core-api endpoints instead of those of the API-WEB (web-api gateway) which is the primary one for the client.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// http.get example: request for extraction data and map value of key to field:
var objectId = scope.data['system:objectId'];
scope.model['extract'].onchange=getextraction; // idea: if boolean field gets checked, request for JSON-formatted extraction data
// extraction service delivers an object with JSON-based data
function getextraction(){
if (scope.model['extract'].value){
var httprequest='/dms/objects/'+objectId+'/contents/renditions/extract'; // call the extraction service
scope.api.http.get(httprequest,'core').then(
function(result) {
scope.model['tenKolibri:subject'].value = [result.data['OS:Subject']]; // map the value to field
},
function(error) {
scope.api.util.notifier.error('Failed to get extraction data', 'Error');
}
)
}
}
scope.api.http.del
The following script deletes an object:
1
2
3
4
5
6
7
8
9
10
11
12
// how to delete an object
var objectId = '7B683C8E19BD492198F6A262D14EF43F';
// use the web-api gateway endpoint:
scope.api.http.del('/dms/' + objectId).then(
function(result) {
scope.api.util.notifier.info('Succeded to delete object: ' + objectId, 'Success');
},
function(error) {
scope.api.util.notifier.error('Failed to delete object ' + objectId, 'Error');
}
);
scope.api.http.post
The following example creates a follow-up for the current object:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function httppost() {
var objectId1 = scope.data['system:objectId'];
var inst = {
"processDefinitionKey":"follow-up",
"name":"follow-up",
"businessKey":objectId1,
"returnVariables":true,
"variables": [
{
"name":"expiryDateTime",
"value":"2020-10-24T09:57:00"
},
{
"name":"whatAbout",
"value":"some reminder"
},
{
"name":"documentId",
"value":objectId1
}
]
};
scope.api.http.post('/bpm/process/instances', inst).then(
function(result){
scope.api.util.notifier.info('A follow-up for the following object is created: ' + objectId1, 'Success');
},
function(error){
scope.api.util.notifier.error('A follow-up for the following object could not be created ' + objectId1, 'Error');
console.log({error});
}
)
scope.api.dms
This section describes the read access to object information.
scope.api.dms.getObject()
Loads a DMS object from the backend
Parameter | Type | Description |
---|---|---|
id |
string |
The id of the DMS object to be fetched. |
version |
string |
optional: retrieve a specific version of the DMS object. |
1
2
3
4
5
6
7
8
9
10
11
12
// example: get object of a given ID
var objectId = '7B683C8E19BD492198F6A262D14EF43F';
scope.api.dms.getObject(objectId).then(
function(result) {
scope.api.util.notifier.info(result.title, 'Title of Object');
// index-values can be found in result.data
// example: result.data.companyname
},
function(error) {
scope.api.util.notifier.error(''+error, 'An error occured');
}
);
4.5.12. Extending Clients with Plug-ins
The PluginsService provided by the framework library allows for extending clients with custom HTML code via a configuration file (s. API documentation for detailed information). The corresponding configuration file is managed via the Web-API Gateway endpoints. It is a simple and fast procedure without the necessity of rebuilding and deployment.
Endpoints for Plug-in Configuration Management
The Web-API gateway provides separate endpoints for the management of tenant-specific and global configuration files. This applies to the plug-in configuration files as well. Use plugin-config as value for the path parameter name. Import an empty JSON file to remove the configuration.
Global:
-
GET /api-web/api/system/resources/config/{name}
- Retrieves the global configuration file specified by name. -
POST /api-web/api/system/resources/config/{name}` - Updates the global configuration file specified by name with the data passed in JSON format in the request body.
Tenant-specific:
-
GET /api-web/api/admin/resources/config/{name}
- Retrieves the tenant-specific configuration file specified by name. -
POST /api-web/api/admin/resources/config/{name}
- Updates a tenant-specific configuration file specified by name with the data passed in JSON format in the request body.
Structure of the Configuration File
The configuration file is in JSON format. The disabled key controls whether the client will use the defined plug-ins or not. The load function is executed once the client is loaded. The following example shows how to disable plug-ins for users with specific roles and how to change the application theme via custom styles. The other sections are described below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"disabled": "() => !api.session.user.hasRole('YUUVIS_TENANT_ADMIN')",
"load": "() => api.util.styles('body, body.dark { --color-accent-rgb: 131, 108, 172; --color-accent: rgb(var(--color-accent-rgb)); --theme-logo-width: 50px; --theme-background: url(https://images.unsplash.com/photo-1460411794035-42aac080490a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1950&q=80); --theme-logo: url(https://images.unsplash.com/photo-1460411794035-42aac080490a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=50&q=80); --theme-logo-big: url(https://images.unsplash.com/photo-1460411794035-42aac080490a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=250&q=80); }', '_pluginStyles')",
"links": [],
"states": [],
"actions": [],
"viewers": [],
"extensions": [],
"triggers": [],
"translations": {
"en": {},
"de": {}
}
}
Detailed descriptions of the properties can be found in the documentation (s. PluginConfigList interface in framework library).
Plug-in Links
Configured links with a path and label can be hooked into the main menu or the settings menu. The label must be configured in the translations section as shown below.
1
2
3
4
5
6
7
8
9
10
{
"links": [
{
"id": "yuv.custom.link.home_yuuvis",
"label": "yuv.custom.action.home_yuuvis.label",
"path": "https://help.optimal-systems.com/yuuvis/home_yuuvis_en.html",
"matchHook": "yuv-sidebar-navigation|yuv-sidebar-settings"
}
]
}
Detailed descriptions of the properties can be found in the documentation (s. PluginLinkConfig interface in framework library).
Plug-in States
States are new views with their own URL that are mostly reached by clicking a main menu item (see Extend Links). The following example shows how to integrate the user management view of yuuvis® architect as a new view into the client. This view can be opened via a new main menu item 'User management.' This item is offered if the user has the YUUVIS_TENANT_ADMIN role.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"states": [
{
"id": "yuv.custom.state.architect.users",
"label": "yuv.custom.state.architect.users",
"path": "architect/users",
"matchHook": "yuv-sidebar-navigation",
"canActivate": "(currentRoute, currentState) => {return this.session.getUser().authorities.includes('YUUVIS_TENANT_ADMIN');}",
"canDeactivate": "(component, currentRoute, currentState, nextState) => true",
"plugin": {
"src": "https://kolibri.enaioci.net/architect/users",
"html": "<style>iframe[src=\"https://kolibri.enaioci.net/architect/users\"] {display: block; height: calc(100% + 50px); margin-top: -50px;}</style>"
}
}
],
"translations": {
"en": {
"yuv.custom.state.architect.users": "User management"
},
"de": {
"yuv.custom.state.architect.users": "Benutzermanagement"
}
}
}
Detailed descriptions of the properties can be found in the documentation (s. PluginStateConfig interface in framework library).
Plug-in Actions
In general, object actions that are listed in the actions menu provide specific functions that manipulate the focused object, e.g., Download, Manage follow-ups, Open versions, … in yuuvis® client as reference implementation. If you want to include all original actions, use "" instead of listing them individually. Note that the position of the listed actions (or the "" if all actions are specified) within the script is irrelevant. The following example shows the implementation of an action that lets you navigate to the dashboard.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"actions": [
"yuv-download-action",
"yuv-delete-action",
"yuv-upload-action",
"yuv-move-action",
{
"id": "yuv.custom.action.home_yuuvis.list",
"label": "yuv.custom.action.home_yuuvis.list",
"description": "yuv.custom.action.home_yuuvis.description",
"icon": "",
"isExecutable": "(item) => item.id",
"header": "yuv.custom.action.home_yuuvis.label",
"subActionComponents": [
{
"id": "yuv.custom.action.home_yuuvis.sub.simple",
"label": "yuv.custom.action.home_yuuvis.simple",
"description": "yuv.custom.action.home_yuuvis.description",
"priority": 0,
"icon": "",
"group": "common",
"range": "MULTI_SELECT",
"isExecutable": "(item) => item.id",
"run": "(selection) => this.router.navigate(['dashboard'])"
}]
}
]
}
Detailed descriptions of the properties can be found in the documentation (s. PluginActionConfig interface framework library).
Plug-in Viewers
The Preview of the document file can be customized via a custom viewer configuration. The following example shows how to:
-
redirect of office files to external service (Office 365 viewer)
-
redirect of javascript and json files to monaco editor (line 18)
-
redirect of text files to monaco editor (line 19)
-
redirect of audio and video files to a custom video viewer (line 20)
-
redirect of xml files to monaco editor (line 21)
-
redirect of images to a custom image viewer (line 22)
-
redirect of text and audio and video files to a native html viewer (line 23)
-
customize the viewer path for each file (line 24)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"viewers": [
{
"mimeType": [
"application/msword",
"application/vnd.ms-excel",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/vnd.openxmlformats-officedocument.presentationml.template",
"application/vnd.openxmlformats-officedocument.presentationml.slideshow"
],
"viewer": "externals/office?path=${path}#locale=${locale}&direction=${direction}&theme=${theme}&accentColor=${accentColor}&fileName=${fileName}&fileExtension=${fileExtension}"
},
{"fileExtension": ["js", "json"], "viewer": "assets/_default/monaco/index.html?file=${file}&lang=${lang}"},
{"mimeType": ["text/plain"], "viewer": "assets/_default/monaco/index.html?file=${file}&lang=${lang}¶ms={\"lineNumbers\":\"off\"}"},
{"mimeType": ["audio/mp3", "video/mp4"], "viewer": "assets/_default/video/index.html?file=${path}&lang=${lang}"},
{"mimeType": ["text/xml"], "viewer": "assets/_default/monaco/index.html?language=xml&responseType=xml&file=${file}&lang=${lang}"},
{"mimeType": ["image/jpeg", "image/png", "image/x-ms-bmp"], "viewer": "assets/_default/image/index.html?file=${file}&lang=${lang}"},
{"mimeType": ["text/plain", "audio/mp3", "video/mp4"], "viewer": "() => parameters.path"},
{"mimeType": "*", "type": "extend", "viewer": "() => parameters.mimeType === "text/plain" ? parameters.viewer + '&extend'" : parameters.defaultViewer},
]
}
Detailed descriptions of the properties can be found in the documentation (s. PluginViewerConfig interface in framework library).
Plug-in Extensions
The standard aspects of the object details offer general views of the data of the object: an Overview of all metadata with the possibility to edit the custom Metadata, a Preview of the document file and a History of system events. If you need more views of data that are residing in other services, you can add more such aspects. Custom extensions are also available for the Content Preview or Search Filter Panel. The following example shows:
-
Tab component – how to load a custom html page via iframe (line 4)
-
Tab component – custom html code and styles rendition (line 10)
-
Tab component – a custom component rendition (line 20)
-
Content preview – custom buttons to select the next/previous grid row (line 30)
-
Search filter panel – a custom filter with the dynamic values CURRENT_USER and TODAY (line 39)
-
Search filter panel – a custom filter group generated from a static catalog (line 68)
-
Search filter panel – a custom filter group generated from a dynamic catalog (line 79)
-
Search filter panel – custom filter groups generated from all available catalogs (line 90)
-
Search filter panel – a custom filter with a dynamic date range - next 28 days (TODAY,TODAY+27) (line 103)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{
"extensions": [
{
"id": "yuv.custom.extension.home_yuuvis",
"label": "yuv.custom.extension.home_yuuvis.label",
"matchHook": "yuv-result|yuv-object",
"plugin": { "src" : "https://help.optimal-systems.com/yuuvis/home_yuuvis_en.html" }
},
{
"id": "yuv.custom.extension.home_yuuvis.complex",
"label": "yuv.custom.extension.home_yuuvis.description",
"matchHook": "yuv-result|yuv-object",
"plugin": {
"html": "<a href='https://help.optimal-systems.com/yuuvis/home_yuuvis_en.html'> yuuvis Home </a> <button onclick=\"api.router.navigate(['dashboard'])\">Go to dashboard</button>",
"styles": ["a {color: red;}"],
"styleUrls": []
}
},
{
"id": "yuv.custom.extension.quickfinder",
"label": "yuv.custom.extension.home_yuuvis.description",
"matchHook": "yuv-result|yuv-object",
"plugin": {
"component": "yuv-quickfinder",
"inputs": { "autofocus": true, "allowedTargetTypes": ["appPersonalfile:pfpersonalfile"]},
"outputs": { "objectSelect": "(selection) => { parent.selection = selection; }"}
}
},
{
"id": "yuv.custom.extension.content.preview.navigation",
"label": "yuv.custom.extension.content.preview.navigation",
"matchHook": "yuv-content-preview",
"plugin": {
"html": "() => { window._selectRow = (next) => { var el = api.util.$('.ag-center-cols-viewport .ag-row-selected')[next ? 'nextSibling' : 'previousSibling']; el && el.click();}; return '<div class=\"preview-navigation\"><button onclick=\"_selectRow()\">⇦</button><button onclick=\"_selectRow(true)\">⇨</button></div>';}",
"styles": ["{ flex: 1; }", ".preview-navigation { display: flex; justify-content: center; margin: 0 4px; }", ".preview-navigation button { padding: 1px 4px; }"]
}
},
{
"id": "yuv.custom.extension.search.filter.createdBy.me",
"label": "yuv.custom.extension.search.filter.createdBy.me",
"matchHook": "yuv-search-result",
"plugin": {
"component": "SearchFilterGroup",
"inputs": {
"skipCount": false,
"skipTranslate": false,
"query": [
{
"lo": "OR",
"filters": [
{
"f": "system:createdBy",
"o": "eq",
"v1": "$CURRENT_USER$|eq"
},
{
"f": "system:creationDate",
"o": "lte",
"v1": "$TODAY$|lte"
}
]
}
]
}
}
},
{
"id": "yuv.custom.extension.search.filter.catalog.static",
"label": "yuv.custom.extension.search.filter.catalog.static",
"matchHook": "yuv-search-result",
"plugin": {
"component": "PluginSearchComponent",
"inputs": {
"init": "() => {return component.catalogToSelectableGroup('tenKolibri:strcatalogaddress');}"
}
}
},
{
"id": "yuv.custom.extension.search.filter.catalog.dynamic",
"label": "yuv.custom.extension.search.filter.catalog.dynamic",
"matchHook": "yuv-search-result",
"plugin": {
"component": "PluginSearchComponent",
"inputs": {
"init": "() => {return component.catalogToSelectableGroup('tenKolibri:strcataloggermancountries', component.loadCatalogOptions('tenKolibri:germancountries').then(countries => countries));}"
}
}
},
{
"id": "yuv.custom.extension.search.filter.catalog.all",
"label": "yuv.custom.extension.search.filter.catalog.all",
"matchHook": "yuv-search-result",
"plugin": {
"component": "PluginSearchComponent",
"inputs": {
"maxHeight": 300,
"hideZeroCount": true,
"init": "() => {return component.getAvailableCatalogs().map(f => component.catalogToSelectableGroup(f.id));}"
}
}
},
{
"id": "yuv.custom.extension.search.filter.date.future",
"label": "yuv.custom.extension.search.filter.date.future",
"matchHook": "yuv-search-result",
"plugin": {
"component": "PluginSearchComponent",
"inputs": {
"init": "() => {return component.toSelectable(component.extension, { array: [new SearchFilter('system:lastModificationDate', SearchFilter.OPERATOR.EQUAL, '$TODAY$,$TODAY$+27|eq')]});}"
}
}
}
]
}
Detailed descriptions of the properties can be found in the documentation (s. PluginExtensionConfig interface in framework library).
Plug-in Triggers
Form controls support users in entering data in formats such as strings, numbers, dates, booleans, or more specific ones such as e-mail addresses, users or references to other objects. If you need more such specific controls, you can extend the form controls as shown in the following example:
-
paste the copied text to input via trigger (line 4)
-
custom value picker for input via dialog (line 12)
-
customize the reference component behavior to search for specific values (line 31)
-
custom dynamic date for date filter (line 37)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{
"triggers": [
{
"id": "yuv.custom.trigger.paste.clipboard",
"label": "yuv.custom.trigger.paste.clipboard",
"matchHook": "yuv-*",
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-hidden=\"true\" focusable=\"false\" width=\"1em\" height=\"1em\" preserveAspectRatio=\"xMidYMid meet\" viewBox=\"0 0 24 24\"><path opacity=\".3\" d=\"M17 7H7V4H5v16h14V4h-2z\" fill=\"white\"/><path d=\"M19 2h-4.18C14.4.84 13.3 0 12 0S9.6.84 9.18 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1s-1-.45-1-1s.45-1 1-1zm7 18H5V4h2v3h10V4h2v16z\" fill=\"#626262\"/></svg>",
"isExecutable": "(component) => component.parent.formControlName",
"run": "(component) => {var _this = this; navigator.clipboard.readText().then((v) => v && _this.form.modelChange(component.parent.formControlName, {name: 'value', newValue: v}))}"
},
{
"id": "yuv.custom.trigger.quickfinder",
"label": "yuv.custom.trigger.quickfinder",
"matchHook": "yuv-*",
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-hidden=\"true\" focusable=\"false\" width=\"1em\" height=\"1em\" preserveAspectRatio=\"xMidYMid meet\" viewBox=\"0 0 24 24\"><path opacity=\".3\" d=\"M17 7H7V4H5v16h14V4h-2z\" fill=\"hotpink\"/><path d=\"M19 2h-4.18C14.4.84 13.3 0 12 0S9.6.84 9.18 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1s-1-.45-1-1s.45-1 1-1zm7 18H5V4h2v3h10V4h2v16z\" fill=\"#626262\"/></svg>",
"group": "visible",
"buttons": {},
"plugin": {
"component": "yuv-quickfinder",
"inputs": { "autofocus": true, "allowedTargetTypes": ["appPersonalfile:pfpersonalfile"]},
"outputs": { "objectSelect": "(selection) => { parent.selection = selection; }"},
"popoverConfig": {
"height": "30%",
"width": "50%"
}
},
"isExecutable": "() => parent.formControlName === 'appClient:clienttitle'",
"run": "() => { parent.selection = {}; trigger.openPopover().afterClosed().subscribe((result) => { result && api.form.modelChange('appClient:clientdescription', { name: 'value', newValue: parent.selection.description || '' }); });}"
},
{
"id": "yuv.custom.trigger.reference",
"matchHook": "yuv-reference",
"isExecutable": "() => parent.formControlName === null",
"run": "() => { var ref = parent.childComponent; ref.descriptionField = 'system:objectId'; ref.allowedTargetTypes = ['appClient:minidoc']; ref.objectTypeFields = ['system:createdBy']; ref.searchFnc = (term) => { var ids = [api.form.getValue('appClient:clienttitle')]; ref.filters = ids && ids[0] ? [{'f':'appClient:clienttitle','o':'in','v1': ids}] : []; return Object.assign({term : '*{0}*'.replace('{0}', term)}, ref.queryJson);}; ref.objectSelect.subscribe(() => { var v = (parent.childComponent.innerValue || [])[0]; var val = (v && v.data && v.data.get('appClient:clienttitle')) || ''; api.form.setValue('appClient:clientdescription', val); });}"
},
{
"id": "yuv.custom.trigger.filter.variable.date",
"label": "yuv.custom.trigger.filter.variable.date",
"matchHook": "yuv-datetime-range",
"group": "hidden",
"isExecutable": "(component) => { return component.parent && component.parent.formControlName; }",
"run": "(component) => { component.parent.dateVariables = [{offset: 3, value: '$TODAY$,$TODAY$+2'}].concat(component.parent.dateVariables); }"
}
]
}
Detailed descriptions of the properties can be found in the documentation (s. PluginTriggerConfig interface in framework library).
Plug-in Translations
In case you need to extend translations with new keys, please specify translations for each language in your system.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
"translations": {
"en": {
"yuv.custom.action.home_yuuvis.label": "yuuvis Home",
"yuv.custom.action.home_yuuvis.description": "yuuvis Description",
"yuv.custom.action.home_yuuvis.simple": "yuuvis Home simple",
"yuv.custom.action.home_yuuvis.component": "yuuvis Home component",
"yuv.custom.action.home_yuuvis.component.full": "yuuvis Home component full",
"yuv.custom.action.home_yuuvis.link": "yuuvis Home link",
"yuv.custom.action.home_yuuvis.list": "yuuvis Home list",
"yuv.custom.trigger.paste.clipboard": "Paste clipboard",
"yuv.custom.trigger.paste.selection": "Paste selection",
"yuv.custom.trigger.paste.suggestion": "Paste suggestion"
},
"de": {
"yuv.custom.action.home_yuuvis.label": "yuuvis Home DE",
"yuv.custom.action.home_yuuvis.description": "yuuvis Description DE",
"yuv.custom.action.home_yuuvis.simple": "yuuvis Home simple DE",
"yuv.custom.action.home_yuuvis.component": "yuuvis Home component DE",
"yuv.custom.action.home_yuuvis.component.full": "yuuvis Home component full DE",
"yuv.custom.action.home_yuuvis.link": "yuuvis Home link DE",
"yuv.custom.action.home_yuuvis.list": "yuuvis Home list DE",
"yuv.custom.trigger.paste.clipboard": "Paste clipboard DE",
"yuv.custom.trigger.paste.selection": "Paste selection DE",
"yuv.custom.trigger.paste.suggestion": "Paste suggestion"
}
}
}
Activating the Extension Feature and Importing Your Plug-in Configuration
To import a configuration file with your extensions (plug-ins), follow these steps:
-
Open the client and open the settings.
-
Click On in the Plug-in Configuration. This feature is offered to all users with the YUUVIS_SYSTEM_INTEGRATOR role.
-
Click Import.
The file is uploaded to the configservice
so that all clients can use these extensions as well.
Removing the Configuration
Import an empty JSON file to remove the configuration.
Use Case Example
The following code block configures an action where a start form for a workflow process is offered.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"id": "yuv.custom.action.taskflow.id",
"label": "yuv.custom.action.taskflow.label",
"description": "yuv.custom.action.taskflow.description",
"priority": 1,
"icon": "<svg height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M0 0h24v24H0V0z\" fill=\"none\"></path> <path d=\"M4 10h12v2H4zM4 6h12v2H4zM4 14h8v2H4zM14 14v6l5-3z\"></path> </svg>",
"group": "further",
"range": "MULTI_SELECT",
"isExecutable": "(item) => item.id",
"buttons": {
"finish": "yuv.custom.action.workflow.start"
},
"plugin": {
"component": "yuv-object-form",
"inputs": {
"__initOptions": "() => this.http.get(`/resources/config/taskflow-startform`, 'api-web').then((res) => {component.cmp.options = {formModel: res.data.tenant, disabled: false}})",
"__init": "() =>parent.finished.subscribe((event) => {var selection = parent.selection;var cmp = component.cmp;var vars = [{ name: 'title', type: 'string', value: cmp.formData.title || '' },{ name: 'taskStatus', type: 'string', value: 'Open' },{ name: 'comment', type: 'string', value: cmp.formData.comment },{name: 'nextAssignee',type: 'string',value: cmp.formData.nextAssignee}];if (cmp.formData.expiryDatetime) {vars.push({name: 'expiryDatetime',type: 'date',value: cmp.formData.expiryDatetime,})}this.http.post('/bpm/processes',{businessKey: selection[0].id,name: selection[0].title || selection[0].id,processDefinitionKey: 'dms-lite-taskflow',attachments: selection.map((s) => s.id),subject: selection[0].title,variables: vars,},'api-web').then(() =>this.util.notifier.success(this.util.translate('yuv.custom.action.taskflow.success')))})"
},
"outputs": {
"statusChanged": "(status) => { parent.disabled = status.invalid; }"
}
}
},
The configured action retrieves the taskflow-startform form from the configuration resources. The framework component yuv-object-form offers the form via the object action menu:
The form displays the localized fields corresponding to the Flowable process variables: title (The task), expiryDatetime (Due until), comment (Comment for the next assignee) and nextAssignee (Next assignee).
The taskStatus variable that is internally used for process management is not displayed.
The expiryDatetime variable can be saved only by calling the dms-lite-taskflow process if a value is set. Thus, it is possible to prohibit setting a null value for the datetime variable which is not allowed in Flowable.
4.5.13. BPM Plug-in
The BPM Engine in yuuvis® Momentum is provided by the BPM-ENGINE service based on the workflow functionality of the open-source software Flowable. In yuuvis® client as reference implementation, it can be integrated in order to support process and task management via the browser application.
Administrators can model process models (process-definitions in Flowable nomenclature) with the help of a Flowable modeler, pack them and export them as applications, and deploy the applications to the BPM-ENGINE service in yuuvis® Momentum. Once deployed in such a manner, a process definition can be instantiated and executed in the BPM Engine. If process instances running in the bpm engine contain user tasks, they will be available in the Inbox of the user to whom they were assigned.
The following information is intended to support administrators to set up Flowable processes that are supported by the reference client.
Processes and Tasks in the Reference Client
yuuvis® client as reference implementation offers three specific views that allow users to handle processes based on Flowable:
-
Users can create follow-ups for each object via the action menu. The My follow-ups view lists all active follow-ups with their follow-up date.
-
The Inbox view lists all user tasks that are intended for the authenticated user, such as reminder tasks of follow-up processes that have reached their follow-up date.
-
As of version 2021 Autumn, all tasks of processes the currently logged-in user is assigned to are listed as well.
-
As of version 2021 Autumn, the new My processes view lists all processes started by the logged-in user.
Recommendations
-
If you start a process related to a document, the ID of the document should be saved in the process variable documentId. The reference client uses this variable to retrieve and display object details.
-
When starting a process, specify a meaningful value for the process property name since it will be shown in the Process column in the My processes view.
-
When modeling a workflow, specify meaningful names for Tasks, since they will be shown in the Task column in the Inbox view.
Inbox
As of version 2021 Autumn, besides the follow-up tasks, the inbox lists all other BPM tasks as well. The following properties are displayed:
Column in yuuvis® client | Technical details | Description |
---|---|---|
Type |
If the process parameter processDefinitionName is Follow-up, then Follow-up. Otherwise Task. As of 2021 Winter, an icon is displayed. If the process parameter processDefinition.idPrefix is follow-up, then a bell is shown and the tooltip shows Follow-up. Otherwise, a general process icon is shown and a tooltip with the localized prefix. If no localization is configured, the technical prefix is displayed. |
The description that was entered while creating the follow-up. |
Task |
Task name |
The time the follow-up (process) was created. |
as of 2021 Winter: Subject |
Web-API Gateway parameter subject, represented as Flowable string variable subject |
Set while creating the process or during the process while saving the Flowable process variable appClientsystem_subject of type string |
Received as of 2021 Winter: Received on |
Task CreateTime |
The date and time the task was created. The value corresponds to the due date that was entered while creating the follow-up. |
As of version 2021 Winter, the inbox offers a task details area with the aspects Task, History, and Attachments (not on the following screenshot).
The following screenshot shows the three possible elements of the aspect Task:
-
A static task description is shown if the task name (here: 2nd_task_dynform) that is set in the Flowable process model has a description representation in the localization for the language the user has set. Use the key <task name>_description for the task description and <task name>_title for localizing the task name itself.
-
Dynamic messages if the Flowable variable appClientsystem_taskMessages of type JSON have been saved. Message can be plane text lines or as unformatted lists. Colors are given by a level parameter. More details are given here: (link will come soon).
-
A static or dynamic form. The static form is set via Flowable formKey and a form model that was saved with this name. The dynamic form can be set by saving the Flowable variable appClientsystem_taskMessages of type JSON.
My processes
As of version 2021 Autumn, all processes including follow-ups are listed as soon as they are started by the user. The following properties are affected:
Column in yuuvis® client | Technical details | Description |
---|---|---|
Type |
Process-definition parameter processDefinitionName As of 2021 Winter, an icon is displayed. If the process parameter processDefinition.idPrefix is follow-up, then a bell is shown and the tooltip shows Follow-up. Otherwise, a general process icon is shown and a tooltip with the localized prefix. If no localization is configured, the technical prefix is displayed. |
Process definition name |
Process (not available anymore as of version 2021) |
Process-instance parameter name (as set when starting the process instance) |
Process instance name (e.g., a case number) |
Created on |
Process-instance parameter startTime |
The time the process was created. |
Status |
Derived from the process-instance parameters completed and suspended |
The status of the process can be running, suspended, or completed. The status is given in the user’s language. |
My follow-ups
This view lists the follow-up processes with the following specific properties:
Column in yuuvis® client | Corresponding Counterpart in BPM Engine | Description |
---|---|---|
Description (not available anymore as of version 2021) |
Process variable whatAbout |
The description that was entered while creating the follow-up. |
as of 2021 Winter: Subject |
Web-API Gateway parameter subject, represented as Flowable string variable subject |
Set while creating the process. |
Created on |
Process parameter startTime |
The time the follow-up (process) was created. |
Follow-up date |
Process variable expiryDateTime |
The due date that was entered while creating the follow-up. |
Status |
Derived from process parameters endTime and suspended |
Possible values for Status are running, completed and suspended. |
Starting a Process for an Object via a Plug-in Action
The object actions can be extended with a plug-in action that can be offered in the MORE ACTIONS action group. The following example shows the Two step process action, which starts a process based on the twosteptest_proc process model (mapped to Flowable processDefinitionKey) for a single marked object or for multiple selected objects.
As of 2021 Winter, the objects are displayed in the attachment task of the task details for a selected task in the Inbox.
To provide the example Two step process action in a client, import the client plug-in configuration file shown below. To be able to import a settings file, users need an administrative role.
The twosteptest_proc process model has to be deployed to the Flowable BPM Engine.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
"disabled": false,
"actions": [
{
"id": "yuv.custom.action.two.step.multi.label",
"label": "yuv.custom.action.two.step.multi.label",
"description": "yuv.custom.action.two.step.multi.description",
"priority": 0,
"icon": "<svg height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M0 0h24v24H0V0z\" fill=\"none\"></path> <path d=\"M4 10h12v2H4zM4 6h12v2H4zM4 14h8v2H4zM14 14v6l5-3z\"></path> </svg>",
"group": "further",
"range": "MULTI_SELECT",
"isExecutable": "(item) => item.id",
"run": "(selection) => this.http.post('/bpm/processes', {businessKey: selection[0].id, name: selection[0].title || selection[0].id, processDefinitionKey: 'twosteptest_proc', attachments: selection.map((s) => s.id), subject: selection[0].title, variables: [{ name: 'myVariable', type: 'string', value: 'Lorem ipsum' }]},'api-web').then(() => this.util.notifier.success(this.util.translate('yuv.custom.action.two.step.multi.success')))"
},
"yuv-download-action",
"yuv-delete-action",
"yuv-delete",
"yuv-upload",
"yuv-upload-action",
"yuv-move-action",
"yuv-move",
"yuv-follow-up-action",
"yuv-follow-up",
"yuv-reference-action",
"yuv-open-context-action",
"yuv-open-versions-action",
"yuv-clipboard-action",
"yuv-clipboard-link-action"
],
"translations": {
"en": {
"yuv.custom.action.two.step.multi.label": "Two step process",
"yuv.custom.action.two.step.multi.description": "Starts simple process with two steps, also for many objects",
"yuv.custom.action.two.step.multi.success": "Process has started"
},
"de": {
"yuv.custom.action.two.step.multi.label": "Zweischritteprozess",
"yuv.custom.action.two.step.multi.description": "Startet einen einfachen Prozess mit zwei Schritten, auch für mehrere Prozesse",
"yuv.custom.action.two.step.multi.success": "Prozess wurde gestartet"
}
}
}
Handling of Task Forms
As of version 2021 Winter, the Inbox view displays tasks in task forms that can be configured in order to provide a specific form for a specific Flowable task. The configuration can be done via following steps:
-
Display the task in the Flowable process modeler and write a technical name into the property FormKey.
-
Define your configuration in a JSON file as shown below.
-
Save this form using the configuration endpoint in the admin-controller or system-controller of the Web-API Gateway. Use the value of FormKey for the path parameter name of the configuration.
POST /api-web/api/admin/resources/config/{name}
or` POST /api-web/api/system/resources/config/{name}`
The client is calling this configuration file using the corresponding endpoint of the resource-controller of the Web-API Gateway.
Structure of the JSON Configuration File
The JSON format for task forms is the same as used for the object forms. Thus, the complete feature set is supported here as well. The expandable code block below shows an example configuration.
The Flowable variable names are specified as values for the key name. We recommend user task names with a prefix (in the example: 'xyz') for easier localization.
If the variable has not been used in the process before the form is called, the given values are saved to these variables after saving the form.
The property types used in forms for yuuvis® Momentum objects can be used for the Flowable variable types as well. Only the yuuvis® property type decimal is mapped to the Flowable variable type double, and the yuuvis® property type datetime is mapped to the Flowable variable type date.
The yuuvis® table properties are saved as in a variable of type JSON.
All other attributes given in this example are mostly self-explanatory.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
{
"name": "twosteptest_proc:1st_task",
"situation": "EDIT",
"script": "",
"elements": [
{
"name": "core",
"type": "o2mGroup",
"elements": [
{
"type": "o2mGroup",
"layout": {
"align": "row"
},
"elements": [
{
"type": "o2mGroup",
"name": "xyzSimplefields",
"layout": {
"align": "column"
},
"elements": [
{
"name": "xyzDatetime",
"type": "datetime",
"required": false,
"cardinality": "single",
"readonly": false
},
{
"name": "xyzDate",
"type": "datetime",
"required": false,
"cardinality": "single",
"readonly": false,
"resolution": "date"
},
{
"name": "xyzInteger",
"type": "integer",
"required": false,
"cardinality": "single",
"readonly": false },
{
"name": "xyzDecimal",
"type": "decimal",
"required": false,
"cardinality": "single",
"readonly": false
},
{
"name": "xyzString",
"type": "string",
"required": false,
"rows": 1,
"readonly": false },
{
"name": "xyzStringmultirow",
"type": "string",
"required": false,
"rows": 3,
"readonly": false
}
]
},
{
"type": "o2mGroup",
"name": "xyzComplexfields",
"layout": {
"align": "column"
},
"elements": [
{
"name": "xyzEmail",
"type": "string",
"cardinality": "single",
"readonly": false,
"classifications": ["email"]
},
{
"name": "xyzUrl",
"type": "string",
"required": false,
"readonly": false,
"classifications": ["url"]
},
{
"name": "xyzPhone",
"type": "string",
"required": false,
"readonly": false,
"classifications": ["phone"]
},
{
"name": "xyzUser",
"type": "string",
"required": false,
"cardinality": "single",
"readonly": false,
"classifications": ["id:organization"]
},
{
"name": "xyzReference",
"type": "string",
"required": false,
"cardinality": "single",
"readonly": false,
"classifications": ["id:reference[]"],
"label": "Reference"
},
{
"name": "xyzCatalogcustom",
"type": "string",
"required": false,
"cardinality": "single",
"readonly": false,
"classifications": ["custom:catalog[/api-web/api/dms/catalogs/tenMytenant:processstatus]"],
"label": "Catalog status"
},
{
"name": "xyzBroc:boolean",
"type": "boolean",
"required": false,
"readonly": false,
"label": "Boolean"
}
]
}
]
},
{
"name": "xyzTest_table",
"type": "table",
"required": false,
"readonly": false,
"label": "Notices",
"description": "List of notices",
"classifications": "sortable",
"elements": [
{
"name": "xyzColumn_string",
"type": "string",
"required": false,
"cardinality": "single",
"readonly": false,
"label": "String"
},
{
"name": "xyzColumn_date",
"type": "datetime",
"required": false,
"cardinality": "single",
"readonly": false,
"label": "Date"
},
{
"name": "xyzColumn_user",
"type": "string",
"required": false,
"cardinality": "single",
"classifications": ["id:organization"],
"readonly": false,
"label": "User"
},
{
"name": "xyzColumn_boolean",
"type": "boolean",
"required": false,
"cardinality": "single",
"readonly": false,
"label": "Boolean"
}
]
}
]
},
{
"name": "data",
"type": "o2mGroupStack",
"elements": [],
"layout": { "align": "column" },
"label": "Table group"
}
]
}
The key-value pair "classifications": ["sortable"] allows the user to sort the table rows manually by drag & drop. |
The following client-specific Flowable variables are available:
Task parameter (Web API Gateway GET tasks) | Example format | Flowable variable name | Example format |
---|
subject
- The client-specific task parameter subject is presented in the Subject column of the Inbox.
- Description
-
The parameter can be set using the Web-API Gateway GET/PUT endpoints for tasks or the corresponding BPM-API endpoints for setting the variable appClientsystem_subject.
- Example format
-
"subject": "My subject"
- Flowable Variable
-
appClientsystem_subject
- Flowable example format
-
{ "action": "save", "variables": [ { "name": "appClientsystem_subject", "type": "string", "value": "My subject" }
attachments
- Used for the tasks' Attachments aspect area of the Inbox.
- Description
-
The value is an array of object GUIDs. The title of the corresponding objects is displayed in the list of attachments for users.
The parameter can be set using the Web-API Gateway GET/PUT endpoints for tasks or the corresponding BPM-API endpoints for setting the variable appClientsystem_attachment.
- Example format
-
"attachments": ["GUID1","GUID2", "GUID2"]
- Flowable Variable
-
appClientsystem_attachments
- Flowable Example Format
-
{ "action": "save", "variables": [ { "name": "appClientsystem_attachments", "type": "json", "value": [ "GUID1", "GUID2" ] }
taskMessages
- Used to present necessary information for working on this particular task on the top of the Task aspect area in the Inbox.
- Description
-
The
level
parameter specifies the formatting of the corresponding messages. The following values are available:level description without level
The message is rendered in the normal format
info
The text is rendered in the accent color
error
Text is rendered in Red
warning
Text is rendered in Orange
If the message is a localization key, the key will be translated (see messageError in the example). The keys do not need an appended _label as required for the name for a form field.
'"Type": "ul" can be used to render messages with this setting in a list.
The value specified for taskMessages is retrieved by the GET tasks endpoint of the Web-API Gateway and can only be set by via the Flowable variable appClientsystem_taskMessages. Example format:: Example code for the GET task’s response of the Web-API Gateway:
+
"taskMessages": [
{
"message": "messageWithoutColor"
},
{
"level": "error",
"message": "messageError",
"type": "ul"
},
{
"level": "warning",
"message": "messageWarning",
"type": "ul"
},
{
"level": "info",
"message": "messageError"
},
{
"message": "Not translated message"
}
]
- Flowable Variable
-
appClientsystem_taskMessages
- Flowable Example format
-
Example code for setting the Flowable variable appClientsystem_taskMessages via BPM-API PUT tasks:
{ "action": "save", "variables": [ { "name": "appClientsystem_taskMessages", "type": "json", "value": [ { "message": "messageWithoutColor" }, { "level": "error", "message": "messageError", "type": "ul" }, { "level": "warning", "message": "messageWarning", "type": "ul" }, { "level": "info", "message": "messageError" }, { "message": "Not translated message" } ] } ] }
taskForm
- Used to specify user-relevant properties to be displayed in the task form.
- Description
-
Each property is specified by its name. The attributes of this property determine the style of the form field.
Form fields can be handled either by
-
listing the relevant properties in schemaProperties or
-
configuring a more complex form with form model syntax in a model.
If name does not have a representation in the schema, it will be ignored.
-
- Example format
-
Example code for the GET tasks response of the Web-API Gateway using schemaProperties:
"taskForm": { "schemaProperties": [ "tenMytenant:strsingle", "tenMytenant:datesingle" ]
Example code for the GET tasks response of the Web-API Gateway using a form model:
"taskForm": { "model": { "name": "twosteptest_proc:2nd_task", "situation": "EDIT", "script": "", "elements": [ { "name": "core", "type": "o2mGroup", "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "name": "twosteptest_proc:simplefields", "layout": { "align": "column" }, "elements": [ { "name": "twosteptest_proc:date", "labelkey": "Date", "type": "datetime", "required": false, "cardinality": "single", "readonly": false, "resolution": "date" }, { "name": "twosteptest_proc:string", "type": "string", "cardinality": "single", "required": false, "rows": 1, "readonly": false } ] } ] } ] } ] ]
- Flowable Variable
-
appClientsystem_taskForm
- Flowable Example format
-
Example code for setting the Flowable variable appClientsystem_taskForm via BPM-API PUT tasks using schemaProperties:
{ "action": "save", "variables": [ { "name": "appClientsystem_taskForm", "type": "json", "value": { "schemaProperties": [ "tenMytenant:strsingle", "tenMytenant:datesingle" ] } } ] }
Example code for saving the Flowable variable appClientsystem_taskForm via BPM-API PUT tasks using a form model:
{ "action": "save", "variables": [ { "name": "appClientsystem_taskForm", "type": "json", "value": { "model": { "name": "twosteptest_proc:2nd_task", "situation": "EDIT", "script": "", "elements": [ { "name": "core", "type": "o2mGroup", "elements": [ { "type": "o2mGroup", "layout": { "align": "row" }, "elements": [ { "type": "o2mGroup", "name": "twosteptest_proc:simplefields", "layout": { "align": "column" }, "elements": [ { "name": "twosteptest_proc:date", "labelkey": "Date", "type": "datetime", "required": false, "cardinality": "single", "readonly": false, "resolution": "date" }, { "name": "twosteptest_proc:string", "type": "string", "cardinality": "single", "required": false, "rows": 1, "readonly": false } ] } ] } ] } ] } } } ] }
The code clock below shows an example for the Flowable representation of a yuuvis table property. Tables are only shown up in a form where the types of the column properties are added as seen above.
{
"name": "twosteptest_proc:test_table",
"type": "json",
"value": [
{
"twosteptest_proc:column_string": "abc",
"twosteptest_proc:column_date": "2021-09-07T17:31Z",
"twosteptest_proc:column_user": "2685df3a-1cf8-4da3-968c-0a4a10b48921",
"twosteptest_proc:column_boolean": true
}
],
"scope": "global"
},
Start Forms for Starting Processes
As of version 2021 Winter, a plug-in action is available that allows to start a process via a start form as shown in the example screenshot. If all form fields are filled with valid values, the Start button is enabled. Both form fields User and Comment are required variables for starting a process. The code block below shows the corresponding plug-in configuration offering a start form with the name taskform in the object action view (displayed after a click on the object action Test process with role assignment).
{
"disabled": false,
"actions": [
{
"id": "yuv.custom.action.userGroupAssignment.multi.label",
"label": "yuv.custom.action.userGroupAssignment.multi.label",
"description": "yuv.custom.action.userGroupAssignment.multi.description",
"priority": 1,
"icon": "<svg height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M0 0h24v24H0V0z\" fill=\"none\"></path> <path d=\"M4 10h12v2H4zM4 6h12v2H4zM4 14h8v2H4zM14 14v6l5-3z\"></path> </svg>",
"group": "further",
"range": "MULTI_SELECT",
"isExecutable": "(item) => item.id",
"buttons": {
"finish": "yuv.custom.action.userGroupAssignment.multi.start"
},
"plugin": {
"component": "yuv-object-form",
"inputs": {
"__initOptions": "this.http.get(`/resources/config/taskform`, 'api-web').then((res) => {component.cmp.options = {formModel: res.data.tenant, disabled: false}})",
"__init": "() => parent.finished.subscribe((event) => { var selection = parent.selection; var cmp = component.cmp; this.http.post('/bpm/processes',{businessKey: selection[0].id,name: selection[0].title || selection[0].id,processDefinitionKey: 'userGroupAssignment',attachments: selection.map((s) => s.id),subject: selection[0].title,variables: [{ name: 'user', type: 'string', value: cmp.formData.user || '' },{ name: 'comment', type: 'string', value: cmp.formData.comment || '' },{ name: 'nextUserAssignee', type: 'string', value: 'fakeUserId' },{ name: 'nextGroupAssignee', type: 'string', value: 'YUUVIS_MANAGE_SETTINGS' }]},'api-web').then(() => this.util.notifier.success(this.util.translate('yuv.custom.action.userGroupAssignment.multi.success')))})"
},
"outputs": {
"statusChanged": "(status) => { parent.disabled = status.invalid; }"
}
}
},
"*"
],
"translations": {
"en": {
"yuv.custom.action.userGroupAssignment.multi.label": "Test process with role assignment",
"yuv.custom.action.userGroupAssignment.multi.description": "Starts a process with two tasks. Second task assigned to YUUVIS_MANAGE_SETTINGS",
"yuv.custom.action.userGroupAssignment.multi.success": "Process has started"
}
}
}
The following code block shows the form definition for the plug-in action example displayed above:
{
"description": "This form is used during process start and both task of process userGroupAssignment",
"name": "taskform",
"situation": "EDIT",
"elements": [
{
"name": "core",
"type": "o2mGroup",
"elements": [
{
"name": "user",
"labelkey": "userGroupAssignment:user",
"type": "string",
"cardinality": "single",
"required": true,
"readonly": false,
"classifications": ["id:organization"]
},
{
"name": "comment",
"labelkey": "userGroupAssignment:comment",
"type": "string",
"required": true,
"readonly": false,
"rows": 3
}
],
"layout": {
"align": "column"
}
},
{
"name": "data",
"label": "data",
"type": "o2mGroupStack",
"elements": []
}
]
}
As of version 2021 Winter, the value multi is supported as an alternative for the value single of the property cardinality in order to configure a multi-value field:
-
If the cardinality of a field is single, its type is mapped to the type of the Flowable variable with the same name.
-
If the cardinality of a field is multi, the Flowable variable type is set to JSON and its values are listed in the specified JSON structure.
Custom Confirm Actions
As of version 2022 Spring, it is possible to configure custom confirm actions for BPM tasks. These custom confirm actions trigger optional forms that give users the possibility to provide further data that is relevant only for this particular outcome. The so-called outcomes can be configured in static BPM form files as well as in dynamic ones:
{
"model":
{
...
},
"outcomes": [
{
"name": "taskflow_finish",
"variable": "status",
"value": "close"
},
{
"name": "taskflow_forward",
"secondary": true,
"variable": "status",
"value": "open",
"model": "taskflow-form-forward"
}
]
}
The outcomes list contains custom task confirm actions that will be displayed as buttons in the UI instead of the standard confirm button. The order of the buttons is from right to left. The buttons are displayed in the accent color per default. The outcomes section can be used in dynamic action forms as well.
Parameter | Description |
---|---|
name |
Technical name of the custom confirm action that is used as label for the button to be displayed in the client if not localized. |
variable |
The name of the Flowable variable for which the specified value is saved after the user has clicked the button. The variable can be used to control the process flow. |
value |
The value of the Flowable variable. |
secondary |
If false (default), the button is shown in the accent color. If true, the button is NOT shown in the accent color. |
model |
Specify the technical name of a defined BPM form or a complete valid form model. This form will only be shown if users click the corresponding custom confirm action. |
4.5.14. Office 365 Plug-in
The functionality provided by the OFFICE365 and DASHLET services is integrated via plug-in configuration in combination with the VIEWER Service in a library-based client. A general explanation of plug-in configurations is provided in a separate article and should be read carefully before addressing a specific use case like the integration of Office 365.
As soon as the plug-in configuration is applied, the VIEWER service provides an Office 365 preview for binary content files of Microsoft Office file types. If users have a write permission for the corresponding object, the object actions menu offers the Edit action that opens the binary content file in the edit mode in a new browser tab. Saving changes triggers the creation of a new object version.
In order to collaborate, multiple users can edit the same binary content file at the same time. The changes are saved after the last user has closed the session. Thus, only one update is applied to the binary content file.
The following information is intended to support administrators to configure the system for the Office 365 functionalities to be integrated in client applications based on our developer libraries.
Plug-in Configuration
The following plug-in configuration enables all functionalities of the Office 365 integration. It consists of an event listener (line 3), viewers (lines 4-30) and actions (lines 31-87) plug-ins. Before applying the plug-in configuration, replace <host> by your domain (line 28) and adjust the permissions according to your roles (e.g., replace the YUUVIS_DEFAULT role by a suitable custom role).
The event listener (line 3) triggers a refresh of the running client application after an update of the plug-in configuration.
In the viewers plug-in configuration section, the binary content file types are listed (lines 16-26) for which the VIEWER service should provide the preview via a specified dashlet.
In the actions plug-in configuration section, two actions are defined:
-
Editing of an existing Microsoft Office content file and storing the modified file as a new version (lines 32-42).
-
Opening a new Microsoft Office file, editing it and replacing the previous content file by the new one (lines 43-86). The following sub actions are specified for the Microsoft Office file types for which file creation is offered:
-
Microsoft Word file (lines 55-63)
-
Microsoft Excel file (lines 66-74)
-
Microsoft PowerPoint file (lines 77-85)
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
{
"disabled": false,
"load": "() => window.addEventListener('message', (e) => { console.log(e); if(!e || !e.data || !e.data.match || !e.data.match('MessageId')) return; var data = JSON.parse(e.data); data && (data.MessageId === 'Host_PostmessageObjectUpdating' || data.MessageId === 'Host_PostmessageObjectConverted') && setTimeout(() => {var btn = api.util.$('.yuv-object-details .refresh-button'); btn && btn.click()}, 3500)})",
"viewers": [
{
"mimeType": [
"application/octet-stream"
],
"fileExtension": [
"nes"
],
"viewer": "externals/x-nes?path=${path}#locale=${lang}&direction=${direction}&theme=${theme}&accentColor=${accentColor}"
},
{
"mimeType": [
"application/msword",
"application/vnd.ms-excel",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.openxmlformats-officedocument.wordprocessingml.template",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.openxmlformats-officedocument.spreadsheetml.template",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"application/vnd.openxmlformats-officedocument.presentationml.template",
"application/vnd.openxmlformats-officedocument.presentationml.slideshow"
],
"viewer": "() => {parameters.path = parameters.path.replace('http://localhost:4400','https://<host>'); var edit = api.session.user.hasRole('YUUVIS_DEFAULT') && !location.pathname.match('/versions/'); return '/dashlet365/?id=${id}' + (edit ? '' : '_' + dmsObject.version) + '&version=${version}&mimeType=${mimeType}&path=${path}&fileExtension=${fileExtension}&locale=${lang}&allowedExtensions=doc,docx,xls,xlsx,ppt,pptx&editMode=' + edit + '&displayName=' + api.session.user.get().firstname;}"
}
],
"actions": [
{
"id": "yuv.custom.action.office.edit.label",
"label": "yuv.custom.action.office.edit.label",
"description": "yuv.custom.action.office.edit.description",
"priority": 0,
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z\"/></svg>",
"group": "further",
"range": "SINGLE_SELECT",
"isExecutable": "(item) => item.id && api.session.user.hasRole('YUUVIS_DEFAULT') && !location.pathname.match('/versions/') && api.content.viewer() && api.content.viewer().location.pathname === '/dashlet365/'",
"run": "(selection) => api.content.viewer().postMessage(JSON.stringify({MessageId:'UI_Edit'}))"
},
{
"id": "yuv.custom.action.office.new.label",
"label": "yuv.custom.action.office.new.label",
"description": "yuv.custom.action.office.new.description",
"priority": 0,
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\"/></svg>",
"group": "further",
"range": "SINGLE_SELECT",
"isExecutable": "(item) => item.id && api.session.user.hasRole('YUUVIS_DEFAULT') && !location.pathname.match('/versions/')",
"header": "yuv.custom.action.office.new.label",
"subActionComponents": [
{
"id": "yuv.custom.action.office.word.label",
"label": "yuv.custom.action.office.word.label",
"description": "yuv.custom.action.office.word.description",
"priority": 0,
"icon": "<svg width=\"512px\" height=\"512px\" viewBox=\"-64 0 512 512\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm220.1-208c-5.7 0-10.6 4-11.7 9.5-20.6 97.7-20.4 95.4-21 103.5-.2-1.2-.4-2.6-.7-4.3-.8-5.1.3.2-23.6-99.5-1.3-5.4-6.1-9.2-11.7-9.2h-13.3c-5.5 0-10.3 3.8-11.7 9.1-24.4 99-24 96.2-24.8 103.7-.1-1.1-.2-2.5-.5-4.2-.7-5.2-14.1-73.3-19.1-99-1.1-5.6-6-9.7-11.8-9.7h-16.8c-7.8 0-13.5 7.3-11.7 14.8 8 32.6 26.7 109.5 33.2 136 1.3 5.4 6.1 9.1 11.7 9.1h25.2c5.5 0 10.3-3.7 11.6-9.1l17.9-71.4c1.5-6.2 2.5-12 3-17.3l2.9 17.3c.1.4 12.6 50.5 17.9 71.4 1.3 5.3 6.1 9.1 11.6 9.1h24.7c5.5 0 10.3-3.7 11.6-9.1 20.8-81.9 30.2-119 34.5-136 1.9-7.6-3.8-14.9-11.6-14.9h-15.8z\"/></svg>",
"group": "common",
"range": "SINGLE_SELECT",
"isExecutable": "(item) => item.id",
"run": "(selection) => { var item = selection[0]; var user = api.session.user.get(); var uri = '/dashlet365/?id=' + item.id + '&version=' + item.version + '&fileExtension=docx&locale=' + user.userSettings.locale + '&editMode=true&displayName=' + encodeURIComponent(user.firstname) + '&action=editnew&mimeTypeGroup=WORD&conversion=none'; var w = window.open(uri); w.addEventListener('beforeunload', () => window.postMessage(JSON.stringify({MessageId:'Host_PostmessageObjectUpdating', Values: {osid: item.id}}))); }"
},
{
"id": "yuv.custom.action.office.excel.label",
"label": "yuv.custom.action.office.excel.label",
"description": "yuv.custom.action.office.excel.description",
"priority": 0,
"icon": "<svg width=\"512px\" height=\"512px\" viewBox=\"-64 0 512 512\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm212-240h-28.8c-4.4 0-8.4 2.4-10.5 6.3-18 33.1-22.2 42.4-28.6 57.7-13.9-29.1-6.9-17.3-28.6-57.7-2.1-3.9-6.2-6.3-10.6-6.3H124c-9.3 0-15 10-10.4 18l46.3 78-46.3 78c-4.7 8 1.1 18 10.4 18h28.9c4.4 0 8.4-2.4 10.5-6.3 21.7-40 23-45 28.6-57.7 14.9 30.2 5.9 15.9 28.6 57.7 2.1 3.9 6.2 6.3 10.6 6.3H260c9.3 0 15-10 10.4-18L224 320c.7-1.1 30.3-50.5 46.3-78 4.7-8-1.1-18-10.3-18z\"/></svg>",
"group": "common",
"range": "SINGLE_SELECT",
"isExecutable": "(item) => item.id",
"run": "(selection) => { var item = selection[0]; var user = api.session.user.get(); var uri = '/dashlet365/?id=' + item.id + '&version=' + item.version + '&fileExtension=xlsx&locale=' + user.userSettings.locale + '&editMode=true&displayName=' + encodeURIComponent(user.firstname) + '&action=editnew&mimeTypeGroup=EXCEL&conversion=none'; var w = window.open(uri); w.addEventListener('beforeunload', () => window.postMessage(JSON.stringify({MessageId:'Host_PostmessageObjectUpdating', Values: {osid: item.id}}))); }"
},
{
"id": "yuv.custom.action.office.powerpoint.label",
"label": "yuv.custom.action.office.powerpoint.label",
"description": "yuv.custom.action.office.powerpoint.description",
"priority": 0,
"icon": "<svg width=\"512px\" height=\"512px\" viewBox=\"-64 0 512 512\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm72-60V236c0-6.6 5.4-12 12-12h69.2c36.7 0 62.8 27 62.8 66.3 0 74.3-68.7 66.5-95.5 66.5V404c0 6.6-5.4 12-12 12H132c-6.6 0-12-5.4-12-12zm48.5-87.4h23c7.9 0 13.9-2.4 18.1-7.2 8.5-9.8 8.4-28.5.1-37.8-4.1-4.6-9.9-7-17.4-7h-23.9v52z\"/></svg>",
"group": "common",
"range": "SINGLE_SELECT",
"isExecutable": "(item) => item.id",
"run": "(selection) => { var item = selection[0]; var user = api.session.user.get(); var uri = '/dashlet365/?id=' + item.id + '&version=' + item.version + '&fileExtension=pptx&locale=' + user.userSettings.locale + '&editMode=true&displayName=' + encodeURIComponent(user.firstname) + '&action=editnew&mimeTypeGroup=POWERPOINT&conversion=none'; var w = window.open(uri); w.addEventListener('beforeunload', () => window.postMessage(JSON.stringify({MessageId:'Host_PostmessageObjectUpdating', Values: {osid: item.id}}))); }"
}
]
}
}
4.5.15. AI Plug-in
The Artificial Intelligence Platform is a set of APIs and tools that enable customers to set up and use AI functionalities by themselves, with low costs and high performance. Customers can export their own documents, train models using different algorithms provided by OPTIMAL SYSTEMS GmbH, evaluate trained models, and deploy them to make predictions. Every part of the AI Platform can be deployed on-premises or in the cloud.
The following information is intended to support administrators to configure the system for the AI functionalities to be integrated in client applications based on our developer libraries.
Classification in Object Type Definitions
The object types to be considered for analysis and predictions via the AI services have to be classified with the classification attribute:
<classification>prediction:classify</classification>
Set this attribute for all desired object types in their schema definition.
Inference Schema
The inference schema is a JSON configuration file defining the object types that will be available for the classification as well as the properties for which the metadata extraction should be done.
In order to use the Artificial Intelligence Platform with a client application based on our client libraries (e.g., yuuvis® client as reference implementation), objectTypeId
has to be defined as a concatenation of app name and SOTs separated by pipes as can be seen in the example provided here.
4.6. Reference Client
yuuvis® Momentum client as reference implementation is an Angular application comprising multiple components. Each of these components implements a specific area of the client application using the functionality provided by the developer libraries.
In the header area, you will find the yuuvis® Momentum bar with icons for the most frequently used features.
Main menu |
|
If you left-click the yuuvis® icon while pressing Ctrl, a new tab will open with another dashboard in your browser. If you left-click the yuuvis® icon in the hit list, folder, or object view, the dashboard will appear again. |
|
Create object |
|
Search (not displayed in the Dashboard view) |
|
Settings menu |
4.6.1. Dashboard
In the middle of the dashboard, you will find the multi-part search input field.
In the footer area, the objects that you recently created or edited are displayed in the form of a tile row. Click the Recently created or Recently edited buttons below the tile row to select which objects you want to view. If you click the More… button to the right of the objects listed in the footer area, the listed objects are displayed in a hit list.
4.6.2. Navigation by Keyboard
To make all functions and actions in yuuvis® Momentum client as reference application easily accessible, most of the commands can be called without using a mouse. To navigate through the application by keyboard, open the Quick access command palette at any time by pressing the Ctrl key twice. Then, start typing a string to find the command you are looking for.
Examples:
-
'navigate'
shows a list of all application views. Select an item from the list to open the respective view. -
'create'
shows a list of possible create commands. One for each object type. Select an item from the list to create an object of the respective type. To find a specific create command, enter the name of the object type into the search field (e.g.,si
results in Create: Sick note, Create: Document (classified), etc.). -
A full-text search of all DMS objects can be requested with
?<key word>
.
4.6.3. Menus
Main Menu
You can access the main menu using the Main menu icon on the yuuvis® Momentum bar. You can access the following areas via the main menu:
-
Dashboard
-
Create object
-
In-tray
-
Inbox
-
My follow-ups
-
My processes
-
Retention management (as of 2022 Summer, only for users with specific authorization)
-
Settings
-
About
Object Actions Menu
Various actions are available for editing documents and folders via this menu, depending on the context and your permissions. It is available in different areas, such as in hit lists, in the folder view, and in the object view, via the Object actions icon.
The suggested actions and processes always refer to the selected object(s). If you select several objects in an object list (such as a hit list) and then click the Object actions icon in the object list area, you can apply an action or a process to several objects.
Add as new version Adds a document file to the selected object in a hit list or in a folder view. Adding a document file automatically creates a new document version. |
|
Copy to clipboard Copies links from one or more selected objects to your operating system’s clipboard. |
|
Delete Deletes the selected object. Deleted items cannot be restored. |
|
Download document file Downloads the document file of one or more selected objects to the local file system in the original format. |
|
Manage follow-up Creates follow-ups for a selected object or opens the dialog for modifying, deleting or confirming follow-ups. |
|
Move Changes the parent folder of an object. It is also possible to remove the current parent folder so that the object will no longer have any parent objects. |
|
|
As of 2022 Summer. Only for users with specific authorization. Set retention time Set an expiration date.
Available for objects of document object types referencing the Extend retention time Replace the expiration date by a later date.
Available for objects of document object types referencing the |
Open in the folder/Open Opens the selected object’s parent folder view. The object view will be opened for document files without a parent folder. |
|
|
Show references Displays an overview of the objects that reference the selected object. |
Show versions Opens an overview of all versions of the selected object. You can select two versions in the version list to compare them side by side. The action is not offered if the selected object only has one version (see Object Versions). Set as current version This action is available when a Version view is displayed. |
In an additional section MORE ACTIONS, plug-in actions can be available if configured by an administrator.
Settings Menu
Configure the main settings of your yuuvis® Momentum client. Open the settings menu by clicking the Settings menu icon in the yuuvis® Momentum bar and select Settings from the dropdown menu. Alternatively, you can also open the settings menu via the Main menu.
The following information and configuration settings are available in the settings menu:
-
Language
You can use the English and German buttons to control the language display of the general user interface elements and the object types, menus, fields, and catalogs specifically configured for your company.
-
Permissions
The Roles dropdown menu displays the roles that are assigned to the currently logged in user.
-
Layout
Customize the design of the client layout to your personal preference. * *Theme, Accent color and Dashboard background image
+ Choose between a light/dark/high contrast design, set an accent color, and upload a background image. This setting is stored on your device, meaning you can work on different devices with different layouts.
-
Dashboard type (as of 2022 Winter)
Choose between the default dashboard layout and a customizable dashboard layout.
-
Export, Import and Reset
You can also export the layout settings for use in other clients by clicking the Export button. Similarly, you can transfer the layout settings from other clients to yours by clicking the Import button. Click the Reset button to delete all of your individual layout settings.
-
-
Configuration
Edit Hit lists, Search filters and Cache.
4.6.4. Hit List Configuration Menu
You can modify the hit lists' appearance and save it. You can configure a hit list for each individual object type as well as for mixed hit lists (hit lists with more than one object type). Run a search request for an object type and open the Configuration menu in the hit list if you want to configure the appearance of the hit list for this object type. Follow the same steps to configure mixed hit lists.
You can adjust the following in the configuration menu:
-
the columns that are shown/hidden in a hit list,
-
the order in which columns are displayed, and
-
the columns that are to be pinned or sorted.
Click Save to save the changes, or Cancel to discard them. Click Reset to default to restore the original configuration.
The saved hit list configuration is applied to each new hit list of the configured object type.
Filter Configuration Menu
This menu provides a graphical interface to configure your filters. It is accessible via the filter panel in the hit list view or via the Settings menu. All users can configure user-defined filters that are only available to themselves.
Users with the YUUVIS_MANAGE_SETTINGS role can additionally configure default filters that are available to all users across the entire system (via the Settings menu).
The configuration menu consists of the following areas:
-
Header area
-
The header area displays the object types for which you configure a filter.
-
You can configure cross-context filters or filters limited to one object type.
-
-
Filter list
-
The filter list shows you the available default filters and the filters you have configured.
-
Custom-configured filters are highlighted in bold in the list.
-
The filter list is divided into the areas Custom filters, Activated filters, and Deactivated filters.
-
-
Configuration area
-
The configuration area displays the configuration of the filter you have selected in the filter list.
-
This is where you can also configure your own filters.
-
You can create the following types of filters:
-
Object-specific filters
-
Only valid for a specific object type.
-
Only the filter fields of the corresponding object type are available in addition to the basic data filter fields.
-
-
Cross-context filters
-
Applicable to several or all object types.
-
Different filter fields will appear depending on which object types are contained in the object list in which you open the filter configuration menu.
-
To organize filter display in the filter panel, you can activate and deactivate the default and saved filters. Deactivated filters will then no longer be displayed in the filter panel. These settings apply to the filter panels of all object lists.
You can also delete filters you have created and saved. Default filters cannot be deleted.
Catalog Edit Menu
Catalogs are used to offer a selection list of predefined values for metadata fields in an object’s Metadata aspect area.
You require the YUUVIS_MANAGE_SETTINGS role to be able to edit catalogs in the client. To edit a catalog click the Pencil icon (if available). The catalog edit menu opens in which the following features are available:
Add entry |
You can create new catalog entries using the entry field in the header area of the edit menu. |
|
Delete a catalog entry by clicking the Remove icon. If you delete a catalog entry in the catalog edit menu, the catalog values can then not be deleted in metadata forms. Catalog values orphaned by deletion are marked red in the metadata form and by a red Remove icon. |
/ |
This checkbox allows you to control whether a catalog entry is displayed in the metadata form or not. |
|
If you click this icon, you can drag and drop the line of the catalog entry to where you want it to be in the list of catalog entries. |
4.6.5. Object Aspects
Objects contain various information that are displayed in units called object aspects. They are summarized in a form with a header area and multiple tabs containing the individual object aspects.
The header area contains a title and description (if available) and the following icons:
… |
Visualizes the object type. |
|
Refresh the object aspects. |
|
Object actions menu. |
The layout of the object areas can be customized. If you have changed the number and the width of the aspect areas, these changes will be saved automatically when you switch views.
|
Split aspect. The view splits and several aspect areas are displayed next to each other. You can use the separator bar between the aspect areas to adjust the size of the displayed areas. |
Undock |
Only available for the Content aspect. Open the content preview in a separate browser window. |
|
The aspect area will revert back to normal. The following object aspects are available. |
Summary Aspect Area
Displays the object properties (basic metadata, type metadata and tags) of an object, such as name, editor, number of versions, file size, etc. The information is divided into the areas Basic metadata, Type metadata, and Advanced information.
If more than one version of a document exists, you can also click the highlighted version number to access the version view.
Metadata Aspect Area
The Metadata aspect area offers the option of editing the type metadata of the selected object, provided that you have the appropriate rights.
History Aspect Area
The History aspect area provides a view of the creation process as well as the editing and usage history of an object. It contains a chronological list of who made which changes to the content or type metadata of an object and when. The output (download and read) of an object is also logged in this aspect area. You can filter the events of the editing history, if needed. The entries in the history also contain links to the versions of the document. You can open the version view by clicking one of these links.
The entries in the history can be filtered by
-
limiting the date to a time period using the operators (>, <, =, -), or
-
specifying a type of action by ticking the corresponding checkboxes. Clicking a group name will select all history entries of this group.
For users to be able to see READ events in the object history, i.e., whether an object was only viewed, they must be assigned the YUUVIS_MANAGE_SETTINGS role.
Content Aspect Area
The Content aspect area offers a content preview of the selected object. Different content previews are used depending on the file type of the document file, based on the VIEWER service or PDF rendition as described in Preview of Binary Content Files.
4.6.6. The Version View
If type metadata is modified or the content file is edited, replaced, moved, or deleted, then new versions of the object are created. The older versions are retained. All versions of an object can be managed in the version view.
There are a number of ways to open the version view:
-
Via the object actions menu, if the selected document has more than one version
-
In the object area via the link on the version number in the Summary aspect area.
-
Via the links on the version numbers in the History aspect area.
The version view shows a list of all versions. Select a version to display its version-specific object information in the object aspect area as described above. If two versions are selected in the list, you can compare them in the tabs Changes to metadata and Changes to content where you have a number of actions available for a visual comparison.
If the content preview is provided as a PDF rendition, it is only available for the current version. |
The slider in the center helps you find the differences. If you move your mouse over the slider, a dropdown menu will offer you more comparison options.
|
Drag the slider left and right to resize the images. |
|
Displays both images instantly. |
| |
Layers both images on top of each other so that you can use the sliders to display one image and then the other. |
|
Only displayed when both images are superimposed. Clicking the icon reverts the view back to normal. |
An older version can be set as the current version. To do this, select the desired version and select Set as current version from the object actions menu. The version view is automatically refreshed by this action.
4.6.7. Creating Objects
You require the YUUVIS_CREATE_OBJECT role to be able to create objects.
You can create objects (folders and documents) in stages. This procedure is especially useful if you create a lot of objects in a short period of time that you do not want to complete until later.
Creating Documents
The following options are available for you to create documents:
-
via the yuuvis® Momentum bar
-
via the Main menu
-
via drag and drop
The following information is relevant for any document creation.
Parent Folders:
If you want to create a document, the first thing you have to decide is if you want to define a folder as parent object. For this purpose, you first need to display the folder object you want to specify as parent for your new document. Once you have opened the right folder, you can create one or more documents as child objects in the folder via the yuuvis® Momentum bar or by drag and drop.
The new document will not have a parent object
-
if you did not open a folder before creation, for example, if you are on the dashboard, in hit lists, in a document’s object view, or
-
if you created it via the Main menu.
Document Object Types:
You can find out which document object types are available for you in the object creation dialog. One of the basic properties of all document types is that they may or may not contain a binary content file.
A distinction is also made between the following object types, particularly with regard to the creation process:
-
Simple object types
-
Simple object types are the fastest way to create documents.
-
The object type is assigned when the object type is selected.
-
The main difference to other object types is that you do not get a preview of the uploaded file during the creation process.
-
-
Variable object type with fixed object type assignment
-
This object type offers you a preview of the uploaded file during the creation process.
-
This gives you the chance to double-check that the object type you selected matches your file.
-
-
Variable object type with subsequent object type assignment
-
For this object type, you can assign the object type after the creation process.
-
In the first step of the creation process, only a small amount of general type metadata is entered and the document is created.
-
You can assign the final object type at a later point, depending on the configuration of the variable object type.
-
Artificial intelligence can be used to create documents with variable object types regardless of how your yuuvis® Momentum system and individual object types are configured. The AI helps you to automatically classify your documents by showing you a suggestion list during object type assignment. This list contains a weighting based on machine learning.
Upload Status:
If you upload files, you can check their upload status in the yuuvis® Momentum bar. Click the Upload status icon to view the names and statuses of the files uploaded in a menu. A green tick behind an entry indicates that the upload process was successful. Click the Remove icon to remove entries from the list to get a better overview. The Upload status icon will no longer be displayed once all of the entries have been removed from the list.
Cancelling the Creation Process:
There are several ways to cancel the creation process:
-
Click Cancel during the creation process. In the form that opens you can:
-
delete the object (Remove object button). The incomplete object is permanently deleted. The files uploaded and/or type metadata entered up to that point will be lost.
-
place the file in the in-tray (File in in-tray button). The incomplete object, including all type metadata entered and/or all files uploaded up to this point, is placed in the in-tray. You can continue and complete the creation process at a later time.
-
-
Click the yuuvis® logo in the yuuvis® Momentum bar, which is part of the main menu, or an entry in the Settings menu during the creation process. Click OK in the form that opens to permanently delete the incomplete object. The files uploaded and/or type metadata entered up to that point will be lost.
Filing E-mails and Attachments:
There are many ways and options available to file e-mails and e-mail attachments. You can file e-mails together with their attachments or file the e-mails and attachments separately. You can upload e-mails from the local file system or drag and drop them.
You will need to keep a few things in mind when filing e-mails directly from an e-mail program via drag and drop. Whether or not it is possible to drag and drop e-mails from an e-mail program directly into the client depends on the e-mail program and the browser you are using. For example, the drag-and-drop filing of e-mails from Microsoft Outlook is supported if the client is running in a Google Chrome browser. In this case, the e-mail is filed in yuuvis® Momentum in the same file format (*.msg) in which it is transferred from Microsoft Outlook. Filing an e-mail in the MSG file format has one distinct disadvantage in that the content preview will differ slightly from the filed e-mail.
If you are working with a different browser, Firefox for example, and would like to file e-mails via drag and drop, then it is best to use the Outlook Add-In for Drag & Drop from OPTIMAL SYSTEMS. It enables drag-and-drop filing, ensuring that e-mails that are dropped onto the client are transferred as EML files so that the content preview generates a more accurate view of the filed e-mail. If you are interested in this add-in, please contact your partner at OPTIMAL SYSTEMS.
Save e-mail attachments in the local file system before uploading them to yuuvis® Momentum. The next steps required to file e-mail attachments from the local file system are similar to those used to create documents in the client. The use of drag and drop to file attachments stored in the local file system is also supported.
Creating Folders
Folders can be created via the yuuvis® Momentum bar as well as via the Main menu. You cannot create a folder inside another folder.
You cannot change a folder’s type after it has been created. If you want to change the folder type during creation, you can return to the object type selection by clicking in the breadcrumb trail in the header area of the form.
If you want to cancel the creation process and leave the form, click an icon on the yuuvis® Momentum bar.
4.6.8. Editing Objects
You require the YUUVIS_CREATE_OBJECT role to be able to edit objects.
4.6.9. In-tray – Assigning Final Object Types
The functionality is based on floating secondary object types. You can assign those object types to incomplete objects after the creation process.
In the first step of the creation process, only a small amount of general type metadata is entered and the object is created. You can assign the final object type at a later point, depending on the configuration of the secondary object type.
All incomplete objects are listed in the Main menu in the in-tray. If you want an object to be displayed in the in-tray, assign the appclient:dlm:prepare
tag with value 0. Replace the value with 1 as soon as you are finished with the desired manual adjustments for the object. As the tag is specified in some object type definitions in the client’s schema, it can be set via metadata form.
If you select an object in the list of incomplete objects in the in-tray, its object aspects will be displayed. You can see which additional options are available for the selected object by the buttons displayed in the Metadata aspect area:
-
Assign object type button: You can assign a final object type to the object.
-
Extend button: You can extend and reduce the type metadata of the object.
If the Assign object type button is displayed in the Metadata aspect area, then you can assign an object type to the object. You can only assign an object type to an object once and this cannot be changed. After you have assigned an object type to an incomplete object, the Assign object type button will no longer be displayed and the object will be removed from the list of incomplete objects.
Adding or Replacing Binary Content Files
You can replace binary content files assigned to document objects with a new file, for example if a copy of the file was modified outside of yuuvis® Momentum and you would like to overwrite the file in yuuvis® Momentum with the new version. To do this, you have to upload the new file from your local file system to yuuvis® Momentum and add it to the document object as a new version.
The following options are available for you to add document files:
-
Use the Add as new version function in the object actions menu.
-
Drag and drop.
If you want to add the binary content file of another object, then you will need to first download this file to your local file system using the object actions menu before you can add it to another object as a binary content file.
Editing Metadata
Entries for type metadata are made and maintained via fields in metadata forms. You can enter type metadata both during and after object creation in the Metadata aspect area. For variable object types, you can also extend or reduce the metadata at any time. When an object is created, the object type is determined and the metadata form is filled out.
For documents, the Metadata aspect is displayed in hit lists and folder views (if a folder is specified as parent object), for example, if you have selected the corresponding document.
For folders, you can also display the Metadata aspect area in hit lists if you have selected the corresponding folder. In the folder view, you must click the folder name in the header of the structure area to display the Metadata aspect area.
Metadata Form Fields:
The form fields are configured by the administrator. Notices are shown if entries in fields and references between fields do not match these specifications.
Only integers from -231 to 231-1 (i.e., from -2,147,483,648 to 2,147,483,647) may be entered in the metadata form. Entries that fall outside this range will cause rounding or other errors.
Catalog fields |
Catalog entry. Selection from a suggestion list after one character has been entered or via the catalog. For hierarchical catalogs with entries in layers, the administrator configures whether the entries for all layers are accepted or only the entry for the lowest layer. Free inputs are not accepted. If a Pencil icon is displayed, you can open the catalog item in the catalog edit menu. Catalog values marked in red are catalog values that can no longer be assigned to a catalog entry due to adjustments made to the catalog. Click on the red Remove icon to delete them. |
Checkboxes |
Checkboxes either have the status 'active' or 'not active'. On an administrative level, the additional status 'neutral' can also be integrated. |
Switches |
Alternative visualization of checkboxes with an intuitive representation of the 'neutral' value, i. e., = = = |
Date fields |
Date. Free input or via the Calendar icon. The format of the date varies based on the user’s language settings. If you click in a date field, the date format to be entered will be displayed. German: DD.MM.YYYY English: MM/DD/YYYY |
E-mail fields |
E-mail addresses must be entered in full and contain the @ character. Placeholders and so on are not supported. E-mail addresses are not case sensitive. To enter multiple e-mail addresses, press Enter to confirm your entry. Sample entry: employee@optimal-systems.de. Click the E-mail icon to create an e-mail with this address in the local e-mail application. |
ID fields |
User or group. Selection from a suggestion list after two characters have been entered. Free inputs are not accepted. |
Mandatory fields |
Mandatory fields must be completed. They are indicated by an asterisk. |
Numerical fields |
Digits. The maximum number of digits and decimal places is defined. |
Tables |
Entry via a dialog. New rows are added at the bottom. Double-clicking a row opens the dialog for editing or deleting the row. The content of metadata tables can be exported as a *.csv file. |
Telephone fields |
To enter multiple telephone numbers, press Enter to confirm your entry. |
URL fields |
Addresses in URL fields must begin with the protocol information, e.g., http://, https://. Web addresses must be entered in full. Placeholders and so on are not supported. Web addresses are not case sensitive. To enter multiple web addresses, press Enter to confirm your entry. Sample entry: http://www.optimal-systems.de. The URL can be opened in the browser by clicking the www icon. |
Tables in Metadata Forms:
The following customization options and functions are available for tables in metadata forms:
-
Sort by column: If you click the header of a column, the table will be sorted by the contents of the column. Clicking the header again undoes the sorting. Tables in metadata forms can only be sorted by the content of a column.
-
Optimal column width: If you click the right column separator of a column, the column will be adjusted to the optimal width.
-
Edit table row: The table is opened in a new form with an input area in full view to make editing easier. The row you have clicked is also highlighted in the opened form. The values of this row are already entered in the form for editing or for adding a new row.
-
Align table columns: All columns in the table will be adjusted to the optimal width.
-
Open table: The table is opened in a new form in full view to make editing easier. If you select a row in the opened form, the input area for editing the row is also displayed.
-
Export spreadsheet data to CSV file: The table will be exported in CSV file format.
-
Text fields are in output in quotation marks (e.g., "abc").
-
Date and time fields are output in ISO format 8601.
-
Decimal numbers are formatted in the language the user has specified.
-
Values from reference fields are output as object IDs.
-
Values from users are output as user IDs.
-
Boolean values are output as FALSE and TRUE or empty/NULL.
-
-
Insert new row: The table is opened in a new form with an input area in full view to make editing easier.
Prepopulated Metadata Fields:
Certain fields in metadata forms may already be prepopulated when objects are created. The administrator defines which fields are prepopulated. These fields are specifically indicated in the metadata forms when objects are created. Manually entered data has priority, i.e., it overwrites automatically imported data in case of conflict. There is a distinction made between two types of prepopulated metadata fields:
-
Object type-specific prepopulated data
Metadata fields that are yielded by the object type’s configuration can be prepopulated depending on the object type. This can be prepopulated data from free text inputs, catalogs, scripts, or additional components. Metadata fields that are prepopulated by the object type definition are indicated by a df during the creation process.
-
Extracted prepopulated data
Specific pieces of data from the metadata of the files (such as title, creation date, author, etc.) can be automatically extracted and written to the metadata, depending on the configuration of your yuuvis® Momentum system, when uploading files. Object type-specific prepopulated data will be overwritten during this process. Metadata fields that extract data from the metadata of uploaded files are indicated by an ex during the creation process.
Object-specific and extracted prepopulated data is transferred as follows:
-
If both a default value and an extraction are defined for a field, then the data for the extraction (if available) is transferred during the creation of an object in yuuvis® Momentum client; otherwise the default value is transferred to the metadata form.
-
No extracted data will be shown in the metadata fields indicated as such for files to be filed as a batch. If you enter information in these fields, it will overwrite all extracted data. If you do not enter anything in these fields, all of the extracted data (if available) will be transferred; if not available, the default value will be transferred to the metadata form.
-
If the document file is later replaced, the extraction will be repeated. Existing data in fields configured for a mapping will be replaced or – if no new value is found – removed.
References:
In metadata forms, the metadata of another object can be transferred into certain fields, which are known as reference fields. These fields reference the ID of certain objects and therefore are retained even if the referenced object is renamed or moved. The administrator configures reference fields, and they are set up as multi-fields to hold several values.
References that have been set up are displayed both in hit lists and in the Summary and Metadata aspect areas. They are indicated in hit lists and in the aspect areas with a Reference icon. Click the icon to quickly open the referenced object(s). If you hold down the Ctrl key while clicking, the location of the referenced object will be displayed in a new tab.
You can create and remove references in the Metadata aspect area.
If a referencing object is located in a folder, you can jump to the filing location of the referenced object by double-clicking the list entry. If the object clicked is located in the main directory, the object view of the referencing object will open.
If a user does not have any rights to a referencing object, it will not be displayed for this user. If a user has read access to a referencing object, but not to the folder in which the object was filed, then the user is only offered the object view for the object.
4.6.10. Searching
You can start search requests on any page. The search dialog is available for this purpose on the dashboard and in the yuuvis® Momentum bar. The following options are available and can also be combined:
|
A drop-down menu to the left of the search input field to limit your search to selected object types. |
Search term |
Full-text search for terms that you think might occur in the objects you are looking for. Searches the contents of document files as well as the string fields within metadata of objects. Note that number and date fields are not taken into account in the full-text search. |
|
Define search conditions. Search for specific properties of objects, such as
Select the property and specify the value by which you want to filter. For properties with resolved user IDs as values, a preview of available users is displayed after typing the first letters. To display all users, type **. The Filter panel in the Hit list view uses predefined filters. In addition, filter criteria can also be changed in the search field in the yuuvis® Momentum bar. These settings are not saved and are only available for the current session. |
|
Run the search request. |
The search combines all search terms and all limitations on object properties and object types with AND by default. Object types are combined in the search with OR. In the search dialog, you can change the logical operator of multiple search terms or criteria to OR and/or create nested searches.
4.6.11. Hit List View
The results of a search are displayed in a hit list of all objects that were found. The hit list view is divided into the areas described below. You can sort, filter, and configure the hit list. Search results are sorted lexicographically. This means that sorting is case-sensitive and special characters are accounted for. Depending on the configuration, the hit list will contain several columns with basic metadata, type metadata, tags, such as type, title, description, editor, etc. The view of a hit list always corresponds to the hit list configuration of the selected object type.
Header Area
|
Export the hit list with the displayed columns as CSV file. Datetime values will be formatted in ISO standard whereas decimals will be formatted corresponding to the localization of the logged-in user.
|
||
|
Hit list configuration menu. You can add or remove columns via the Hit list configuration menu in the header of the hit list. |
||
|
Refresh the hit list. |
||
|
Object actions menu. If multiple objects are selected, the action will be applied to all of them. |
Filter Panel
In the filter panel, you can control the display of the objects shown in a hit list. You can limit the number of objects shown in the hit list by using filters. You can find the filters in the filter panel next to the object list. Click the Double chevron icon to expand the filter panel if it is collapsed.
In the filter panel, you can use both default filters that are available to every user throughout the system and your own filters that you have configured yourself via the filter configuration menu. How many filters are available and which depends on the object types that are displayed in an object list.
You activate a filter by clicking the checkbox next to it. The numbers in front of the checkboxes indicate how many documents in the hit list match the specific filter criterion.
You can expand and collapse the sections in the list of filters by clicking the Minus or Plus icons. In the footer of the filter panel, you can toggle between different layouts for the display of the filters (flat list, grouped), or expand and collapse the filter panel. The filter panel’s layout settings are saved when you exit the view. The next time you open the same view, the same layout settings will be displayed.
Hit List Area
Hit List
The hit list presents the results of a search request in a table per default. It contains several columns containing basic metadata, type metadata, and tags with information such as object type, title, description, editor, etc.
The appearance of this table can vastly differ, depending on the search, configuration of object types, or configuration of the hit list. This means that the view of a hit list always corresponds to the hit list configuration of the object type currently selected in the hit list.
You can make the following changes directly in a hit list:
-
Adjust column widths by moving the column divider or by double-clicking the column divider (creates the optimal column width). The change of column width will also affect other hit lists, provided that you use the same columns there, too. If you have changed column widths, these changes will be saved automatically when you switch views. In addition, these settings apply to all users who use the same browser as you.
-
Adjust column sorting:
-
You can sort the hit list by a column by clicking its header. Clicking the column header repeatedly will change the sort direction or undo it.
-
You can sort a hit list by several columns by holding the Ctrl key. Numbers and small arrows in the column headers indicate the sort order.
-
Columns with labels (for example, columns with user names) cannot be sorted.
-
If you have sorted a hit list by clicking the column headers and then open the hit list configuration menu, this sorting will be transferred to the hit list configuration menu and can be saved there.
-
If you select an object in the hit list, the object aspects will be displayed on the right-hand side of the screen. You can open the folder view, or the object view if a document does not have a parent folder, by double-clicking an item in the hit list.
Selecting and Focusing
We distinguish between selected and focused elements:
-
Selected elements:
-
The row of selected elements is highlighted.
-
Multiple rows can be selected.
-
-
Focused elements:
-
Only one element out of all selected elements can be focused.
-
The icon is highlighted again at the beginning of the row.
-
For focused elements, the object aspects are displayed in the object area.
-
You can use the mouse to select further elements by additionally holding down the Ctrl key or the Shift key while clicking these elements. If you hold down the Shift key when clicking the mouse, all the rows between the row you have clicked and the row with the most recent focusing are selected, but the focus remains on the first row. If you hold down the Ctrl key when clicking the mouse, the row you have clicked is highlighted in addition to the existing selections. The focus still remains on the first row. When you position the cursor on another selected row and click the right mouse button, this row is focused.
Click the mouse on the selected row while holding down the Ctrl key to remove the selection again.
Copying
The copy to clipboard operation is supported in all grids (result list, metadata table) and can be applied in the following ways:
Key combination | Selection |
---|---|
Ctrl+C |
Single cell |
Ctrl+Alt+C |
Single cell and the corresponding column header |
Ctrl+Shift+C |
Selected rows |
Ctrl+Shift+Alt+C |
Selected rows and all column headers |
To indicate that copying the selection was successful, the selected cells/rows are highlighted in the accent color for a few seconds. This is the default setting, which the administrator can adjust accordingly.
Footer
The number of hits is shown in the footer of the hit list. In the footer of the hit list, you can also choose between the display layouts, scroll through the hit list or go to the start or end.
|
Table layout |
|
Gallery layout |
|
List layout |
/ |
Previous/next page of the hit list |
/ |
First/last page of the hit list |
Object Area
The object area is displayed to the right of the hit list area when you select an element from the hit list. It shows all object aspects of the selected object. To hide the object area, click the element in the hit list again while holding the Ctrl key.
4.6.12. Business Process Management
Processes are created based on at least one object, which is stored as an attachment in the process.
In the default configuration, users can start a follow-up process for an object via Manage follow-us provided by the object actions menu. If an administrator configures further types of business processes in addition to follow-up processes, they can be started for individual objects via the respective object action under MORE ACTIONS in the object actions menu.
Each process contains tasks that must be completed by users.
There are three specific views that allow users to handle processes:
-
The Inbox view lists all tasks of processes the currently logged-in user is assigned to, such as reminder tasks for follow-up processes that have reached their follow-up date.
-
The My follow-ups view lists all active follow-up processes that you created via the object actions menu.
-
The My processes view lists all processes started by the logged-in user.
In the individual views, the process/task list can be sorted by individual columns as already described for hit lists. Furthermore, it is possible to filter by specifying a term that should be matched by the subject of each displayed process/task.
The number of displayed processes/tasks is limited to 100 in the individual views in the default configuration. The configuration can be customized by specifying other values in the main.json configuration file.
Inbox View
The Inbox shows an overview of all the tasks a user is assigned to. The view of the Inbox can be toggled between a list view and a table view using the corresponding buttons at the bottom right.
In the Table view, the following columns are displayed: Type, Task, Subject, Received on and Due on. In the Type column, the Processes icon represents tasks of custom processes and the Notification icon represents follow-ups. The sort order can be changed by clicking on the header of the corresponding column. The position of columns can be rearranged within the table by drag and drop of individual columns. A red entry in the Due on column indicates that this task is overdue.
In the List view, Type (icon only), Subject and Task are displayed on the left-hand side, and the due date on the right-hand side. Sorting the inbox items or repositioning the information is not possible.
Tasks can be opened for editing by clicking on the respective task in the Inbox view. On the right-hand side, the task details will open, in which you can edit the task. After editing, the task can be further processed using the buttons at the bottom of the task details.
To process tasks, different buttons are available depending on the nature of the task. Standard follow-ups with the entry “Review” in the Task column only offer the option Confirm. For custom processes, Delegate, Forward, and other custom buttons are available as well as individual entries in the Task column, depending on the process model.
In the Inbox, attachments can be added to the task or deleted from it while the process is running. Attachments are displayed in the Attachments task aspect in the task details for every task. The document highlighted in the accent color is the focused attachment for which object details are displayed. Note that the first attachment cannot be deleted.
My follow-ups View
Follow-up processes can be created for both folder and document objects. They act as processing reminders, for example. You can only create one follow-up for each object via the object actions menu. Once you have created a follow-up, it will be displayed in the My follow-ups view provided via the main menu until the due date of the follow-up is reached. Here you can edit or delete all active follow-ups (i.e., follow-ups for which time has not yet expired).
When the due date of a follow-up is reached, the object to be followed up is also displayed in the Inbox provided via the main menu. By confirming the follow-up, you can remove expired follow-ups from both the Inbox and the My follow-ups view.
My processes View
If you started a process, it appears in the My processes view. In addition to the filter option by a query term, the predefined filters All, Running and Completed are available.
By selecting a process in the task list, the users can open the process details view with the Summary, Progress, Comments and Attachments aspect areas.
4.6.13. Retention Management View
Only for users with specific authorization: The Retention management view is accessible via the Main menu as of product version 2022 Winter LTS. A hit list view displays all objects with a system:rmExpirationDate property. The functional icons in the header area are already described for the hit list view.
The first column of the hit list contains a colored label that indicates whether the expiration date is already exceeded or not. A time is specified that tells users by how long the expiration date is already exceeded or how long it is until the expiration date is reached. If the time is longer than 12 months, it is indicated in years (e.g., 1.5 year(s) means one year and six months).
The predefined filters are:
-
having any expiration date (All),
-
having an expiration date within the next month (Next month) or
-
having an expired expiration date (To be removed).
By clicking an object in the hit list, you open the object aspects for this object.
The destruction date is displayed if specified, but is not evaluated. |
4.6.14. Linking your Documentation
You can set up a hyperlink in the About yuuvis® area as well as on the yuuvis® Momentum bar to link to your own documentation of your custom solution. The corresponding URL is configured in the main.json
configuration file.
5. Administration Tools
5.1. Tenant Management API
The Tenant Management API is a collection of endpoints provided by the tenant-management
service. It is responsable for the retrieval of information from the connected identity provider for Web-API Gateway, clients and business process management (if configured). Thus, you can connect any identity provider working with OAuth2.
In combination with Keycloak, it additionally provides the tenant and user management functionality used by yuuvis® architect.
5.1.1. Endpoints
admin-controller
These endpoints can be used for role, group and user management in Keycloak within the own tenant. Administrative tenant-specific information can be retrieved as well.
The access to the endpoints has to be limited to administrative users as specified with the permission for /tenant-management/api/admin/**
endpoints in the authentication-prod.yml
configuration file.
If you use yuuvis® architect, do not change the default access condition that is matched with the YUUVIS_TENANT_ADMIN
role.
As of 2022 Autumn, in the default configuration, users with the YUUVIS_MANAGE_SETTINGS
role are allowed to manage users of their own tenant as well. They have access to all endpoints /tenant-management/api/admin/users/**
. However, the following operations are not allowed for them:
-
Assigning the
YUUVIS_TENANT_ADMIN
orYUUVIS_SYSTEM_INTEGRATOR
roles. -
Editing the data of users having the
YUUVIS_TENANT_ADMIN
orYUUVIS_SYSTEM_INTEGRATOR
role. -
Deleting users having the
YUUVIS_TENANT_ADMIN
orYUUVIS_SYSTEM_INTEGRATOR
role.
GET /tenant-management/api/admin/groups
- Retrieve a list of groups.
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves all groups with the assigned roles and members for the tenant.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
curl -X 'GET' \ 'https://examplehost.net/tenant-management/api/admin/groups' \ -H 'accept: application/json'
- Response Example
-
[ { "id": "fa854da5-004a-5187-9cc6-3b5c5bc2c728", "name": "HR-Manager", "realmRoles": [ "EMAIL_WITHOUT_ACL" ], "members": [ "gustav" ] }, { "id": "dab12224-4e4a-5e23-06e8-ffd3ed17cff7", "name": "QA-Manager", "realmRoles": [ "QA_MANAGER" ], "members": [ "susanne", "gustav" ] } ]
POST /tenant-management/api/admin/groups
- Create or add a top level realm group.
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Creates a new group for the tenant with the properties specified in the JSON request body.
In the response, the group ID is returned again in JSON format.
The only required parameter is
name
for the group name. If roles should be assigned the givenrealmRoles
must exist.Response HTTP status codes:
HTTP status code Meaning 201
CREATED
401
Unauthorized
409
Conflict
- Request Example
-
POST /tenant-management/api/admin/groups HTTP/1.1
{ "id": "fa854da5-004a-5187-9cc6-3b5c5bc2c728", "name": "HR-Manager", "realmRoles": [ "EMAIL_WITHOUT_ACL" ], "members": [ "gustav" ] }
- Response Example
-
201 CREATED
GET /tenant-management/api/admin/groups/{id}
- Retrieve representation of a group.
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves the group specified by
id
with the assigned roles and members for the tenant.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
GET /tenant-management/api/admin/groups/fa854da5-004a-5187-9cc6-3b5c5bc2c728 HTTP/1.1
no request body
- Response Example
-
200 OK
Response Body{ "id": "fa854da5-004a-5187-9cc6-3b5c5bc2c728", "name": "HR-Manager", "realmRoles": [ "EMAIL_WITHOUT_ACL" ], "members": [ "gustav" ] }
PUT /tenant-management/api/admin/groups/{id}
- Update a group.
- As of Version
-
2021 Autumn
- Request Method
-
PUT
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Updates the data of the group specified by
id
with the data passed in the request body in JSON format.This endpoint does not allow for adding the role
YUUVIS_SYSTEM_INTEGRATOR
to a group. If this role is passed as an entry of therealmRoles
list, the endpoint will return an error.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
PUT /tenant-management/api/admin/groups/a99a0bb1-2345-6c77-8901-22dee3f4a567 HTTP/1.1
Request Body{ "id": "fa854da5-004a-5187-9cc6-3b5c5bc2c728", "name": "HR-Manager", "realmRoles": [ "EMAIL_WITHOUT_ACL" ], "members": [ "gustav" ] }
- Response Example
-
200 OK
DELETE /tenant-management/api/admin/groups/{id}
- Delete a group.
- As of Version
-
2021 Autumn
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Deletes the group specified by
id
.Response HTTP status codes:
HTTP status code Meaning 204
No content
401
Unauthorized
404
Not found
409
Conflict
500
Internal Server Error
- Request Example
-
/tenant-management/api/admin/groups/a99a0bb1-2345-6c77-8901-22dee3f4a567
no request body
- Response Example
-
200 NO CONTENT
no response body
GET /tenant-management/api/admin/roles
- Retrieve all roles.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Gets all roles.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
500
Internal Server Error
- Request Example
-
GET /tenant-management/api/admin/roles HTTP/1.1
no request body
- Response Example
-
200 OK
Response Body{ "name": "TEST_ROLE", "description": "Example role" }
POST /tenant-management/api/admin/roles
- Create a role.
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Creates a new role for the tenant with the properties specified in the JSON request body.
The only required parameters are
name
for the role and itsdescription
.Response HTTP status codes:
HTTP status code Meaning 201
CREATED
401
Unauthorized
500
Internal Server Error
- Request Example
-
POST /tenant-management/api/admin/roles HTTP/1.1
Request Body{ "name": "TEST_ROLE", "description": "Example role" }
- Response Example
-
201 CREATED
Response Body{ "errors": [], "valid": true }
DELETE /tenant-management/api/admin/roles/{role-name}
- Delete a role.
- As of Version
-
2021 Autumn
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Deletes the role specified by
name
.Response HTTP status codes:
HTTP status code Meaning 204
No content
401
Unauthorized
404
Not found
409
Conflict
500
Internal Server Error
- Request Example
-
/tenant-management/api/admin/role/myrole
no request body
- Response Example
-
200 OK
no response body
GET /tenant-management/api/admin/tenant
- Retrieve the top-level representation of the tenant.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Retrieves the tenant data as given in the Keycloak identity provider for the tenant of the calling user.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
GET /tenant-management/api/admin/tenant HTTP/1.1
no request body
- Response Example
-
200 OK
Response Body{ "name": "My Name", "description": "My Tenant", "displayNameHTML": "This is a HTML formatted display name", "adminPassword": "changeme", "adminEmail": "mrexample@examplemail.net", "adminFirstName": "Johann", "adminLastName": "Fluss", "enabled": true, "emailSettings": { "host": "string", "from": "string", "username": "string", "password": "string", "fromDisplayName": "string", "port": 0, "enableAuthentication": true, "enableSSL": true, "enableStartTLS": true }, "clientSettings": { "redirectUris": [ "string" ], "postLogoutRedirectUri": "string" }, "systems": { "ips": true, "yuuvis": true } }
PATCH /tenant-management/api/admin/tenant
- Update the tenant.
- As of Version
-
2023 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Updates the tenant data in the Keycloak identity provider for the tenant of the calling user.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
403
Forbidden
500
Internal Server Error
- Request Example
-
PATCH /tenant-management/api/admin/tenant HTTP/1.1
Request Body[ {"op":"replace", "path": "/displayNameHTML", "value" : "This is a HTML formatted display name" }, {"op":"replace", "path": "/description", "value" : "My Tenant" }, { "op": "replace", "path": "/emailSettings/port", "value": 200 }, {"op":"replace", "path": "/enabled", "value" : false } ]
- Response Example
-
200 OK
Response Body{ "name": "My Name", "description": "My Tenant", "displayNameHTML": "This is a HTML formatted display name", "adminPassword": "changeme", "adminEmail": "mrexample@examplemail.net", "adminFirstName": "Johann", "adminLastName": "Fluss", "enabled": true, "emailSettings": { "host": "string", "from": "string", "username": "string", "password": "string", "fromDisplayName": "string", "port": 0, "enableAuthentication": true, "enableSSL": true, "enableStartTLS": true }, "clientSettings": { "redirectUris": [ "string" ], "postLogoutRedirectUri": "string" }, "systems": { "ips": true, "yuuvis": true } }
GET /tenant-management/api/admin/users
- Retrieve a list of users.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
andYUUVIS_MANAGE_SETTINGS
(as of 2022 Autumn) roles. - Description
-
Retrieves a list of all users within the tenant.
As 2021 Autumn, the list can be filtered by applying query parameters.
Optional query parameters:
Parameter Type Description search
string
Retrieve only users for which the specified string is contained in user name, first name, last name or e-mail.
first
integer($int32)
Skip the first users in the result list. Return only users with index equal or larger than the specified value.
max
integer($int32)
Return only the specified number of users.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
GET /tenant-management/api/admin/users HTTP/1.1
no request body
- Response Example
-
200 OK
Response Body[ { "id": "406b5a28-7a8b-4c36-a569-df7bff480375", "firstName": "Heinrich", "lastName": "Schuetzel", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "YUUVIS_TENANT_ADMIN", "HR_MANAGER", "YUUVIS_CREATE_OBJECT", "YUUVIS_MANAGE_SETTINGS" ], "username": "newuser5", "enabled": true, "createdTimestamp": 1622122631393 }, { "id": "320c67d0-b88b-4e99-852a-b938f4b38cd7", "email": "kammer@segelreisen.de", "firstName": "Hannes", "lastName": "Kammer", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "YUUVIS_TENANT_ADMIN", "YUUVIS_CREATE_OBJECT", "YUUVIS_MANAGE_SETTINGS", "YUUVIS_AI_PIPELINE", "COMPLIANCE_MANAGER", "YUUVIS_AI_PREDICT" ], "groups": [ "onlyoffice" ], "username": "kammer", "enabled": true, "createdTimestamp": 1591957723730 }, { "id": "a6f5e1aa-ff42-4140-b9ec-5de4cc61f1a9", "email": "schwimmer@segelreisen.de", "firstName": "Klaus", "lastName": "Schwimmer", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "INVOICE_MANAGER", "YUUVIS_TENANT_ADMIN", "HR_MANAGER", "YUUVIS_AIINVOICE", "EMAIL_WITHOUT_ACL", "QA_MEMBER_AREA2", "uma_authorization", "YUUVIS_CREATE_OBJECT", "TEAMS_MANAGER", "PHOTOARCHIVE_MANAGER", "YUUVIS_MANAGE_SETTINGS", "QA_MANAGER", "ACL_ALL_USERS", "YUUVIS_AI_PIPELINE", "QA_MEMBER_AREA1", "COMPLIANCE_MANAGER", "YUUVIS_AI_PREDICT", "offline_access" ], "username": "klaus", "enabled": true, "createdTimestamp": 1606820894094 } ]
POST /tenant-management/api/admin/users
- Create a user.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
andYUUVIS_MANAGE_SETTINGS
(as of 2022 Autumn) roles. - Description
-
Creates a new user in the tenant with the given properties.
The properties for the new user are passed in JSON format. In the response, the user including its ID is returned again in JSON format.
The only required parameter is
username
, but specifying theemail
parameter is recommended. The specified e-mail address is used to invite users after they have been created and in case they have forgotten their password. If no SMTP parameters are set for a new user, no invitation e-mail can be sent. The currently logged-in user will be informed.It is not allowed to assign the
YUUVIS_SYSTEM_INTEGRATOR
default role to new users.As of 2022 Autumn, in the default configuration, users with the
YUUVIS_MANAGE_SETTINGS
role are allowed to use the endpoint as well. However, they are not allowed to assign the rolesYUUVIS_TENANT_ADMIN
orYUUVIS_SYSTEM_INTEGRATOR
.It is recommended to deactivate users instead of deleting them. Their usernames might be required for compliance reasons.
New users are created with the Keycloak settings shown in the screenshot below. The first actions newly created users have to carry out are specified under Required User Actions. In this configuration, these are Update Password and Update Profile. Hence, new users have to register by setting a password and other user data. The URL to the registration page is specified in the e-mail invitation.
yuuvis® Momentum client as reference implementation displays the user’s name in the following format:
lastName, firstName (username)
.Optional query parameters:
Parameter Type Description withInvitation
boolean
Weather an invitation should be sent on creation. (default:
false
)temporaryPassword
boolean
Weather the password should be changed after the first login. (default:
true
)Response HTTP status codes:
HTTP status code Meaning 201
CREATED
401
Unauthorized
409
Conflict
At least one of the following situations occurred:
-
The username is not unique.
-
The email address is not unique.
-
The email address or password must be set.
-
The role {ROLE_NAME} was not found.
-
The group {GROUP_NAME} was not found.
-
- Request Example
-
GET /tenant-management/api/admin/users HTTP/1.1
Request Body{ "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0 }
- Response Example
-
201 CREATED
Response Body{ "id": "a00a0bb1-1234-5c66-7890-00fbb1c1a222" }
GET /tenant-management/api/admin/users/{id}
- Retrieve representation of a user.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
andYUUVIS_MANAGE_SETTINGS
(as of 2022 Autumn) roles. - Description
-
Retrieves the data of the user specified by
id
.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
GET /tenant-management/api/admin/users/a69a0eb6-3662-4c00-8096-38fbb2c4a922 HTTP/1.1
no request body
- Response Example
-
200 OK
Response Body{ "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0 }
PUT /tenant-management/api/admin/users/{id}
- Update a user.
- As of Version
-
2020 Winter
- Request Method
-
PUT
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
andYUUVIS_MANAGE_SETTINGS
(as of 2022 Autumn) roles. - Description
-
Updates the data of the user specified by id with the data passed in the request body in JSON format.
As of version 2021 Autumn, this endpoint does not allow for the assignment of the
YUUVIS_SYSTEM_INTEGRATOR
role to a user. If this role is passed as an entry of the roles list, the endpoint will return an error.As of version 2022 Summer, the deactivation of users leads to an invalidation of all their active sessions (if the
enabled
property is changed tofalse
).As of 2022 Autumn, in the default configuration, users with the
YUUVIS_MANAGE_SETTINGS
role are allowed to use the endpoint as well. However, they are not allowed to assign the rolesYUUVIS_TENANT_ADMIN
orYUUVIS_SYSTEM_INTEGRATOR
or to update the data of users with at least one of those roles.Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
409
Conflict
At least one of the following situations occurred:
-
The username is not unique.
-
The email address is not unique.
-
The email address or password must be set.
-
The role {ROLE_NAME} was not found.
-
The group {GROUP_NAME} was not found.
-
- Request Example
-
PUT /tenant-management/api/admin/users/a99a0bb1-2345-6c77-8901-22dee3f4a567 HTTP/1.1
Request Body{ "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0 }
- Response Example
-
200 OK
DELETE /tenant-management/api/admin/users/{id}
- Delete a user.
- As of Version
-
2020 Winter
- Request Method
-
DELETE
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
andYUUVIS_MANAGE_SETTINGS
(as of 2022 Autumn) roles. - Description
-
Deletes the user specified by
id
.As of 2022 Summer, all active sessions of the deleted user are invalidated.
As of version 2022 Autumn, in the default access authorization configuration, users with the
YUUVIS_MANAGE_SETTINGS
roles are allowed to use the endpoint as well. However, they are not allowed to delete users with theYUUVIS_TENANT_ADMIN
orYUUVIS_SYSTEM_INTEGRATOR
role assigned.Response HTTP status codes:
HTTP status code Meaning 204
No content
401
Unauthorized
404
Not found
409
Conflict
422
Unprocessable Entity
- Request Example
-
/tenant-management/api/admin/users/a99a0bb1-2345-6c77-8901-22dee3f4a567
no request body
- Response Example
-
204 No content
Response Body{ "reason": "string", "deleted": true }
GET /tenant-management/api/admin/users/count
- Retrieve amount of users.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
andYUUVIS_MANAGE_SETTINGS
(as of 2022 Autumn) roles. - Description
-
Retrieves the number of all users of the tenant.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
- Request Example
-
GET /tenant-management/api/admin/users HTTP/1.1
no request body
- Response Example
-
200 OK
42
idm-controller
The endpoints of the Identity Management Controller (idm-controller) provide an interface for retrieving user and role information from the connected identity provider.
In the default configuration, the endpoints are available for any user logged-in to yuuvis® Momentum.
GET /tenant-management/api/idm/me
- Retrieve representation of the current user.
- As of Version
-
2021 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
The endpoint is available for every logged-in user.
- Description
-
Retrieves the representation of the currently logged-in user.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/tenant-management/api/idm/me
no request body
- Response Example
-
200 OK
Response Body{ "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0 }
GET /tenant-management/api/idm/roles
- Retrieve all roles.
- As of Version
-
2022 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
The endpoint is available for every logged-in user.
- Description
-
Gets all roles of the tenant of the requesting user.
Optional query parameters:
Parameter Type Description search
string
A string contained in role name or description.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
500
Internal Server Error
- Request Example
-
https://<host>/tenant-management/api/idm/roles?search=test
no request body
- Response Example
-
200 OK
Response Body[ { "name": "TEST_ROLE", "description": "Example role" }, { "name": "EXAMPLE_ROLE", "description": "Role containing word test in its description" } ]
GET /tenant-management/api/idm/roles/{role}/users
- Retrieve users that have the given role.
- As of Version
-
2021 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
The endpoint is available for every logged-in user.
- Description
-
Retrieves a list of users that have the specified
role
assigned to them.Optional query parameters:
Parameter Type Description briefRepresentation
boolean
-
If
true
(default), the following parameters will be returned for each user:id
,email
,firstName
,lastName
,username
,enabled
,createdTimestamp
. -
If
false
, the following parameters will be additionally included:roles
,groups
.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
-
- Request Example
-
https://<host>/tenant-management/api/idm/roles/YUUVIS_TENANT_ADMIN/users?briefRepresentation=false
no request body
- Response Example
-
200 OK
Response Body[ { "id": "406b5a28-7a8b-4c36-a569-df7bff480375", "firstName": "Heinrich", "lastName": "Schuetzel", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "YUUVIS_TENANT_ADMIN", "HR_MANAGER", "YUUVIS_CREATE_OBJECT", "YUUVIS_MANAGE_SETTINGS" ], "username": "newuser5", "enabled": true, "createdTimestamp": 1622122631393 }, { "id": "320c67d0-b88b-4e99-852a-b938f4b38cd7", "email": "kammer@segelreisen.de", "firstName": "Hannes", "lastName": "Kammer", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "YUUVIS_TENANT_ADMIN", "YUUVIS_CREATE_OBJECT", "YUUVIS_MANAGE_SETTINGS", "YUUVIS_AI_PIPELINE", "COMPLIANCE_MANAGER", "YUUVIS_AI_PREDICT" ], "groups": [ "onlyoffice" ], "username": "kammer", "enabled": true, "createdTimestamp": 1591957723730 }, { "id": "a6f5e1aa-ff42-4140-b9ec-5de4cc61f1a9", "email": "schwimmer@segelreisen.de", "firstName": "Klaus", "lastName": "Schwimmer", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "INVOICE_MANAGER", "YUUVIS_TENANT_ADMIN", "HR_MANAGER", "YUUVIS_AIINVOICE", "EMAIL_WITHOUT_ACL", "QA_MEMBER_AREA2", "uma_authorization", "YUUVIS_CREATE_OBJECT", "TEAMS_MANAGER", "PHOTOARCHIVE_MANAGER", "YUUVIS_MANAGE_SETTINGS", "QA_MANAGER", "ACL_ALL_USERS", "YUUVIS_AI_PIPELINE", "QA_MEMBER_AREA1", "COMPLIANCE_MANAGER", "YUUVIS_AI_PREDICT", "offline_access" ], "username": "klaus", "enabled": true, "createdTimestamp": 1606820894094 } ]
GET /tenant-management/api/idm/users
- Retrieve a list of users, filtered according to query parameters.
- As of Version
-
2021 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
The endpoint is available for every logged-in user.
- Description
-
Retrieves a list of all users within the same tenant as the currently logged-in user.
Each user in the result list will be represented with all user account parameters available via Tenant Management API.
Required query parameter:
Parameter Type Description pageable
JSON
Example{ "page": 0, "size": 1, "sort": [ "string" ] }
Optional query parameters:
Parameter Type Description search
string
Retrieve only users for which the specified string is contained in user name, first name, last name or e-mail.
briefRepresentation
boolean
-
If
true
(default), the following parameters will be returned for each user:id
,email
,firstName
,lastName
,username
,enabled
,createdTimestamp
. -
If
false
, the following parameters will be additionally included:roles
,groups
.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
-
- Request Example
- Response Example
-
200 OK
Response Body{ "objects": [ { "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0 } ], "numItems": 50, "totalNumItems": 1234, "hasMoreItems": true }
GET /tenant-management/api/idm/users/{id}
- Retrieve representation of the specified user.
- As of Version
-
2021 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
The endpoint is available for every logged-in user.
- Description
-
Retrieves the representation of the user specified by
id
. Only users within the tenant of the logged-in user are available.The response body contains all user account properties available via Tenant Management API.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Request Example
-
https://<host>/tenant-management/api/idm/users/string
no request body
- Response Example
-
200 OK
Response Body{ "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0 }
system-controller
These endpoints can be used for role, group and user management for any tenant within the system and to create and delete tenants in Keycloak.
The access to the endpoints has to be limited to administrative users as specified with the permission for /tenant-management/api/system/**
endpoints in the authentication-prod.yml
configuration file.
If you use yuuvis® architect, do not change the default access condition that is matched with the YUUVIS_SYSTEM_INTEGRATOR
role.
GET /tenant-management/api/system/profile
- Retrieve the tenant creation profile.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Updates the tenant creation profile that is used while creating a tenant of a customer with all the information that should be set up, e.g., additional roles, users, schema and client settings. Each SaaS application has its own tenant creation profile.
Optional query parameters:
Parameter Type Description name
String
The name of the tenant creation profile. Should be specified only if multiple profiles are used.
Response HTTP status codes:
HTTP status code Meaning 200
OK
401
Unauthorized
404
Not found
- Response Example
-
{ "user": { "withInvitation": true, "users": [ { "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0, "temporaryPassword": true } ] }, "roles": [ { "name": "string", "description": "string" } ], "groups": [ { "id": "string", "name": "string", "realmRoles": [ "string" ], "members": [ "string" ] } ], "email": { "host": "string", "from": "string", "username": "string", "password": "string", "fromDisplayName": "string", "port": 0, "enableAuthentication": true, "enableSSL": true, "enableStartTLS": true }, "general": { "displayNameHTML": "string", "customMicroservice": "string", "customMicroserviceOnDelete": "string", "defaultLocale": "string", "supportedLocales": [ "string" ] }, "client": { "redirectUris": [ "string" ], "postLogoutRedirectUri": "string" } }
POST /tenant-management/api/system/profile
- Update the tenant creation profile.
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Description
-
Updates the tenant creation profile that is used while creating a tenant of a customer with all the information that should be set up, e.g., additional roles, users, schema and client settings. Each SaaS application has its own tenant creation profile. All available parameters are described here.
Optional query parameters:
Parameter Type Description name
String
The name of the tenant creation profile. Should be specified only if multiple profiles are used.
Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the tenant with the specified name has been created.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
POST /tenant-management/api/system/profile HTTP/1.1
Request Body{ "user": { "withInvitation": true, "users": [ { "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0, "temporaryPassword": true } ] }, "roles": [ { "name": "string", "description": "string" } ], "groups": [ { "id": "string", "name": "string", "realmRoles": [ "string" ], "members": [ "string" ] } ], "email": { "host": "string", "from": "string", "username": "string", "password": "string", "fromDisplayName": "string", "port": 0, "enableAuthentication": true, "enableSSL": true, "enableStartTLS": true }, "general": { "displayNameHTML": "string", "customMicroservice": "string", "customMicroserviceOnDelete": "string", "defaultLocale": "string", "supportedLocales": [ "string" ] }, "client": { "redirectUris": [ "string" ], "postLogoutRedirectUri": "string" } }
GET /tenant-management/api/system/tenants
- Retrieve the top-level representation of all realms.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the top-level representation of all realms. It will not include nested information like User and Client representations. Reads the list of all tenants.
Optional query parameters:
Parameter Type Description withSystems
boolean
If
true
, thesystems
property section is included for each tenant in the response JSON. Iffalse
(default), thesystems
properties section is not displayed.For each tenant, the following properties are included in the JSON response body:
Property Type Description name
string
Tenant name.
description
string
Only displayed if available.
enabled
boolean
If
true
, the tenant is activated. Users can log in.systems
Section of parameters displayed only if
withSystems=true
.ips
boolean
If
true
, the tenant is configured in the identity provider.yuuvis
boolean
If
true
, the tenant is configured in yuuvis® Momentum.Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the data of all tenants have been read.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
GET /tenant-management/api/system/tenants?withSystems=true
- Response Example
-
Response Body
[ { "name": "string777", "enabled": false, "systems": { "ips": true, "yuuvis": false } }, { "name": "technicaltenant", "description": "tenant userd by specific services", "enabled": false, "systems": { "ips": true, "yuuvis": false } }, { "name": "e2e", "description": "End-To-End Test System", "enabled": true, "systems": { "ips": true, "yuuvis": true } } ]
POST /tenant-management/api/system/tenants
- Create a tenant.
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Creates a new tenant with the values for the corresponding parameters specified in JSON format. Required settings for Keycloak and yuuvis® Momentum core are passed as well as custom (= product application) settings.
A Keycloak realm with a name and description is created together with the initial default technical user
admin
that you can use as a proxy user in your portal for tenant management. The values for name and description can be displayed in the Keycloak Admin Console as Realm Name and Display name as shown in the first screenshot below.The parameters available for defining Keycloak settings are described in the
here
. These parameters determine the settings for each further tenant that will be created.name
anddescription
are mandatory.The
adminPassword
can be set for the default user admin. The admin user has to be used to create any additional users for the tenant using the user management in yuuvis® architect.If
adminEmail
is specified and the smtp e-mail service parameters are set up, an e-mail invitation is sent to this address. Users have to change the password and edit their profile data.If no e-mail address is specified, you can use a (secure) communication channel of your choice to inform your admin user about how to log in to yuuvis® architect and manage users.
In an additional system parameter section, you can specify following parameters:
-
ips
- Boolean value. Iftrue
, the tenant is created in the identity provider (only supported for Keycloak). -
yuuvis
- Boolean value. Iftrue
, the tenant is added to theapplication-oauth2.yml
configuration file of the core system.
In the yuuvis® Momentum system, a tenant with the same name will be created as well. No further configurations are set up. For additional configurations like tenant schema or extensions of the role set, a custom microservice can be configured in the profile. It will be called after each tenant creation process and add the defined extending configurations.
After creating a new yuuvis® tenant, the newly created admin user can be used to access the system using the core API, yuuvis® architect, or yuuvis® Momentum client as reference implementation.
Optional query parameters:
Parameter Type Description profile
String
The name of the tenant creation profile that should be used for the new tenant. Should be specified only if multiple profiles are available. It is obsolete if less than two tenant creation profiles are available.
Response HTTP status codes:
HTTP status code Meaning 201 CREATED
Successful, the tenant with the name has been created.
400 BAD REQUEST
No valid instance for new realm <tenantname> found.
401 UNAUTHORIZED
The call was unauthorized.
-
- Request Example
-
Request Example
{ "name": "My Name", "description": "My Tenant", "displayNameHTML": "This is a HTML formatted display name", "adminPassword": "changeme", "adminEmail": "mrexample@examplemail.net", "adminFirstName": "Johann", "adminLastName": "Fluss", "enabled": true, "emailSettings": { "host": "string", "from": "string", "username": "string", "password": "string", "fromDisplayName": "string", "port": 0, "enableAuthentication": true, "enableSSL": true, "enableStartTLS": true }, "clientSettings": { "redirectUris": [ "string" ], "postLogoutRedirectUri": "string" }, "systems": { "ips": true, "yuuvis": true } }
- Response Example
-
201 CREATED
no response body
GET /tenant-management/api/tenants/{tenant}
- Retrieves the top-level representation of the Keycloak realm specified by tenant.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the top-level representation of the Keycloak realm specified by tenant. It will not include nested information like User and Client representations. Reads the tenant data of the specified tenant.
Optional query parameters:
Parameter Type Description withSystems
boolean
If
true
, thesystems
property section is included for each tenant in the response JSON. Iffalse
(default), thesystems
properties section is not displayed.Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the data of the specified tenant has been read.
401 UNAUTHORIZED
The call was unauthorized.
404 NOT FOUND
The specified tenant was not found.
- Request Example
-
GET /tenant-management/api/system/tenants/myMandant1 HTTP/1.1
no request body
- Response Example
-
200 OK
Response Body{ "value": {}, "filters": {} }
DELETE /tenant-management/api/system/tenants/{tenant}
- Delete the specified tenant.
- As of Version
-
2020 Winter
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
The tenant is only deleted if no DMS objects are stored. If the tenant does not contain any DMS object, all client-side configurations are deleted. The configuration files saved via the
configservice
like tenant schema, forms, localization files, and catalogs are deleted as well. In case theconfigservice
is not available, those configuration files remain and have to be deleted manually later on.All users of the deleted tenant are deleted as well. If they have active sessions, they are invalidated (as of 2022 Summer).
This endpoint is still under development. Its behavior might change with the next release. Response HTTP status codes:
HTTP status code Meaning 204 NO CONTENT
Successful, the specified tenant has been deleted.
401 UNAUTHORIZED
The call was unauthorized.
404 NOT FOUND
The specified tenant was not found.
- Request Example
-
/tenant-management/api/system/tenants/myTenant
- Response Example
-
204 NO CONTENT
Response Body{ "reason": "string", "deleted": true }
PATCH /tenant-management/api/system/tenants/{tenant}
- Update a specified tenant.
- As of Version
-
2021 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Update a new tenant with the values for the corresponding parameters specified in JSON format.
The PATCH request body is expected to be in JSONPath format.
The following properties can be updated:
-
Keycloak realm Display Name (request property is
displayNameHTML
) -
HTML Display Name (request property is
description
) -
As of version 2021 Autumn: Activation/Deactivation of the tenant (request property
enabled
) -
As of version 2021 Autumn: Any property of the e-mail settings (request property
emailSettings/<property>
)
Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the tenant with the name has been updated.
401 UNAUTHORIZED
The call was unauthorized.
-
- Request Example
-
PATCH /tenant-management/api/system/tenants/myTenant HTTP/1.1
Request Body[ {"op":"replace", "path": "/displayNameHTML", "value" : "This is a HTML formatted display name" }, {"op":"replace", "path": "/description", "value" : "My Tenant" }, { "op": "replace", "path": "/emailSettings/port", "value": 200 }, {"op":"replace", "path": "/enabled", "value" : false } ]
- Response Example
-
200 OK
Response Body{ "name": "My Name", "description": "My Tenant", "displayNameHTML": "This is a HTML formatted display name", "adminPassword": "changeme", "adminEmail": "mrexample@examplemail.net", "adminFirstName": "Johann", "adminLastName": "Fluss", "enabled": true, "emailSettings": { "host": "string", "from": "string", "username": "string", "password": "string", "fromDisplayName": "string", "port": 0, "enableAuthentication": true, "enableSSL": true, "enableStartTLS": true }, "clientSettings": { "redirectUris": [ "string" ], "postLogoutRedirectUri": "string" }, "systems": { "ips": true, "yuuvis": true } }
GET /tenant-management/api/system/tenants/{tenant}/groups
- Retrieve all groups of a specified tenant.
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves all groups of the specified tenant with the assigned roles and members.
Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, all roles of the specified tenant have been read.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
GET /tenant-management/api/system/tenants/myTenant/groups HTTP/1.1
no request body
- Response Example
-
Response Body
[ { "id": "fa854da5-004a-5187-9cc6-3b5c5bc2c728", "name": "HR-Manager", "realmRoles": [ "EMAIL_WITHOUT_ACL" ], "members": [ "gustav" ] }, { "id": "dab12224-4e4a-5e23-06e8-ffd3ed17cff7", "name": "QA-Manager", "realmRoles": [ "QA_MANAGER" ], "members": [ "susanne", "gustav" ] } ]
POST /tenant-management/api/system/tenants/{tenant}/groups
- Create a group.
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Creates a new group with the given properties for the specified tenant.
The properties for the new group are passed in JSON format. In the response body, the group ID is returned again in JSON format.
The only required parameter is
name
for the group name. If roles should be assigned, the specifiedrealmRoles
must exist.Response HTTP status codes:
HTTP status code Meaning 201 CREATED
Successful, the user has been created with the specified properties.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
POST /tenant-management/api/system/tenants/{mytenant}/groups HTTP/1.1
Request Body{ "id": "fa854da5-004a-5187-9cc6-3b5c5bc2c728", "name": "HR-Manager", "realmRoles": [ "EMAIL_WITHOUT_ACL" ], "members": [ "gustav" ] }
- Response Example
-
201 CREATED
Response Body{ "id": "a00a0bb1-1234-5c66-7890-00fbb1c1a222" }
PUT /tenant-management/api/system/tenants/{tenant}/groups/{id}
- Update a specified group.
- As of Version
-
2021 Autumn
- Request Method
-
PUT
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Updates the data of the group specified by id that is given for the specified tenant.
Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the data for the specified group have been updated.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
PUT /tenant-management/api/system/tenants/{tenant}/groups/a99a0bb1-2345-6c77-8901-22dee3f4a567 HTTP/1.1
Request Body{ "id": "fa854da5-004a-5187-9cc6-3b5c5bc2c728", "name": "HR-Manager", "realmRoles": [ "EMAIL_WITHOUT_ACL" ], "members": [ "gustav" ] }
- Response Example
-
200 OK
DELETE /tenant-management/api/system/tenants/{tenant}/groups/{id}
- Delete a specified group.
- As of Version
-
2021 Autumn
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Deletes the group specified by id in the specified tenant.
Response HTTP status codes:
HTTP status code Meaning 204 NO CONTENT
Successful, the specified group has been deleted.
401 UNAUTHORIZED
The call was unauthorized.
404 NOT FOUND
The specified group was not found.
- Request Example
-
/tenant-management/api/system/tenants/mytenant/group/a99a0bb1-2345-6c77-8901-22dee3f4a567
- Response Example
-
204 NO CONTENT
no response body
GET /tenant-management/api/system/tenants/{tenant}/roles
- Retrieve all roles of a specified tenant.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Gets all roles of the specified tenant.
Optional query parameters:
Parameter Type Description search
string
The result list contains only roles that contain the specified string in their
name
ordecription
value.Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, all roles of the specified tenant have been read.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
GET /tenant-management/api/system/tenants/myTenant/roles HTTP/1.1
- Response Example
-
Response Body
[ { "name": "TEST_ROLE", "description": "Example role" }, { "name": "EXAMPLE_ROLE", "description": "Role containing word test in its description" } ]
POST /tenant-management/api/system/tenants/{tenant}/roles
- Create a role.
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Creates a new role for the specified tenant with the properties specified in JSON format in the request body.
The properties for the new role are passed in JSON format.
The only required parameters are name for the role and its description.
Response HTTP status codes:
HTTP status code Meaning 201 CREATED
Successful, the role has been created with the specified properties.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
POST /tenant-management/api/system/tenants/mytenant/roles HTTP/1.1
Request Body{ "name": "TEST_ROLE", "description": "Example role" }
- Response Example
-
201 CREATED
Response Body{ "errors": [], "valid": true }
DELETE /tenant-management/api/system/tenants/{tenant}/roles/{role-name}
- Delete a specified role.
- As of Version
-
2021 Autumn
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Deletes the role specified by name for the specified tenant.
Response HTTP status codes:
HTTP status code Meaning 204 NO CONTENT
Successful, the specified role has been deleted
401 UNAUTHORIZED
The call was unauthorized.
404 NOT FOUND
The specified role was not found.
- Request Example
-
/tenant-management/api/system/tenants/mytenant/role/myrole
- Response Example
-
204 NO CONTENT
no response body
GET /tenant-management/api/system/tenants/{tenant}/users
- Retrieve all users of a specified tenant.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves a list of all users of the specified tenant. As 2021 Autumn, the list can be filtered by applying query parameters.
Optional query parameters:
Parameter Type Description search
string
Retrieve only users for which the specified string is contained in user name, first name, last name or e-mail.
first
integer($int32)
Skip the first users in the result list. Return only users with index equal or larger than the specified value.
max
integer($int32)
Return only the specified number of users.
Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the data of all users of the specified tenant have been read.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
GET /tenant-management/api/system/tenants/myTenant/users HTTP/1.1
or
GET /tenant-management/api/system/tenants/myTenant/users?first=1&max=5&search=test
- Response Example
-
200 OK
Response Body[ { "id": "406b5a28-7a8b-4c36-a569-df7bff480375", "firstName": "Heinrich", "lastName": "Schuetzel", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "YUUVIS_TENANT_ADMIN", "HR_MANAGER", "YUUVIS_CREATE_OBJECT", "YUUVIS_MANAGE_SETTINGS" ], "username": "newuser5", "enabled": true, "createdTimestamp": 1622122631393 }, { "id": "320c67d0-b88b-4e99-852a-b938f4b38cd7", "email": "kammer@segelreisen.de", "firstName": "Hannes", "lastName": "Kammer", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "YUUVIS_TENANT_ADMIN", "YUUVIS_CREATE_OBJECT", "YUUVIS_MANAGE_SETTINGS", "YUUVIS_AI_PIPELINE", "COMPLIANCE_MANAGER", "YUUVIS_AI_PREDICT" ], "groups": [ "onlyoffice" ], "username": "kammer", "enabled": true, "createdTimestamp": 1591957723730 }, { "id": "a6f5e1aa-ff42-4140-b9ec-5de4cc61f1a9", "email": "schwimmer@segelreisen.de", "firstName": "Klaus", "lastName": "Schwimmer", "roles": [ "YUUVIS_SYSTEM_INTEGRATOR", "YUUVIS_DEFAULT", "INVOICE_MANAGER", "YUUVIS_TENANT_ADMIN", "HR_MANAGER", "YUUVIS_AIINVOICE", "EMAIL_WITHOUT_ACL", "QA_MEMBER_AREA2", "uma_authorization", "YUUVIS_CREATE_OBJECT", "TEAMS_MANAGER", "PHOTOARCHIVE_MANAGER", "YUUVIS_MANAGE_SETTINGS", "QA_MANAGER", "ACL_ALL_USERS", "YUUVIS_AI_PIPELINE", "QA_MEMBER_AREA1", "COMPLIANCE_MANAGER", "YUUVIS_AI_PREDICT", "offline_access" ], "username": "klaus", "enabled": true, "createdTimestamp": 1606820894094 } ]
POST /tenant-management/api/system/tenants/{tenant}/users
- Create a user.
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Creates a new user with the given properties for the specified tenant.
The properties for the new user are passed in JSON format. In the response, the user ID is returned again in JSON format.
The only required parameter is username, but specifying the email parameter is recommended. The specified e-mail address is used to invite users after they have been created and in case they have forgotten their password. If no SMTP parameters are set for a new user, no invitation e-mail can be sent. The currently logged-in user will be informed.
It is recommended to deactivate users instead of deleting them. Their user names might be required for compliance reasons.
New users are created with the Keycloak settings shown in the screenshot below. The first actions newly created users have to carry out are specified under Required User Actions. In this configuration, these are Update Password and Update Profile. Hence, new users have to register by setting a password and other user data. The URL to the registration page is specified in the e-mail invitation.
yuuvis® Momentum client as reference implementation displays the user’s name in the following format:
lastName, firstName (username)
.Optional query parameters:
Parameter Type Description withInvitation
boolean
Weather an invitation should be sent on creation. (default:
false
)temporaryPassword
boolean
Weather the password should be change after the first login. (default:
true
)Response HTTP status codes:
HTTP status code Meaning 201 CREATED
Successful, the user with the specified properties has been created.
401 UNAUTHORIZED
The call was unauthorized.
409 CONFLICT
At least one of the following situations occurred:
-
The username is not unique.
-
The email address is not unique.
-
The email address or password must be set.
-
The role
{ROLE_NAME}
was not found. -
The group
{GROUP_NAME}
was not found.
-
- Request Example
-
POST /tenant-management/api/system/tenants/{tenant}/users?withInvitation=true HTTP/1.1
Request Body{ "email": "example@exampleprovider.de", "username": "mrexample", "firstName": "Examplename", "lastName": "Examplesurname", "roles": ["role1","role2"], "groups": ["group3","group1","group5"], "enabled": true, "password": "asecurepassword" }
- Response Example
-
201 CREATED
Response Body{ "id": "a00a0bb1-1234-5c66-7890-00fbb1c1a222" }
GET /tenant-management/api/system/tenants/{tenant}/users/{id}
- Retrieve a specified user.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the data of the user specified by tenant and id.
Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the data of the specified user of the specified tenant has been read.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
GET /tenant-management/api/admin/tenant/users/a99a0bb1-2345-6c77-8901-22dee3f4a567 HTTP/1.1
- Response Example
-
200 OK
Response Body{ "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0 }
PUT /tenant-management/api/system/tenants/{tenant}/users/{id}
- Update a specified user.
- As of Version
-
2020 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Update the data of the user specified by tenant and id.
The properties for the new user are passed in JSON format.
The specified e-mail address is used in case users have forgotten their password.
It is recommended to deactivate users instead of deleting them. Their user names might be required for compliance reasons.
yuuvis® Momentum client as reference implementation displays the user’s name in the following format:
lastName, firstName (username)
.As of version 2022 Summer, the deactivation of users leads to an invalidation of all their active sessions (if the
enabled
property is changed tofalse
).Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the data of the user with the specified tenant and id have been updated.
401 UNAUTHORIZED
The call was unauthorized.
404 NOT FOUND
The user with the id was not found.
409 CONFLICT
At least one of the following situations occurred:
-
The username is not unique.
-
The email address is not unique.
-
The email address or password must be set.
-
The role
{ROLE_NAME}
was not found. -
The group
{GROUP_NAME}
was not found.
-
- Request Example
-
PUT /tenant-management/api/admin/tenants/myTenant/users/a69a0eb6-3662-4c00-8096-38fbb2c4a922 HTTP/1.1
Request Body{ "id": "string", "email": "string", "firstName": "string", "lastName": "string", "roles": [ "string" ], "groups": [ "string" ], "username": "string", "password": "string", "enabled": true, "createdTimestamp": 0 }
- Response Example
-
200 OK
no response body
DELETE /tenant-management/api/system/tenants/{tenant}/users/{id}
- Delete a specified user.
- As of Version
-
2.4
- Request Method
-
DELETE
- Response Format
-
JSON
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Deletes the user specified by id of the specified tenant.
As of 2022 Summer, all active sessions of the deleted user are invalidated.
Response HTTP status codes:
HTTP status code Meaning 204 NO CONTENT
Successful, the specified user has been deleted.
401 UNAUTHORIZED
The call was unauthorized.
404 NOT FOUND
The specified user was not found.
- Request Example
-
/tenant-management/api/system/tenants/myTenant/users/a99a0bb1-2345-6c77-8901-22dee3f4a567
- Response Example
-
204 NO CONTENT
Response Body{ "reason": "string", "deleted": true }
GET /tenant-management/api/system/tenants/{tenant}/users/count
- Request the number of users within the specified tenant.
- As of Version
-
2020 Winter
- Request Method
-
GET
- Response Format
-
TXT
- Required Permission
-
Available if listed in
authorization.accesses
inauthentication-prod.yml
and the specified access condition is matched. In the default configuration, access is granted via theYUUVIS_SYSTEM_INTEGRATOR
role. - Description
-
Retrieves the number of all users of the specified tenant.
Response HTTP status codes:
HTTP status code Meaning 200 OK
Successful, the number of users has been requested from Keycloak.
401 UNAUTHORIZED
The call was unauthorized.
- Request Example
-
GET /tenant-management/api/system/tenants/myTenant/users/count HTTP/1.1
- Response Example
-
200 OK
Response Body23
5.1.2. Tenant Creation Profile
The tenant management API allows for the creation of new tenants in a customer’s yuuvis® Momentum system. All information for the initial configuration of the new tenant are stored in the tenant creation profile, e.g. additional roles, initial users, schema and client settings. Each yuuvis® Momentum cluster has its own tenant creation profile. The tenant creation profile is stored, retrieved and updated in JSON format.
As of 2024 Summer, it is possible to store multiple tenant creation profiles. They are identified by a name
query parameter. During each tenant creation process, the administrator can select the desired pre-configured settings.
An admin user is created for each tenant that is used for the initial tenant administration. Per default, this user gets all global default roles except YUUVIS_SYSTEM_INTEGRATOR. The Credentials and E-mails will be specified during tenant creation. The users specified in the tenant creation profile are created in addition to this admin user.
The tenant creation profile does not belong the the configuration profiles of yuuvis® core. It is an independent file that follows its own concept and is managed only via the Tenant Management API.
Placeholders
It is possible to use placeholders within the tenant creation profile that will be replaced by values determined from the parameters of each tenant creation call. The syntax to incorporate them is ${varName}
. The following placeholders are available:
Placeholder Name | Description |
---|---|
|
The Keycloak Realm Display Name of the tenant as specified in the creation call. |
|
The Keycloak Realm Name of the tenant as specified in the creation call. |
The profile can be read and set via the following endpoints:
-
GET /tenant-management/api/system/profile returns the currently active profile.
-
POST /tenant-management/api/system/profile applies a new profile to the cluster.
Parameters
The following table gives an overview of the parameters available within the profile and their usage. The parameters in the section general are displayed also in the Keycloak GUI, realm setting Themes.
Parameter | Required | Values | Description |
---|---|---|---|
|
No (but recommended) |
|
Sets the left hand side of the login page’s icon and title. If not specified, the Keycloak realm HTML Display name will be set by default to |
|
No |
URL |
The URL of a custom microservice endpoint that will be called in each process of a tenant creation via the Tenant Management API. Thus, custom tenant preparations are supported. A POST request will be sent to the specified URL during each tenant creation process. The request contains a header and body:
The call is asynchronous, the tenant creation does not wait for a response from the microservice. |
|
No |
URL |
Define the URL of the custom microservice that should be asynchronously called after deleting a tenant to remove additional custom settings. |
|
No |
List of ISO language terms e.g. |
Defines which languages a user can select in the login dialogue of Keycloak. The default locales are en for English and de for German. Find more available locales in the Keycloak documentation. |
|
No |
ISO language term, e.g., |
Determines the language of the invitation e-mails that will be sent to each user created during the tenant creation. |
|
No |
List of URIs, e.g. |
URIs used in Keycloak Client creation to set Valid redirect URIs. Default URI (baseURL+"/*") will always be added to this list, only use this to set additional redirect URIs |
|
|||
|
No |
JSON mapping |
Set theming parameters as described in the Keycloak documentation. Example:
|
|
If using e-mail |
URL |
The SMTP server to be configured in the Keycloak realm (e.g., for sending invitation e-mails). |
|
No |
Integer |
The port of the SMTP server. Default is 25. |
|
No |
String |
The display name of the e-mail sender for administrative emails. |
|
If using e-mail |
eMail address |
The sender of the administrative e-mails. |
|
No |
Boolean |
Determines if SSL is enabled (true) or disabled (false). Default is false. |
|
No |
Boolean |
Determines if TLS is enabled (true) or disabled (false). Default is false. |
|
No |
Boolean |
Determines if the SMTP server requires authentication. |
|
If using e-mail with authentication |
String |
The user name for authentication against the SMTP server. |
|
If using e-mail with with authentication |
String |
The password for authentication against the SMTP server. |
|
No |
List of key value pairs with the following parameters. |
Section that allows to add custom roles (in addition to the pre-defined role set) which will be available within each new tenant. The roles are specified by their name and a description. |
|
No |
String |
The name of a role to be added to the tenant. The following roles are created per tenant by default:
|
|
No |
String |
The description of a role to be added to the tenant. |
|
No |
As of 2021 Autumn, not yet supported by yuuvis® architect. |
Specify groups that will be created in the tenant with the listed roles assigned to them. |
|
If additional users shall be created |
List of key value pairs with the following parameters. |
If a tenant is created via Tenant Management API, a first user admin is always included. Here you can define additional initial users that will be set up in each tenant created. For each of them, the following configuration parameters are available. |
|
If additional user is to be created |
String |
The user name of the user to be created. |
|
If additional user is to be created, with e-mail invitation |
String |
The e-mail address of the user to be created. |
|
No |
String |
The first name of the user to be created. |
|
No |
String |
The last name of the user to be created. |
|
No |
List of Strings |
The list of roles the user should be assigned to. |
|
If additional user is to be created, without e-mail invitation |
String |
The user password of the user to be created. It will be stored encrypted. Not necessary when inviting users via e-mail. Note: The password policy must be met, see corresponding description of this tenant management API endpoint: POST /tenant-management/api/system/tenants |
|
Boolean |
Enable ( |
|
|
Boolean |
If you want to set up technical users that should not be forced to change their passwords while logging in for the first time, set false. The default is true. |
|
|
Boolean |
Determines if new users should be invited via e-mail. If The default value is |
Profile Structure
The following code block shows an example profile.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{
"general":{
"displayNameHTML": "<div class=\"yuv-brand-logo\">${DISPLAY_TENANT_NAME}</div>",
"customMicroservice": "https://myCustomMicroserviceURL",
"supportedLocales": ["en","de","es"],
"defaultLocale": "es"
},
"client": {
"redirectUris": [ "https://example.com/*" ]
},
"email": {
"host": "myemailservice.com",
"port": 25,
"fromDisplayName": "mySenderShowName",
"from": "my.sender@address.tld",
"enableSSL": true,
"enableStartTLS": true,
"enableAuthentication": true,
"username": "emailserviceuser",
"password": "PaswordWith8Characters1Uppercase1SpecialNoUserName"
},
"roles": [
{
"role": "Role 1",
"description": "Description of Role 1"
}, ...
],
"user": {
"users": [
{
"username": "yauser",
"email": "yauser@example.tld",
"firstName": "yaFirstName",
"lastName": "yaLastName",
"roles": ["YUUVIS_DEFAULT"],
"password": "PasswordWith8Characters1Uppercase1SpecialNoUserName",
"temporaryPassword": false,
"enabled": true
},
...
],
"withInvitation": true
}
}
5.1.3. User Management via Endpoints
The Tenant Management API provided by the tenant-management
service offers endpoints for user management via Keycloak. In order to scale the identity management, the keycloak-proxy
service can be used for the connection of multiple Keycloak instances. The endpoints of the Tenant Management API are called by the architect
services.
This article describes the handling and representation formats of data for individual user accounts as retrieved and expected by the Tenant Management Endpoints.
Further functionality is provided by our userservice
.
User Management Endpoints
The following endpoints of the Tenant Management API are available for User Management purposes:
Endpoints | Required User Role in Default Configuration | Purpose |
---|---|---|
|
|
operations on any tenant in the system |
|
|
operations on the own tenant |
|
The endpoints are available for every logged-in user. |
operations on the own tenant |
All endpoints for user management via the Tenant Management API are available via the Swagger UI: https://<host>/tenant-management/swagger-ui.html
.
The POST and PUT endpoints allow for the deactivation of users. In object histories, the user names of deactivated users are still displayed. In the client framework components, these usernames are still reserved by the Web API Gateway as the users still exist in the corresponding tenant. In order to reuse the user name of a deactivated user for a new user, you may append -disabled to the original user name. Thus, the deactivated user can still be identified in the object history and the user name can be reused at the same time.
5.1.4. User Account Properties
The following properties for user accounts can be managed via the Tenant Management API.
Property | Type | in Creation Request Bodies | in Update Request Bodies | in Response Bodies | Description |
---|---|---|---|---|---|
|
string |
Ignored. |
Ignored. |
Included. |
The ID of the user for identification in the identity management system and in yuuvis® Momentum. |
|
string |
Required if invitation via e-mail is desired. |
Optional, unchanged if not specified. |
Included if available. |
The e-mail address of the user. |
|
string |
Optional. |
Optional, unchanged if not specified. |
Included if available. |
The first name of the user. |
|
string |
Optional. |
Optional, unchanged if not specified. |
Included if available. |
The last name of the user. |
|
list of string role names |
Optional. |
Optional, unchanged if not specified. Note that changes can also be applied by assigning/removing groups. |
Included if available. Includes roles assigned via groups if available. |
A list of roles defined in the identity management system that are assigned to the user. |
|
list of string group names |
Optional. |
Optional, removed from data set if not specified. |
Included if available. |
A list of groups defined in the identity management system in which the assigned user is a member. |
|
string |
Required. |
Optional, unchanged if not specified. |
Included. |
The user name of the user. |
|
boolean |
Optional, default: |
Optional, unchanged if not specified. |
Included. |
Specifies whether the user is allowed to log in ( |
|
unix time stamp |
Ignored. |
Ignored. |
Included. |
Date and time of user creation in the identity provider. |
5.1.5. User Account Data Sets
For each user account represented in a request or response body, its properties are specified in JSON format. The order of the individual properties within one data set is arbitrary.
The following code block shows an example for a result list including the data sets of several user accounts. Such result list can be retrieved, e.g., by the GET /tenant-management/api/idm/users
endpoint.
[
{
"id": "406b5a28-7a8b-4c36-a569-df7bff480375",
"firstName": "Heinrich",
"lastName": "Schuetzel",
"roles": [
"YUUVIS_SYSTEM_INTEGRATOR",
"YUUVIS_DEFAULT",
"YUUVIS_TENANT_ADMIN",
"HR_MANAGER",
"YUUVIS_CREATE_OBJECT",
"YUUVIS_MANAGE_SETTINGS"
],
"username": "newuser5",
"enabled": true,
"createdTimestamp": 1622122631393
},
{
"id": "320c67d0-b88b-4e99-852a-b938f4b38cd7",
"email": "kammer@segelreisen.de",
"firstName": "Hannes",
"lastName": "Kammer",
"roles": [
"YUUVIS_SYSTEM_INTEGRATOR",
"YUUVIS_DEFAULT",
"YUUVIS_TENANT_ADMIN",
"YUUVIS_CREATE_OBJECT",
"YUUVIS_MANAGE_SETTINGS",
"YUUVIS_AI_PIPELINE",
"COMPLIANCE_MANAGER",
"YUUVIS_AI_PREDICT"
],
"groups": [
"onlyoffice"
],
"username": "kammer",
"enabled": true,
"createdTimestamp": 1591957723730
},
{
"id": "a6f5e1aa-ff42-4140-b9ec-5de4cc61f1a9",
"email": "schwimmer@segelreisen.de",
"firstName": "Klaus",
"lastName": "Schwimmer",
"roles": [
"YUUVIS_SYSTEM_INTEGRATOR",
"YUUVIS_DEFAULT",
"INVOICE_MANAGER",
"YUUVIS_TENANT_ADMIN",
"HR_MANAGER",
"YUUVIS_AIINVOICE",
"EMAIL_WITHOUT_ACL",
"QA_MEMBER_AREA2",
"uma_authorization",
"YUUVIS_CREATE_OBJECT",
"TEAMS_MANAGER",
"PHOTOARCHIVE_MANAGER",
"YUUVIS_MANAGE_SETTINGS",
"QA_MANAGER",
"ACL_ALL_USERS",
"YUUVIS_AI_PIPELINE",
"QA_MEMBER_AREA1",
"COMPLIANCE_MANAGER",
"YUUVIS_AI_PREDICT",
"offline_access"
],
"username": "klaus",
"enabled": true,
"createdTimestamp": 1606820894094
}
]
5.1.6. Configuration
Working with Keycloak
-
First, create an initial Keycloak realm. Then create a user with the YUUVS_SYSTEM_INTEGRATOR role within this realm.
-
Users calling endpoints of the system controller need the YUUVIS_SYSTEM_INTEGRATOR role.
-
Users calling endpoints of the admin controller need the YUUVIS_TENANT_ADMIN role and must be a member of the Keycloak realm that is created when creating a yuuvis® Momentum tenant.
-
Before creating the first tenant, the profile has to be saved via POST /tenant-management/api/system/profile by a user with the YUUVS_SYSTEM_INTEGRATOR role.
Working with any Identity Provider via OAuth2
As of 2022 Spring, the service can be configured such that the idm-controller endpoints retrieve their information from a custom IDM proxy. This proxy can be used to connect other identity providers than Keycloak for reading purposes. An example proxy service is available as a beta version on request.
Note: If the service is not combined with Keycloak, all endpoints not belonging to the idm-controller are not available and return a 404 error.
In order to connect such a custom IDM proxy, create a tenant-management-prod.yml
configuration file with the following parameters:
idm:
custom:
enabled: true
base-url: http://IDM_HOST:port
The handling of profile-related configuration files is described for the core system.
5.2. yuuvis® architect
yuuvis® architect provides a support tool with a graphical user interface for client administrators. Based on the framework library, metadata forms of their client’s graphical user interface can be modeled. Furthermore, users can be added or removed from the respective tenant and language settings can be customized.
After installing the client services, yuuvis® architect can be accessed via the following URL: https://<domain>/architect
.
yuuvis® architect works with the default roles.
5.2.1. Dashboard and Menus
The yuuvis® architect dashboard shows the most important application information at a glance.
Header Area
In the header area, you will find the yuuvis® Momentum bar with icons for the most frequently used features, such as the main menu icon and the yuuvis® icon on the left, and the settings menu icon with the current user’s initials on the right. Click the icons to go to the corresponding linked areas.
As of version 2021 Autumn: If you have the role YUUVIS_MULTI_TENANT, you will find Switch tenant in the drop down menu after clicking the settings menu icon. Click this option to log out from the current tenant and log in to a different tenant.
Whenever you left-click the yuuvis® icon, the dashboard will appear again.
If you left-click the yuuvis® icon while pressing Ctrl, a new tab will open with another yuuvis® architect dashboard in your browser.
Middle Area
In the middle of the dashboard, you will find tiles for the different views of yuuvis® architect. Click a tile to open one of them.
The Main Menu
Via the main menu you can access important areas and features such as the dashboard and the settings menu. You can access the main menu using the main menu icon on the yuuvis® Momentum bar.
You can access the following areas via the main menu:
-
Dashboard: Open the dashboard of yuuvis® Momentum client.
-
Localization: Open the localization customizing view.
-
Form modeling: Open the form modeling view.
-
User management: Open the user management view.
-
Settings: Open the settings menu, where you can configure the language settings and yuuvis® architect’s appearance.
-
About yuuvis® architect: This area provides you with information on the software manufacturer and versions. The licenses of the software components used are displayed in the Licensing notes area.
The Settings Menu
Use the settings menu to configure the settings of your yuuvis® architect. Open the settings menu by clicking the settings icon in the header area and select Settings from the dropdown menu. Alternatively, you can also open the settings menu via the main menu.
The following information and configuration settings are available in the settings menu:
-
Language: You can use the buttons to control the language display of the general user interface elements and the object types, menus, fields, and catalogs displayed in your yuuvis® architect session.
-
Roles: The drop-down menu indicates the user roles that were assigned to you. User roles and group access rights to object types and program functions are explained here.
-
Layout: In the Layout settings area, you can customize the design of the yuuvis® architect appearance to your personal preferences. Here, you can choose between a light and a dark theme, set an accent color, and upload a background image for yuuvis® architect. These settings are stored on your device, meaning you can work on different devices with different designs.
You can also reuse the layout settings in your client by clicking the Export button. Similarly, you can transfer the layout settings from other clients to yours by clicking the Import button. Click the Reset button to delete all of your individual layout settings in your yuuvis® architect.
-
Configuration: In the Cache settings area, you can empty the application cache of your device by clicking the button. Tick or untick the checkboxes to determine whether the entire cache should be emptied or only certain data, such as the system cache or layout settings, should be deleted. The deletion is device-dependent. This means that only the settings of the device on which the deletion is performed are reset.
-
System: Reloads all system configurations, such as the schema. If the schema was modified, the updated version will be imported in yuuvis® architect.
-
Layout: Resets the area width in the different views and the column width, for example, for the technical names list in the localization view.
-
5.2.2. Rights and Roles
Rights management in yuuvis® architect is based on the default roles. It is not yet possible to configure yuuvis® architect to enable access via custom roles.
Depending on the description of the position and tasks, employees work with different data, functions, and tools. User rights for access to data, functions, and applications in accordance with the employees’ fields of duties and responsibility are grouped into roles in the client application and yuuvis® architect. In this way, users with the same fields of duties and responsibility also have the same rights in the system.
Users can view the roles assigned them via their settings.
Roles for Users and Administrators
The following roles can be assigned to users of yuuvis® Momentum client as reference implementation and yuuvis® architect in order to manage their permissions. Users can view the roles assigned to them in the settings menu.
Role | Permissions in yuuvis® Momentum client as reference implementation | Permissions in yuuvis® architect |
---|---|---|
|
Users have full access to all objects. |
no impact |
|
Users are allowed to customize the global standard configurations for hit lists and filters in the settings menu. Those standards will be the default settings for (new) users that have not saved their own user-specific standard configurations so far. |
As of 2022 Autumn, users can manage other users of their own tenant but cannot assign the roles |
|
Administrative object information is provided to users in the metadata forms of any object in the system. |
Users can modify metadata forms in the metadata aspect area for any object type defined in the global system schema or in an app-specific schema. Users can customize the localization of the labels associated with object types defined in the global system schema or in an app-specific schema. Users can add or delete users of their own tenant and assign roles to them. |
|
Administrative object information is provided to users in the metadata forms of any object in the system. |
Users can modify metadata forms in the metadata aspect area for any object type defined in the tenant-specific schema. Users can customize the localization of the labels associated with object types defined in the tenant-specific schema. Users can add or delete users of their own tenant and assign roles to them. |
|
Users with accounts in multiple tenants can easily switch between their tenants via Switch tenant instead of a conventional logout. |
Users with accounts in multiple tenants can easily switch between their tenants via Switch tenant instead of a conventional logout. |
Custom Roles
The roles listed above are provided as default for yuuvis® Momentum client as reference implementation and yuuvis® architect. yuuvis® Momentum allows for the definition of custom roles as well. But be aware that you will not be able to use yuuvis® architect. Instead, you can build your own administrative tool based on the API-WEB Service (Web-API Gateway).
5.2.3. Object Types
Any business object handled in your client has an object type. The available object types are defined in the yuuvis® Momentum schema as document, folder or secondary object type. This article gives an introduction into the basics of the yuuvis® Momentum schema and the particularities for yuuvis® Momentum client and yuuvis® architect.
The yuuvis® Momentum Schema
yuuvis® Momentum uses schemata to ensure a valid and consistent data structure for the metadata of stored business objects. The metadata consists of properties. Some predefined system properties are automatically assigned to all objects during their creation. Further properties can be defined in a schema.
The individual properties can be referenced in object type definitions. If you create a business object, you will select one of those object types. It determines the set of properties that will be available for business objects.
Schemata are configuration files containing property and object type definitions.
-
All tenants can refer to the global system schema.
→ yuuvis® architect allows its management only for users with the
YUUVIS_SYSTEM_INTEGRATOR
role. -
Additionally, each tenant can configure an own tenant schema. All properties and object types defined in a tenant schema are not available in other tenants.
→ yuuvis® architect allows its management for users with the
YUUVIS_TENANT_ADMIN
role. -
An app schema contains property and object type definitions that will be available in all tenants for which the concrete app is enabled.
→ yuuvis® architect allows its management only for users with the YUUVIS_SYSTEM_INTEGRATOR role.
The roles used by yuuvis® architect are not defined in the schema but in a tool-specific role set. This role set is also the default library-based clients. However, yuuvis® Momentum allows you to define your own role set. If you do so, you will not be able to use yuuvis® architect. |
Floating Secondary Object Types in yuuvis® architect
In contrast to SSOTs, FSOTs can be handled in a flexible way during the import or at runtime for already existing documents or folders with an update. The concept of FSOTs fits the import behavior where files are imported as documents of a general document object type with no or only a few defined metadata properties. After creation, a classification job analyses the document and assigns specific FSOTs to that document providing the typical properties of a specific business object like an invoice, a delivery note, an order, etc.
In order to be able to assign an FSOT, it has to be referenced as floating in the corresponding document (or folder) object type definition.
An FSOT must not be referenced by more than one object type to assure valid form modeling. |
The operating principle of yuuvis® architect is based on a classification of the SOTs. FSOTs referenced in a document or folder object type definition can be given a classification appClient:primary
or appClient:required
.
Classification 'primary'
With respect to the above-mentioned import process, the user can specify business types for an object manually by means of assigning an FSOT. Here, you can only choose a primary-classified floating secondary object type (PFSOT), characterized by the appClient:primary
classification. All of them need to be referenced as floating in the corresponding object type definition in the schema. After importing an object with the general object type, exactly one of those PFSOTs can be selected. Thus, the business type of the object will be determined by assigning its metadata: a specific business type name like invoice, order, etc. and a corresponding description.
During runtime, only one PFSOT can be assigned to an instantiated object.
Whenever one of the referenced PFSOTs is assigned, all RFSOTs referenced in the same object type definition are assigned at the same time.
Classification 'required'
Business objects may need more metadata properties than provided by the initial general object type together with the user-selected PFSOT. With the classification appClient:required
, the required-classified floating secondary object types (RFSOTs) are defined. Their metadata properties are assigned automatically together with the assignment of any PFSOT if they are referenced in the same document or folder object type definition. The assignment of multiple RFSOTs is allowed.
Extending Types without Classification
In the schema, SOTs can be defined without any classification appClient:primary
or appClient:required
. Nevertheless, they can be referenced as FSOTs in an object type definition. Thus, they allow for the user to assign additional metadata independently of other SOTs. They can also be assigned or removed later on if necessary. Examples are general address data, e-mail address data, and approval process attributes.
Types for Business Objects
Any business object in the yuuvis® system needs an object type – either a document or a folder object type. The document or folder object type can reference SSOTs. Thus, any instance of the document or folder object type is provided with a set of metadata coming from the final object type definition and a set of metadata coming from the referenced SSOT.
The assignment of a PFSOT makes an object appear with a specific business pseudo-type determined by the properties of the PFSOT. Since all referenced RFSOTs are assigned at the same time, the object now has a fixed set of metadata containing the properties of the original general object type from the creation, of the assigned PFSOT and of the assigned RFSOTs. This set of metadata will be the same for any object to which the corresponding PFSOT is assigned. Thus, you can consider them as pseudo-types you can choose for your business objects. They are identified by the title property of the PFSOTs.
Instantiated documents or folders of both categories can be extended at runtime by assigning extending FSOTs.
Tags
Tags make it possible to flag the current state of an instantiated object within a process chain in the backend.
In order to display their values in your client, they need to be introduced into your schema as well. Indeed, they are introduced in a specific object type definition. Their names and expected values are set in this definition.
So once introduced, the name and expected values of a tag will appear as technical names in the localization view for users who have the permission to manage the comprising object type.
5.2.4. Localization
The Localization tile is available on the dashboard for users with the YUUVIS_TENANT_ADMIN or YUUVIS_SYSTEM_INTEGRATOR roles.
In your client, forms are used to present the properties of your business objects. yuuvis® architect allows you to customize the labels of the individual property fields and thus replace technical names in the forms, filters and hit list columns.
The structure of the metadata forms for the client cannot be customized via localization, but by means of the Form Modeling view of yuuvis® architect.
Customizing Labels
yuuvis® Momentum client reference implementation includes a default label configuration for the languages English and German. Any technical name you may have defined additionally will have no corresponding language-specific label. If you select a language other than English or German, no labels are predefined at all. In your client, the technical names will be displayed instead.
The following instructions will help you to either customize the default labels or define your own labels.
-
Click the Localization tile to open the view for the label customizing. Alternatively, click the menu button on the top left and select Localization.
-
Select one or two languages on the right side of the top bar.
-
Find a list with the columns Technical name, and for each language Label and Description. All technical names are displayed that correspond to a specific property field available in your client and that are enabled for customizing based on your roles.
-
Add or edit labels and/or descriptions in your language for any technical name in the list. The description is used to group object types in the Create object and Restrict to object types dialogs. Object types with the same description are displayed in the same group.
-
Save your changes or Reset to the last saved configuration and discard all changes.
-
Sort the list by a column by clicking its header. Clicking the column header repeatedly will invert the sort direction.
-
Find a tree of object types in the Filter technical names by: area on the left next to the list. The structure represents the schema structure and contains all types of business objects and extending types you are allowed to customize. Additionally, the # Tags filter provides all technical names identifying names and values of process tags that you are allowed to customize.
-
Click on a node or leaf in the tree to limit the listed technical names by showing only the technical names associated with the selected filter.
-
Click repeatedly on the same filter to remove it and display the entire list of technical names.
New technical names cannot be added in the localization view of yuuvis® architect. They appear automatically in the list after applying changes to the metadata structure directly via the schema or via the Form Modeling view of yuuvis® architect.
The technical names are automatically extracted from the active schema definition. If new definitions are added, the corresponding technical names will appear in the list of available technical names. However with the version 2020 Winter of yuuvis® architect, if schema definitions are deleted, the technical names are not removed from the localizations list. So far, it is not possible to delete the corresponding localization entries that have been saved before. This feature will be available as of version 2021 Summer. |
Customizing Language Files
As of version 2021 Summer, the labels can be localized alternatively via language files. To change the language file you have two options: a) make changes online in your browser or b) download the language file, make changes offline and upload the edited file to the server.
a) Online editing
-
To change a label or description for an object type, double-click on the corresponding field and enter your change. Click Save to save your change or Reset to reset.
b) Offline editing
-
Download the language file for the selected language by clicking the corresponding Export icon on the right side of the title bar.
-
Modify the file locally in an editor of your choice.
-
If you want to reuse the file for a different language, rename it consistent with the convention <ISO>.json, e.g., fr.json for French.
-
If you want to reuse the file for a different tenant, the prefixes of tenant-specific labels have to be adjusted.
-
Upload your custom language file by clicking the corresponding Datei, laden Symbol Import icon on the right side of the title bar and selecting the file from the Explorer window.
-
After you have selected the language file, the Import validation dialog opens in which you can check your changes before uploading them. In the left column of the Import validation dialog, the technical names of all object types that have been added to the language file are displayed. In the right column of the Import validation dialog, the technical names of all object types that have been deleted from the language file are displayed. If only the labels and descriptions of object types have been changed, but no technical names, the left column of the Import validation dialog will remain empty.
-
Click OK to upload your local language file to the server.
-
To complete the offline editing, click Save. The values on the server will then be overwritten by the values from your local language file.
yuuvis® Momentum library-based clients support a number of languages.
Sublocales, like German for Switzerland (de-CH), are not supported in yuuvis® architect. |
5.2.5. Form Modeling
The Form modeling tile is available on the dashboard for users with the YUUVIS_TENANT_ADMIN or YUUVIS_SYSTEM_INTEGRATOR roles.
You can model the Metadata aspect area in CREATE and EDIT forms that are offered in your client to view and edit metadata. It also possible to combine the form modeling with situation-specific scripts. To check the current layout during modeling, yuuvis® architect provides a form preview presenting the modeled metadata form as it will appear in your client.
The labels displayed in the metadata forms for the client cannot be customized in the form modeler, but by means of the Localization view in yuuvis® architect.
Modeling Forms for Metadata
In your client, the properties of your business objects are presented in different aspect areas. The properties provided by document an folder object types themselves are displayed in the summary aspect area that cannot be customized in yuuvis® architect. However, the properties provided by assigned secondary object types are displayed in the metadata aspect area which can indeed be customized. For each type of your business objects, you can customize separate forms in yuuvis® architect for the Create and Edit working scenarios. For example, you can hide fields from an edit form that are only necessary to create an object. The corresponding form is provided to the user in yuuvis® client accordingly.
You can use default forms if you do not want to create custom forms. These forms are generally sufficient for technical data transfers.
Depending on your roles, you have different permissions. You can model only the metadata forms for which you are authorized by your roles. With the YUUVIS_TENANT_ADMIN role only object types defined in the tenant schema will appear in the architect. With the YUUVIS_SYSTEM_INTEGRATOR role only object types defined in the global system and app schema will appear in the architect.
In general, metadata aspect area forms consist of a form model with arranged groups of fields and optionally a script for manipulating field values. The following instructions will help you to customize the forms displaying metadata in your client for the edit and create situations.
-
Click the Form modeling tile to open the form modeling view. Alternatively, click the menu button on the top left and select Form modeling.
-
In the column Select object type, find a tree to navigate through all object types for which you have the permission to model the metadata forms. In this view, you cannot distinguish pseudo-types determined by primary-classified floating secondary object types from document (or forlder) object types.
Node Content Required Role Application
Further nodes are displayed, each of them corresponds to one specific application with its own app schema.
Each node contains types defined in the specific app-schema:
-
Document and folder object types.
-
Pseudo-types determined by a primary-classified floating secondary object type.
YUUVIS_SYSTEM_INTEGRATOR
Extending Types
Floating secondary object types without the classification primary or required defined in
-
the system schema,
-
the app schema or
-
the own tenant schema.
For system and app schema: YUUVIS_SYSTEM_INTEGRATOR
For tenant schema: YUUVIS_TENANT_ADMIN
System
Types defined in the system schema:
-
Document and folder object types.
-
Pseudo-types determined by a primary-classified floating secondary object type.
YUUVIS_SYSTEM_INTEGRATOR
Tenant
Types defined in the own tenant schema:
-
Document and folder object types.
-
Pseudo-types determined by a primary-classified floating secondary object type.
YUUVIS_TENANT_ADMIN
-
-
Click either EDIT in order to customize the edit form or CREATE in order to customize the create form displayed in your client. In case you have saved a model for the EDIT situation but not the CREATE situation, you are asked whether to reuse the EDIT model for CREATE.
The browser window is now divided in 3 areas: On the left a building set area, the Model tree and the Layout area. After clicking on a field in the Model tree or Layout area, an additional Properties area is opened on the right-hand side.
Building Set Area
The left-hand area shows the selected type and the form situation (EDIT or CREATE) you are currently modifying. Below, you can find a list of all available elements you can use to build your metadata aspect area form. On the top, there are two structuring elements: Group and GroupStack. Below, metadata properties are listed that are always assigned to the selected object type via secondary object types. All these properties will be assigned to each object of this business object type, independently of the form of presentation.
The properties are characterized by their names that are displayed in the form, by their data types in italic (-string-, -boolean- etc.) and by their schema-intern property IDs in lower-case letters below.
If a property is displayed in grey letters, it is already part of the metadata form for your client.
If a property is displayed in white letters, it is currently not part of your form presenting the metadata in your client. You can drag and drop the property into the Model tree area.
Properties provided by the document or folder object type itself are not available for form modeling. However, they are always assigned to all instances of the corresponding object type and are provided in the Summary aspect area in the client. |
Model Tree Area
In this area you define the structure of your metadata aspect area form. By means of drag and drop, you add elements from the building set on the left. You can arrange the form elements using drag and drop to design groups and GroupStacks of properties. Click x to delete unwanted GroupStacks, Groups, and properties from the form. Properties, groups and GroupStacks can be rearranged by drag and drop within a form.
By default, form layouts are organized into a Main Area for the most important metadata and a Data Area. This layout structure is optional. You may only use the Main Area. Later in time, the Data Area should be used for grouping the metadata in the Summary aspect of the object details in yuuvis® Momentum client.
All Groups and GroupStacks in the model tree can be collapsed or expanded for a better overview.
You can use the Import and Export buttons in order to download your form model as JSON file and import it again later on. The file can only be used for the specific object type. During import, the file is validated and specific errors are reported.
The Clear model button removes all properties from the Model tree together with allmost all Groups and GroupStacks. Only the Main Area Group and the Data Area GroupStack remain.
Click Save to save your form and apply it to your client.
Group:
-
Groups combine properties and group them visually. Properties whose contents are related, can thus be logically combined (e.g., a person’s name, contact details, and postal address, etc.) like in an address book entry. The corresponding fields in the form are visually grouped by means of background color and layout.
-
Elements within a group are arranged vertically by default. In order to arrange them horizontally, go to the Properties area and select Row instead of Column.
-
For example, you can arrange a person’s first and last name next to each other in the first row in an address book entry and place the contact details below in a block with full lines.
-
In the Properties area, you can give groups a unique technical name for identification. This technical name is required in order to display a label for the Group in your form. Customize the labels via Localization. If not specified in the corresponding localization configuration, the technical name will be displayed in the metadata form.
GroupStack:
-
GroupsStacks combine several groups. Groups combined via GroupStack are shown as tabs within the GroupStack area. The name of the Groups in a GroupStack is shown as title of the tabs.
-
The Data Area is per default an empty GroupStack. Thus, no property fields can be arranged here outside of groups.
Layout Area
In this area you can see the properties as fields displayed in their Groups and GroupStacks. The arrangement corresponds to the structure defined in the Model tree. If you select an element in the Model tree, it will be highlighted in the Layout. The highlighting of elements within a GroupStack will be visible only if the corresponding tab is selected.
The Layout area displays an overview of the structure and does not distinguish between arrangement in rows or columns.
Via Open form preview you can have a look at your model to see what it will look like in your client.
Via Open script you can open a scripting window providing further form modeling possibilities. Thus, yuuvis® architect makes it possible to assign situation-specific scripts to the current form. As a scripting support, IntelliSense is available: Click Copy to clipboard in the left corner to select a technical field name. Add the selected string surrounded with the correct syntax to your script at the position of your cursor via Ctrl+V.
Properties Area
After clicking any element in the Model tree or Layout area, an additional Properties area is opened on the right-hand side. Information on the selected element is provided here.
On the top, the name and element type are displayed in a first block.
The second block below differs for different types of elements:
-
For a single property field, you can tick or untick the checkbox Read-only in order to define the behavior in the client. For a string property, you can modify the number of Lines that will be provided for the property field in the client.
Under Schema, you can see the attributes of the schema property definition for the selected property.
-
For a table property, you see a Read-only checkbox together with the Schema attributes of the property definition, too. Additionally, an overview of the available columns is provided. They are named with their technical names and their types (string etc.). By clicking one of them, you can define for each individual column the number of Lines for each entry and for the entries to be Read-only or not. By drag and drop, you can change the order of the columns or move them between Columns used and Columns not used. Thus, you can include or exclude columns from the metadata form.
-
For a Group, you can select either Row or Column as Layout for the arrangement of the included property fields. Except for the Main Area, you can define a unique technical name for the identification of the Group. This technical name is required in order to display a label for the Group in your form. Customize the labels via Localization.
-
For a GroupStack, no second information block is displayed.
5.2.6. User Management
Users with the YUUVIS_MANAGE_SETTINGS
or YUUVIS_TENANT_ADMIN
or YUUVIS_SYSTEM_INTEGRATOR
roles see the User management tile on the dashboard.
This view of yuuvis® architect provides a graphical interface for administrative users in order to manage users belonging to their tenant. Individual users can be edited or deleted and users can be added. New users will be invited via e-mail to set up their passwords.
The functionality is provided by the admin endpoints of the Tenant Management API.
List of Users
A click on the User management tile on the Dashboard opens a new state that lists all users of your client belonging to your own tenant. Each row corresponds to one user. The list is displayed with the following columns:
Column name | Description |
---|---|
Active |
Ticked users are activated and can log in. An unticked and thus deactivated user will not be able to log in. |
User name |
User name for the login of the user. The field is mandatory. |
First name |
First name of the user. |
Last name |
Last name of the user. |
E-mail address of the user. By clicking the entry, a new e-mail will be opened in your local e-mail client with the specified e-mail address as recipient. |
|
Roles |
The roles assigned to the user. You can add or remove roles. |
ID |
Unique user ID automatically set by the yuuvis® Momentum system. |
Sort the list by a column by clicking its header. Clicking the column header repeatedly will invert the sort direction.
Filter the list by clicking the icon in any column header and typing your search term.
Adding New Users
In order to add a new user to your tenant, click the Add user button on the right in the top bar. The New user area will open and display a blank form asking for the data of the user to be added. Mandatory fields are User name, E-mail and Roles, where you can select one or several of the roles provided in the dropdown catalog. By clicking the letter icon in the E-Mail field, a new e-mail will be opened in your local e-mail client with the specified e-mail address as recipient.
Click Save to add the user to your tenant.
The user will receive an invitation e-mail guiding them to the registration page. The invitation is valid for 12 hours.
Editing User Data
In the list of users, click on the row of the user for which you want to edit the data. The Properties area will open with the data of the selected row arranged in a form. You can edit the values for First name, Last name and E-Mail, assign additional roles or remove roles, and activate or deactivate the user via the Active checkbox. The user’s password is not displayed and can only be changed by the corresponding user.
Click Save to apply your changes. The data of the user will be updated in the list.
Deleting Users
In the list of users, click on the row of the user you want to delete. The Properties area will open where you can find the Delete button. Confirm with OK in the pop-up window. The user will be removed from the list.
5.2.7. Catalog Management
The Catalog management tile is available on the dashboard for users with the YUUVIS_TENANT_ADMIN
or YUUVIS_SYSTEM_INTEGRATOR
roles.
Selection lists with pre-defined entries can be used in forms for the properties of your business objects in your client. These selection lists are provided by so-called dynamic catalogs of the Web-API Gateway. Thus, yuuvis® architect allows you to create and modify dynamic catalogs leading to changes in the selection lists displayed in your client.
Dynamic Catalogs
Users with the YUUVIS_TENANT_ADMIN
role can create and edit tenant-specific catalogs and set them to Read-only. Catalogs that are set to Read-only implement non-editable selection lists in your client.
Additionally, tenant administrators can create a tenant-specific copy of global or app-specific catalogs that are not set to Read-only. Each copy can be managed as a tenant-specific catalog. Your client will display the selection list configured in the tenant-specific copy of the global catalog. Changes of the original global catalog do not affect the tenant-specific copy and thus also not the selection list displayed in your client.
Users with the YUUVIS_SYSTEM_INTEGRATOR
role can create and edit global and app-specific catalogs that are available in every tenant and set them to Read-only
. Global or app-specific catalogs that are set to Read-only
cannot be copied to a tenant-specific resource.
Start managing catalogs as follows:
-
Click the Catalog management tile to open the catalog management view. Alternatively, click the menu button on the top left and select Catalog management.
-
In the Catalogs column on the left, find a tree to navigate though all catalogs available for users of your tenant. Catalogs under System and App are available in each tenant whereas catalogs under Tenant are available only for users within the corresponding tenant.
-
You can either edit existing catalogs or create new catalogs.
Editing Catalogs
The following instructions will help you to customize the selection lists in your client by managing the catalogs.
-
Select a catalog. A new area is opened displaying the data for the selected catalog.
-
If you have the appropriate permissions, you can edit the catalog and its entries.
-
As a YUUVIS_TENANT_ADMIN you cannot edit global or app-specific catalogs. Instead, the Create tenant copy button allows you to copy the catalog to your tenant resource and edit it as a tenant-specific catalog.
-
Edit the catalog:
-
Decide whether the catalog should be Read-only or not by ticking or not ticking the checkbox.
-
Specify values for the catalog that will be the entries available in the selection list in your client. Enter each of them in the field New entry and confirm with Add. The values cannot be localized.
-
Disable a value by unticking its checkbox.
-
Delete a value by clicking the x icon.
-
Check the Preview sub-area on the right and see what the selection list will look like in your client.
-
-
Save the modified catalog.
Creating Catalogs
The following instructions will help you to create a new selection list in your client by creating a catalog.
-
You can create catalogs in each resource where you can see a + icon behind the name of the node in the tree. Users with the
YUUVIS_SYSTEM_INTEGRATOR
role will see a + icon behind the System node and behind the individual child nodes of App. Users with theYUUVIS_TENANT_ADMIN
role will see the + icon next to their tenant’s node. -
Click the + icon next to the node where you want to create the new catalog. The New catalog area will be opened.
-
Enter the technical name for your catalog in the Catalog name field. You can localize it afterwards via Localization.
-
Use the editing options described above.
-
Save the catalog.
5.2.8. Schema Management
Beta Version
As of yuuvis® Momentum release 2022 Summer, the Schema management is available as a beta version.
|
The Schema management tile is available on the dashboard for users with the YUUVIS_TENANT_ADMIN
or YUUVIS_SYSTEM_INTEGRATOR
roles.
You can use this graphical user interface provided by yuuvis® architect to define object types and their properties for the business objects in your client application. The object types and properties are defined in schema structures.
Depending on the roles assigned to the currently logged-in user, it is possible to manage the global schema, app schemata and/or tenant schemata as described below.
The schema management provided by yuuvis® architect uses the corresponding endpoints provided by the Core API and the Web-API Gateway.
The structure of the metadata forms that present the properties of your business objects in your client can be customized by means of the Form Modeling view of yuuvis® architect.
Before you start working on your schemata, it is important to define how the available types of schemata as well as properties and object types will best depict your business use case. Especially as a system integrator with access to the global schema as well as to all tenant and app schemata, you are responsible for the creation and management of a complex configuration with multiple schemata that can refer to each other. With this definition in mind, you can create and edit your schemata. |
Selecting/Creating a Schema
Select the schema file you want to read or edit from the Schema selection list on the left side of the Schema management view of yuuvis® architect. Depending on your role, you have read and/or edit permissions:
Icon | Scope | Required Roles for Read Access | Required Role for Edit Actions |
---|---|---|---|
system |
|
YUUVIS_SYSTEM_INTEGRATOR |
|
app |
|
|
|
tenant |
|
|
The namespace of the individual schemata indicates their concrete scope: either the entire system, a specific app or a specific tenant.
To create a new app schema, use the endpoint POST /api/system/apps/{app}/schema .
|
As of 2022 Autumn, a new app schema can be created via the + Plus icon in the top bar of the Schema selection list.
Importing an External Schema File
Import an external XML file from a local directory by clicking Import in the bottom left corner.
Managing Classifications
Classifications can be set for object types and properties in their definition. All available classifications that trigger a specific behavior in a library-based client are described here.
Furthermore, it is possible to specify one or more custom classifications. If you specify a custom classification value, do not use the semicolon character as it is internally used as separator.
Display Modes
yuuvis® architect offers two different display modes.
-
The Model mode allows to manage schemata via a graphical user interface.
-
The XML mode displays the selected schema file in XML format.
Click the Model and XML buttons on the top right to toggle between the two views.
Using the Model Mode
After selecting a schema file, the scope of the schema (the tenant name, the app name or system) is displayed in the header of the left side bar. Below, you can switch between the two tabs Object types and Metadata to display the IDs of object types or metadata definitions that are part of the selected schema file. The object type IDs are grouped by base type (Document, Folder, and Secondary (extensions)) whereas the metadata IDs are grouped by metadata type (e.g., DateTime, Integer, String, …).
If no draft is available for the selected schema file, you can either copy the schema version currently used by yuuvis® Momentum or start with an empty schema file to create a new draft.
Creating/Editing Object Type Definitions:
-
Select the Object types tab on the left side. If your selected schema already contains object type definitions, they are arranged in a selection list grouped by the corresponding base type Document, Folder, or Secondary (extensions).
-
Create: Click the + Plus icon next to the schema namespace and choose one of the following object type definitions to be created: Document, Folder, and Secondary (extensions).
To add another object type definition to an already existing base type group, click the + Plus icon next to the corresponding base type.
-
Edit: Display the defined object types by opening the selection list of the corresponding base type Document, Folder, or Secondary (extensions). Click the object type ID of the definition you want to edit.
-
-
The base type is displayed in the header of the form view providing an object type configuration form, and the object type ID if specified.
-
Attributes marked with
*
are required. -
The properties referenced in the Metadata field area are part of the metadata.
-
To add a property, click the + icon. The Metadata field view is displayed on the right.
-
Create a new property by clicking the + icon in the header of the Metadata field view.
-
Edit a property by clicking the pencil icon.
-
Click a property in the Metadata field view to add it to or remove it from the Metadata field area of the object type view.
-
-
For document and folder object type definitions: The Used secondary object types area displays all secondary object types by their IDs that are referenced in the document or folder object type definition.
-
Click Apply to introduce your changes into the draft you are currently working on.
Creating/Editing Metadata Definitions:
-
Select the Metadata tab on the left side. If your selected schema already contains metadata definitions, they are arranged in a selection list of the corresponding metadata types (e.g., DateTime, Integer, String, …).
-
Create: Click the + Plus icon next to the schema namespace and select the type of metadata to be created. To add another metadata definition to an already existing type group, click the + Plus icon next to the corresponding type.
-
Edit: Display the defined object types by opening the selection list of the corresponding metadata types (e.g., DateTime, Integer, String, …). Click the metadata ID of the definition you want to edit.
-
-
The metadata type is displayed in the header of the form view providing a metadata configuration form, and the metadata ID if specified.
-
Attributes marked with * are required.
-
Click Apply to introduce your changes into the draft you are currently working on.
Using the XML Mode
After selecting a schema file, the two views DEPLOYED Schema and DRAFT Schema are displayed. Both of them present a schema in its XML structure.
By clicking the arrows in the right sidebar, you can compare the deployed and draft schemata in the Schema Diff view.
DEPLOYED Schema View:
-
The current version of the selected schema file is displayed. This version is currently used by yuuvis® Momentum. Editing is not possible.
-
Click Export to save a local copy of the displayed XML file.
DRAFT Schema View:
-
This view displays the draft version for the selected schema file. You can edit and save it to continue your work at a later time.
-
Click Import to load an XML file from a local directory.
-
Click Export to save a local copy of the displayed XML file.
Schema Diff View:
-
The deployed schema on the left is compared to the draft schema on the right. Differences are highlighted.
Saving and Deploying a Draft
Via Validate, it is possible to check whether your draft fulfills all requirements for a valid schema.
Click Deploy to replace the schema version currently used by yuuvis® Momentum by your draft schema. The draft is automatically validated. Thus, the process can only be successful if your draft is valid.
Click Save draft to store your current working status. The draft is not validated.
5.2.9. Access Rights Management
The Access rights management tile is available on the dashboard for users with the YUUVIS_TENANT_ADMIN
or YUUVIS_SYSTEM_INTEGRATOR
roles.
You can use this graphical user interface provided by yuuvis® architect to manage roles and the rights they will grant in your client application. The roles are defined in role set structures.
Depending on the roles assigned to the currently logged-in user, it is possible to manage the global role set, app role sets and/or tenant role sets as described below.
Selecting a Role Set
Select the role set file you want to read or edit from the Select role set selection list on the left side of the Access rights management view of yuuvis® architect. Depending on your roles, you have read and/or edit permissions:
Icon | Scope | Required Roles for Read Access | Required Role for Edit Actions |
---|---|---|---|
system |
|
YUUVIS_SYSTEM_INTEGRATOR |
|
app |
|
|
|
tenant |
|
|
The namespace of the individual role sets indicates their concrete scope: either the entire system, a specific app or a specific tenant.
To create a new app role set, use the endpoint POST /api/system/apps/{app}/permissions .
|
Display Modes
yuuvis® architect offers two different display modes.
-
The Model mode allows to manage role sets via a graphical user interface.
-
The XML mode displays the selected role set file in XML format.
Click the Model and XML buttons on the top right to toggle between the two views.
After selecting a role set file, the scope of the role set (the tenant name, the app name or system) is displayed in the header of the main area.
Creating a Role:
-
Click the + Plus icon in the header of the Select a role sidebar. Specify a name for the new role.
Editing Roles:
-
Select an existing role in the Select a role selection list on the left side. If your selected role set already contains roles, they are arranged in the Select a role selection list.
-
The role name is displayed next to the role set’s scope in the header of the form view providing a role set configuration form.
-
Attributes marked with
*
are required. -
The following fields can be configured:
-
Name of the role.
-
Permissions for the handling of DMS objects the role will grant to the users if assigned. Available values are create, read, write, delete.
-
condition to limit the specified permissions to specific object types.
-
-
Click Save role to introduce your changes into the draft you are currently working on.
After selecting a role set file, the two views Deployed role set and Draft role set are displayed. Both of them present a role set in its XML structure.
Deployed role set View:
-
The current version of the selected role set file is displayed. This version is currently used by yuuvis® Momentum. Editing is not possible.
-
Click Export to save a local copy of the displayed XML file.
Draft role set View:
-
This view displays the draft version for the selected role set file. You can edit and save it to continue your work at a later time.
-
Click Import to load an XML file from a local directory.
-
Click Export to save a local copy of the displayed XML file.
Saving and Deploying a Draft
Via Validate, it is possible to check whether your draft fulfills all requirements for a valid role set.
Click Deploy to replace the role set version currently used by yuuvis® Momentum by your draft role set. The draft is automatically validated. Thus, the process can only be successful if your draft is valid.
Click Save draft to store your current working status. The draft is not validated.
5.2.10. Process Management (BPM)
The Process management (BPM) tile is available on the dashboard for users with the YUUVIS_TENANT_ADMIN
role.
Processes/Tasks List View
Select the corresponding tab to display either the Processes list view or the Tasks list view (as of 2023 Autumn).
The lists can be sorted by the values of those properties by clicking the corresponding column header. Furthermore, it is possible to filter by specific values for the individual process properties. The value can be specified
-
via input field for string properties
-
via calendar for datetime properties or
-
via selection list for the Status.
It is possible to specify filter values for multiple properties. Internally, the conditions will be concatenated via a logical AND operator.
Processes Tab
All processes within in the currently active tenant are listed. For each process, the properties ID, Process definition key, Name, Started by, Start time, End time, Status and Business key are displayed.
Hereby, the Started by column displays Lastname, Firstname (username) like in a client application instead of the userId
. The format is configurable. Filtering is possible by typing the user’s name whereas it is internally resolved and treated as userId
. Admin users are not searchable.
Tasks Tab
As of 2023 Autumn: All tasks within the currently active tenant are listed. For each task, the properties ID, Name, Status, Editor, Owner, Creation time and End time are displayed.
Hereby, the Editor and Owner columns display Lastname, Firstname (username) like in a client application instead of the userId
. The format is configurable. Filtering is possible by typing the user’s name whereas it is internally resolved and treated as userId
. Admin users are not searchable.
Process Details View
Click a specific process instance in the processes list to display the corresponding process details. Multi-selection is possible.
The details of the selected process are displayed in the aspects Summary, Tasks and Progress.
As of 2023 Summer, the process details view’s top bar contains the Delete process and Refresh buttons.
Summary Aspect Area
The Summary aspect area contains the metadata of the selected process instance:
-
Status (Running or Completed)
-
ID
-
Process definition key
-
Name
-
Started by
-
Start time
-
End time (if already completed)
-
Business key
-
Process variables (if available) in a table with the columns Name, Type and Value
The process variables (if available) can be edited.
-
Boolean values can be changed from
true
tofalse
or vice versa. -
String values can be replaced by a different string value with a length up to 4000 characters.
-
Dates can be changed via calendar icon.
-
JSON values can be replaced by a different valid JSON structure.
-
Integer and double values can be edited to integer and double values.
-
Variables without type (
null
value variables) cannot be edited as their type is unknown.
Tasks Aspect Area
All tasks belonging to the selected process instances are listed. To sort the list by their individual values for the task properties, click the corresponding column header.
Progress Aspect Area
This aspect area displays the history of the selected process instance.
Task Details View
Click a specific task instance in the task list to display the corresponding task details. Multi-selection is possible.
The details of the selected process are displayed in the aspects Summary and Editor history.
The task details view’s top bar contains the Refresh button and, if the task is currently assigned to the logged-in user, the Unassign button.
Summary Aspect Area
The Summary aspect area contains the metadata of the selected process instance:
-
Status (Running or Completed)
-
Editor
-
Owner
-
Task ID
-
Task definition key
-
Form key
-
Process ID
-
Name
-
Creation time
-
End time (if already completed)
Task Editor History Aspect Area
An Assignments list contains information on user assignments and unassignments, delegations and resolving of the task.
5.3. Monitoring via Prometheus and Grafana
Display the current status and capacity of the services within your yuuvis® Momentum cluster via Grafana Web UI.
As of version 2021 Autumn, this monitoring solution allows the observation of your yuuvis® Momentum Kubernetes Cluster. The integrated Grafana Web UI serves for visualization of resource consumption and network traffic for yuuvis® services or their individual pods.
5.3.1. Helm Chart 'monitoring'
The monitoring
Helm chart includes Prometheus for the collection and processing of the service-specific status information, and Grafana providing a graphical user interface which displays the results provided by Prometheus. Furthermore, a Kubernetes NodePort service is installed that manages the port for the monitoring and thus allows for the access to the monitoring displayed in Grafana via web browser.
Each service within the yuuvis
namespace can be monitored.
The Grafana UI can be accessed in the web browser via the port of the NodePort service:
http://<host>:3000
There are two dashboards for the Grafana UI installed via the monitoring Helm chart:
Dashboard File Name | Description |
---|---|
|
Dashboard for inspection of single pods in a yuuvis® Momentum cluster. Displays the status information of the individual pods, e.g., their memory or CPU consumption. |
|
Dashboard for inspection of services in a yuuvis® Momentum cluster. For services using multiple pods, the results of all pods of that service are summarized. Network traffic like error messages, response times, logs etc. can thus be displayed. |
To import one of them into Grafana UI, click the Dashboards icon in the left corner and select Manage. Then, click the Import button and select a dashboard.
If you want to save a custom dashboard, click the Share icon in the top bar, switch to the Export tab and activate Export for sharing externally in order to store your dashboard in an importable format. If you now click Save to file, the exported file can be stored in the correct format. |
5.3.2. Installation and Configuration
Before deploying the monitoring Helm chart during an installation or upgrade, adjust the following parameters in the values.yaml
configuration file.
Parameter | Description | Default Value | ||
---|---|---|---|---|
|
Configuration parameters for Prometheus. |
- |
||
|
Storage time for log data collected by the Prometheus operator. |
10d |
||
|
Configuration parameters for Grafana. |
- |
||
|
Password for login to Grafana UI.
|
|
||
|
Boolean value specifying whether the Kubernetes NodePort service for the browser access of monitoring is activated ( If set to |
|
6. Business Process Management
6.1. BPM Engine API
6.1.1. Concept
In order to establish a standardized approach when working with such a large amount of documents, companies that use DMS systems need to establish and enforce business rules for their processing. For instance, an employee must know which steps are to be performed with an invoice document in order to pay an invoice to a third party, while still complying with bookkeeping rules of the company. The business rules also include multiple technical steps that should be performed by the employee in order to comply with these business rules as well as with the legal norms. For instance, a paid invoice must be marked as such in order to avoid double payment of it, and the retention time of it should be set, to prevent deletion within the time period defined by the law. All this puts a considerable cognitive load onto employees working with documents, since they have to execute their primary task of processing the invoice, while keeping the status of the document up to date (how far has the payment process progressed and what has been done so far) and setting such purely technical fields on the document.
yuuvis® Momentum is a powerful DMS system that can handle hundreds of millions of documents with ease—whether they are of numerous types, spread over multiple tenants or used by hundreds or thousands of users. In order to efficiently adopt and enforce the business rules, a considerable automation is necessary to be able to support the employees who work on the documents. And that is why we integrate the yuuvis® Momentum DMS with a workflow functionality in form of a BPM Engine. The DMS stores and manages the documents, and BPM Engine implements the business rules that define how documents are processed in a company. Implementing the business rules as workflows is not only an automation capability, but also a great opportunity for companies to document their business rules.
Why Flowable?
In order to support the workflows in yuuvis® Momentum, we have decided to integrate Flowable engine in it, for the following reasons:
-
it supports the BPMN 2.0 modeling notation, and has a visual modeler
-
it is highly extensible and supports numerous ways of integration with third-party systems
-
it has an active developer and user community
-
it has detailed documentation for all its components and technical interfaces
-
it has been proven in numerous projects and for various purposes
-
it is a freely available, open source workflow engine, accessible to any yuuvis® Momentum solution developer in case some details of implementation require detailed investigation
Integration Overview
The BPM engine is deployed within the Kubernetes cluster, next to other yuuvis® Momentum services. It exposes a detailed REST interface that is accessible from the cluster. The administration console uses this interface to manage models and processes running within the engine. The REST interface of the engine is not exposed to external clients, but can be accessed only through system gateway (that authenticates and authorizes incoming requests) and Web-API gateway. Flowable REST interface that is accessible within the cluster includes not only process-instance relevant endpoints that are of interest to clients, but also considerable number of endpoints that are used for management purposes. For this reason, the Web-API exposes only those endpoints that are relevant to external clients (that may be yuuvis® Momentum client, its customization or a custom client), such as endpoints for starting a process, or an endpoint that lists the currently active tasks of a user. The engine contains a custom IDM connector for Keycloak with which it can access users and their roles.
Both the BPM engine and Web-API Gateway REST interfaces are documented using Open-API and can be explored and tested via Swagger-UI.
The engine supports multitenancy. Each request coming from the Web-API Gateway will contain the tenant information in the JWT token and the processes and models are divided into tenants based on this information.
In case that REST interface of the engine is accessed from within the cluster, the caller has to ensure that either a correct yuuvis® Momentum JWT token is sent with the request or that the tenant ID is passed as a parameter of the endpoint call.
6.1.2. Endpoints
These endpoints allow the management of workflow processes and tasks.
Manage Process Definitions
GET /bpm-engine/api/process-definitions
- Retrieve a list of process definitions.
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves a list of process definitions matching the conditions defined in various query parameters.
Optional query parameters:
Parameter Type Description category
string
Only return process definitions with the given category.
categoryLike
string
Specify a string that has to match the category and that can contain % characters as placeholders for an arbitrary number of unknown characters.
categoryNotEquals
string
Only return process definitions which do not have the given category.
key
string
Only return process definitions with the given key.
keyLike
string
Specify a string that has to match the key and that can contain
%
characters as placeholders for an arbitrary number of unknown characters.name
string
Only return process definitions with the given name.
nameLike
string
Specify a string that has to match the name and that can contain
%
characters as placeholders for an arbitrary number of unknown characters.version
integer
Only return process definitions with the given version.
latest
boolean
Only return the latest process definition versions. Can only be used together with
key
andkeyLike
parameters. Combination with any other parameters will result in an error with HTTP status code 400.suspended
boolean
If
true
, only suspended process definitions are returned. Iffalse
, only active process definitions (which are not suspended) are returned.startableByUser
string
A valid user ID. Only return process definitions which user specified by the ID is authorized to start.
page
integer($int32)
Result page you want to retrieve (0…N). Default is 0 which means the first page.
size
integer($int32)
Number of objects per page.
sort
string
Sorting of results either ascending (
asc
) or descending (desc
). Default sort order is ascending.Response HTTP status codes:
HTTP status code Meaning 200
Request was successful and the process definitions are returned.
400
A parameter was passed in the wrong format or latest is used with parameters other than key and keyLike. The status message contains additional information.
401
The calling user is not authorized.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/process-definitions/?page=0&size=50&sort=desc&version=1
- Response Example
-
{ "objects": [ { "id": "follow-up:1:00000000-0000-0000-0000-000000000000", "category": "examplecategory", "key": "follow-up", "name": "Follow-up", "description": "Follow up any document (NOTE: The start-form enforces 1 parameter (expiryDateTime) and 1 optional parameter (whatAbout))", "version": 1, "global": false, "startFormDefined": true, "suspended": false }, { "id": "onesteptest_proc:1:00000000-0000-0000-0000-000000000001", "category": "exampleprocess", "key": "onesteptest_proc", "name": "One step test process", "description": null, "version": 1, "global": false, "startFormDefined": false, "suspended": false }, { "id": "twosteptest_proc:1:00000000-0000-0000-0000-000000000002", "category": "exampleprocess", "key": "twosteptest_proc", "name": "Process-definition-name: Two step test process", "description": "This is description from model editor (high level, not the visual editor of process). The first step goes to initiator, second to no one (can be played with id-links). There is one form reference (get group id) in the first task.", "version": 1, "global": false, "startFormDefined": false, "suspended": false } ], "numItems": 3, "totalNumItems": 3, "hasMoreItems": false }
GET /bpm-engine/api/process-definitions/{processDefinitionID}
- Retrieve a process definition by ID.
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the process definitions specified by
processDefinitionId
.Response HTTP status codes:
HTTP status code Meaning 200
The process definition was found and returned.
401
The calling user is not authorized.
404
The requested process specified by
processDefinitionId
was not found. - Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/process-definitions/onesteptest_proc:1:00000000-0000-0000-0000-000000000001
- Response Example
-
{ "id": "onesteptest_proc:1:00000000-0000-0000-0000-000000000001", "category": "exampleprocess", "key": "onesteptest_proc", "name": "One step test process", "description": null, "version": 1, "global": false, "startFormDefined": false, "suspended": false }
Manage Process Instances
GET /bpm-engine/api/processes
- Retrieve all processes for the user
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
This endpoint returns a list of processes from the same tenant as the user.
A user without admin rights can only see processes that he has started himself.
A user with admin rights can see all processes from the user’s tenant. An admin user can also filter for processes started by a given user using the parameter
startedBy
.With default filter parameters the list of processes contains completed and not completed(running) processes.
Optional query parameters:
Parameter Type Description processInstanceId
string
Only return process instances with the given id.
name
string
Only return process instances with the given name.
nameLike
string
Only return process instances with a name like the given name.
nameLikeIgnoreCase
string
Only return process instances with a name like the given name ignoring case.
processDefinitionKey
string
Only return process instances with the given process definition key.
processDefinitionId
string
Only return process instances with the given process definition ID.
processDefinitionCategory
string
Only return process instances with the given process definition category.
processDefinitionVersion
integer
Only return process instances with the given process definition version.
businessKey
string
Only return process instances with the given
businessKey
.businessKeyLike
string
Specify a string that has to match the
businessKey
and that can contain%
characters as placeholders for an arbitrary number of unknown characters.startedAfter
date-time
Only return process instances started after the given date.
startedBefore
date-time
Only return process instances started before the given date.
finishedAfter
date-time
Only return process instances ended after the given date.
finishedBefore
date-time
Only return process instances ended before the given date.
startedBy
string
Only return process instances started by the given user specified by userId. The result depends on the permissions of the currently logged-in user:
-
If
startedBy
is not specified and-
the user has admin access, all processes are returned.
-
the user has no admin access, user gets only the own processes.
-
-
If
startedBy
is specified and-
the user has admin access, all processes started by the specified user are returned.
-
the user has no admin access, only the own
userId
is allowed as value forstartedBy
. A request with a different userId as value forstartedBy
returns an error.
-
involvedUser
string
Only return process instances in which the given user is involved.
superProcessInstanceId
string
Only return process instances which have the given super process instance ID (for processes that have a call activity).
excludeSubprocesses
boolean
Return only process instances which are not sub-processes.
includeProcessVariables
boolean
Include process variables in the result.
isCompleted
boolean
If
true
, only completed processes are returned. Iffalse
, only running processes are returned. If not specified, both completed und running processes are returned.page
integer($int32)
Result page you want to retrieve (0…N). Default is 0 which means the first page.
size
integer($int32)
Number of objects per page.
sort
string
Sorting of results either ascending (
asc
) or descending (desc
). Default sort order is ascending.Response HTTP status codes:
HTTP status code Meaning 200
Request was successful and the process definitions are returned.
400
A parameter was passed in the wrong format or latest is used with parameters other than key and keyLike. The status message contains additional information.
401
The calling user is not authorized.
-
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/processes?page=0&size=1
- Response Example
-
{ "objects": [ { "id": "00000000-0000-0000-0000-000000000000", "name": "testProcessInstanceName", "businessKey": "testBusinessKey", "processDefinitionId": "twosteptest_proc:4:8dc694a2-10b1-11ec-99ef-027ea5eeae02", "processDefinitionName": "Two tasks test process", "processDefinitionDescription": "Process shall be started with Web-API Gateway variable subject to be shown in the same column of the inbox and with . Both tasks to initiator.", "startUserId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "startTime": "2021-11-01T12:28:46.363Z", "deleteReason": null, "endActivityId": null, "startActivityId": "startEvent1", "durationInMillis": null, "endTime": null, "suspended": false, "variables": [] } ], "numItems": 1, "totalNumItems": 1, "hasMoreItems": false }
POST /bpm-engine/api/processes
- Start a process
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Starts a process specified in a JSON structure in the request body.
Response HTTP status codes:
HTTP status code Meaning 200, 201
Request was successful and the process instance was created.
400
Either the process definition was not found or an invalid variable was passed. Status description contains additional information about the error.
401
The calling user is not authorized.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/processes
Request Body{ "businessKey": "myBusinessKey", "name": "myProcessInstanceName", "processDefinitionKey": "oneTaskProcess", "variables": [ { "name": "myVariable", "scope": "myScope", "type": "myType", "value": "test", "valueUrl": "http://...." } ] }
- Response Example
-
{ "hasMoreItems": true, "numItems": 50, "objects": [ { "businessKey": "myBusinessKey", "completed": true, "id": 187, "name": "myProcessInstanceName", "processDefinitionDescription": "A process definition description", "processDefinitionId": "oneTaskProcess:1:00000000-0000-0000-0000-000000000000", "processDefinitionName": "A process definition name", "startTime": "2018-04-17T10:17:43.902+0000", "startUserId": "user0001", "suspended": true, "variables": [ { "name": "myVariable", "scope": "myScope", "type": "myType", "value": "test", "valueUrl": "http://...." } ] } ] }
DELETE /bpm-engine/api/processes
- Delete multiple processes.
- As of Version
-
2023 Autumn
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Description
-
Batch delete a list of process instances. If one of the provided process instance id is not found, then no processes will be deleted. Process instances ids have to be provided as list of id strings in the request body.
Response HTTP status codes:
HTTP status code Meaning 200
Indicates the process instances were found and deleted. Response body is left empty intentionally.
401
Indicates the calling user is not authorized.
403
Indicates the calling user is not allowed to use this endpoint.
404
Indicates at least one of the requested process instances was not found.
GET /bpm-engine/api/processes/{processInstanceId}
- Retrieve a process instance
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Retrieves the process instance specified by
processInstanceId
.Optional query parameters:
Parameter Type Description includeProcessVariables
boolean
Indication to include process variables in the result. Default is
false
.Response HTTP status codes:
HTTP status code Meaning 200
The process instance was found and returned.
401
The calling user is not authorized.
404
The requested process instance specified by
processInstanceId
was not found. - Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/processes/187
- Response Example
-
{ "businessKey": "myBusinessKey", "completed": true, "id": 187, "name": "myProcessInstanceName", "processDefinitionDescription": "A process definition description", "processDefinitionId": "oneTaskProcess:1:00000000-0000-0000-0000-000000000000", "processDefinitionName": "A process definition name", "startTime": "2018-04-17T10:17:43.902+0000", "startUserId": "user0001", "suspended": true, "variables": [ { "name": "myVariable", "scope": "myScope", "type": "myType", "value": "test", "valueUrl": "http://...." } ] }
DELETE /bpm-engine/api/processes/{processInstanceId}
- Delete a process instance
- As of Version
-
2021 Autumn
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Description
-
Deletes the process instance specified by
processInstanceId
.Response HTTP status codes:
HTTP status code Meaning 200
The process instance was found and deleted.
401
The calling user is not authorized.
404
The requested process instance specified by processInstanceId was not found.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/processes/187
- Response Example
-
200
POST /bpm-engine/api/processes/{processInstanceId}/evaluate
- Evaluate a script on a process instance
- As of Version
-
2024 Summer
- Request Method
-
POST
- Response Format
-
HTTP status code
- Required Permission
-
Available if the authenticated user has the admin role configured in
bpm.engine.app.admin-access-role
. In the default configuration, access is granted via theYUUVIS_TENANT_ADMIN
role. - Description
-
Evaluates the script in the request body on a running process instance. Process variables can be changed by such a script. Supported script languages:
-
Javascript
-
Groovy
REQUIRED query parameters:
Parameter Type Description scriptLanguage
String
Specifies the language of the script that is sent in the request body.
Available values:
-
groovy
-
javascript
(default)
Response HTTP status codes:
HTTP status code Meaning 200
The script was successfully evaluated.
401
The calling user is not authorized.
403
The calling user is not allowed to use this endpoint.
404
The requested process was not found.
409
The script evaluation failed.
-
GET /bpm-engine/api/processes/{processInstanceId}/history
- Retrieve the history of a process instance
- As of Version
-
2021 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the history of the process instance specified by
processInstanceId
.Optional query parameters:
Parameter Type Description includeIdentityLinks
boolean
Decides whether the
identityLinks
list is included (true
) in the individual tasks' history or not (false
). Default isfalse
.includeComments
boolean
Decides whether the Comments list is included (
true
) in the process history or not (false
). Default isfalse
.Response HTTP status codes:
HTTP status code Meaning 200
The process instance history was found and returned.
400
Bad request.
403
Forbidden.
404
The requested process instance specified by
processInstanceId
was not found.409
Conflict.
415
Unsupported media type.
500
Internal server error.
Each error is thrown in the response body in JSON format containing an error message and an exception string.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/processes/00000000-0000-0000-0000-000000000000/history
- Response Example
-
{ "tasks": [ { "id": "00000000-0000-0000-0000-000000000123", "name": "1st_task", "description": "In this case, you have to do several things as they are:\n1. subtask\n2. subtask", "assignee": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "owner": null, "createTime": "2021-11-01T12:28:46.388Z", "claimTime": null, "endTime": null, "identityLinks": [ { "candidates": { "users": [], "roles": [] }, "assignmentHistory": [ { "type": "ASSIGNMENT", "assignee": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "timestamp": "2021-11-01T12:28:46.447Z" } ] } ] } ], "comments": [ { "id": "00000001-0001-0001-0001-000000000001", "author": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "message": "This is the first example comment for the first task.", "time": "2021-11-02T13:05:29.099Z", "processInstanceId": "00000000-0000-0000-0000-000000000000", "taskId": "00000000-0000-0000-0000-000000000123" } ] }
PUT /bpm-engine/api/processes/{processInstanceId}/variables
- Update process variables.
- As of Version
-
2024 Spring
- Request Method
-
PUT
- Response Format
-
HTTP status code
- Description
-
Saves a list of variables for a running process. If a variable does not exist yet, it will be created in the process scope.
The following types are available for variables:
-
boolean
-
string
-
datetime
-
JSON
Response HTTP status codes:
HTTP status code Meaning 200
Request was successful and the process variables were saved.
401
The calling user is not authorized.
403
The calling user is not allowed to use the endpoint.
404
The requested process instance was not found.
-
- Request Example
-
https://<host>/bpm-engine/api/processes/187/variables
Request Body{ "variables": [ { "name": "myVariable", "scope": "myScope", "type": "myType", "value": "test", "valueUrl": "http://...." } ] }
- Response Example
-
200 OK
Manage Tasks
GET /bpm-engine/api/tasks
- Retrieve a list of tasks
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves a list of tasks of the currently active user that are matching the conditions defined in various query parameters.
If the currently logged-in user has administrative rights, all active tasks within the tenant are retrieved. Use the
visibleTo
query parameter to specify any user.Optional query parameters:
Parameter Type Description id
string
Only return the task with the given id.
name
string
Only return process instances with the given name.
nameLike
string
Specify a string that has to match the name and that can contain
%
characters as placeholders for an arbitrary number of unknown characters.description
string
Only return tasks with the given description.
processInstanceId
string
Only return tasks which are part of the process instance with the given ID.
processInstanceIdWithChildren
string
Only return tasks which are part of the process instance and its children with the given ID.
processInstanceBusinessKey
string
Only return tasks which are part of the process instance with the given business key.
processInstanceBusinessKeyLike
string
Specify a string that has to match the processInstanceBusinessKey and that can contain % characters as placeholders for an arbitrary number of unknown characters.
processDefinitionId
string
Only return process instances with the given process definition ID.
processDefinitionKey
string
Only return process instances with the given process definition key.
processDefinitionKeyLike
string
Specify a string that has to match the processDefinitionKey and that can contain % characters as placeholders for an arbitrary number of unknown characters.
Only return tasks which are part of a process instance which has a process definition with a key matching the given value.
processDefinitionName
string
Only return tasks which are part of a process instance which has a process definition with the given name.
processDefinitionNameLike
string
Specify a string that has to match the processDefinitionName and that can contain % characters as placeholders for an arbitrary number of unknown characters.
Only return tasks which are part of a process instance which has a process definition with a name matching the given value.
Only return tasks which are part of the process instance which has a business key matching the given value.
createdAfter
string
Only return tasks which have been created after the given date.
createdBefore
string
Only return tasks which have been created before the given date.
createdOn
string
Only return tasks which have been created on the given date.
completedAfter
date-time
Only return tasks which are completed after the given date.
completedBefore
date-time
Only return tasks which are completed before the given date.
dueAfter
string
Only return tasks which are due after the given date.
dueBefore
string
Only return tasks which are due before the given date.
dueOn
string
Only return tasks which are due on the given date.
withoutDueDate
boolean
Only return tasks which do not have a due date. The property is ignored if the value is
false
.scopeDefinitionId
string
Only return tasks with the given
scopeDefinitionId
.scopeId
string
Only return tasks with the given
scopeId
.scopeType
string
Only return tasks with the given scopeType.
owner
string
Only return tasks with the given owner id.
includeProcessVariables
boolean
Include process variables in the result.
isAssigned
boolean
As of 2023 Spring.
If
isAssigned=true
, the endpoint retrieves only tasks that are assigned to the currently logged-in user.If
isAssigend=false
, the endpoint retrieves only tasks without an assignee for which the currently logged-in user is a candidate user.If
isAssigned
is not specified in the request URL, the endpoint retrieves tasks that are assigned to the currently logged-in user as well as tasks without an assignee for which the currently logged-in user is a candidate user.visibleTo
string
As of 2023 Autumn: Only return tasks visible to this user.
isCompleted
boolean
As of 2023 Autumn: If
true
, only completed tasks are returned. Iffalse
, only running tasks are returned. If not specified, both completed and running tasks are returned.page
integer($int32)
Results page you want to retrieve (0…N). Default is 0 which means the first page.
size
integer($int32)
sort
string
Number of objects per page.
filter
string
(up to 2022 Winter) Allows to filter the result. By default, all tasks that are assigned to the current user, have been claimed by the current user or are waiting to be claimed by the current user (candidate user or groups) will be returned.
assignee
string
up to 2023 Summer
Response HTTP status codes:
HTTP status code Meaning 200
The request was successful and the tasks are returned.
401
The calling user is not authorized.
404
A parameter was passed in the wrong format. The status message contains additional information.
- Request Example
-
https://<host>/bpm-engine/api/tasks?page=0&size=1
no request body
- Response Example
-
200 OK
Response Body{ "objects": [ { "id": "187", "name": "1st_task", "description": "In this case, you have to do several things as they are:\n1. subtask\n2. subtask", "assignee": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "owner": aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa5, "createTime": "2021-11-01T12:28:46.388Z", "endTime": "2023-12-02T13:39:57.499Z", "claimTime": "2021-11-01T13:29:47.389Z", "processDefinitionId": "twosteptest_proc:4:8dc694a2-10b1-11ec-99ef-027ea5eeae02", "processInstanceId": "00000000-0000-0000-0000-000000000000", "parentTaskId": null, "formKey": "twosteptest_proc:1st_task", "taskDefinitionKey": "sid-4CAF2A19-B303-46C6-A7C0-2F506F1613D4", "delegationState": "pending", "suspended": true, "variables": [ { "name": "whatabout", "type": "string", "value": "testValue", "scope": "global" }, { "name": "initiator", "type": "string", "value": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa5", "scope": "global" } ] } ], "numItems": 1, "totalNumItems": 1, "hasMoreItems": false }
GET /bpm-engine/api/tasks/{taskId}
- Retrieve a task by ID
- As of Version
-
2021 Autumn
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the task specified by
taskId
.Optional query parameters:
Parameter Type Description includeProcessVariables
boolean
Indication to include process variables in the result. Default is
false
.Response HTTP status codes:
HTTP status code Meaning 200
The task was found and returned.
401
The calling user is not authorized.
404
The requested task was not found.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/tasks/187
- Response Example
{
"id": "187",
"name": "1st_task",
"description": "In this case, you have to do several things as they are:\n1. subtask\n2. subtask",
"assignee": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"owner": aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa5,
"createTime": "2021-11-01T12:28:46.388Z",
"claimTime": "2021-11-01T13:29:47.389Z",
"processDefinitionId": "twosteptest_proc:4:8dc694a2-10b1-11ec-99ef-027ea5eeae02",
"processInstanceId": "00000000-0000-0000-0000-000000000000",
"parentTaskId": null,
"formKey": "twosteptest_proc:1st_task",
"taskDefinitionKey": "sid-4CAF2A19-B303-46C6-A7C0-2F506F1613D4",
"delegationState": "pending",
"suspended": true,
"variables": [
{
"name": "whatabout",
"type": "string",
"value": "testValue",
"scope": "global"
},
{
"name": "initiator",
"type": "string",
"value": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa5",
"scope": "global"
}
]
}
POST /bpm-engine/api/tasks/{taskId}
- Perform an action on a task
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Performs an action defined in the request body on the task specified by taskId.
In addition to the complete action and in contrast to the corresponding underlying Flowable task actions, the following actions allow to apply changes to variables as well:
-
delegate
-
resolve
The specified values for the variables are updated even if the final resolving process fails.
Response HTTP status codes:
HTTP status code Meaning 200
The request was successful and the task is returned.
400
An invalid variable has been passed. Status description contains additional information about the error.
401
The calling user is not authorized.
404
The requested task was not found.
-
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/tasks/8
Request Body{ "action": "claim", "assignee": "userWhoClaims", "variables": [ { "name": "myVariable", "scope": "myScope", "type": "myType", "value": "test", "valueUrl": "http://...." } ] }
- Response Example
-
{ "assignee": "userWhoClaims", "claimTime": "2018-04-17T10:17:43.902+0000", "createTime": "2013-04-17T10:17:43.902+0000", "description": "Task description", "formKey": "myKey", "id": 8, "name": "My task", "parentTaskId": "null", "processDefinitionId": 123, "processInstanceId": 123, "suspended": true, "variables": [ { "name": "myVariable", "scope": "myScope", "type": "myType", "value": "test", "valueUrl": "http://...." } ] }
GET /bpm-engine/api/tasks/{taskId}/candidates
- Retrieve candidates
- As of Version
-
2024 Spring
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves the list of candidates for the task specified by
taskId
.Response HTTP status codes:
HTTP status code Meaning 200
The task was found and the list of candidates returned.
401
The calling user is not authorized.
404
The requested task was not found.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/tasks/187/candidates
- Response Example
{
"users": [
"string"
],
"roles": [
"string"
]
}
PUT /bpm-engine/api/tasks/{taskId}/candidates
- Add candidates
- As of Version
-
2024 Spring
- Request Method
-
PUT
- Response Format
-
JSON
- Description
-
Extends the list of candidates for the task specified by
taskId
. The new candidates are specified in the JSON request body directly via their user ID or indirectly via roles.Response HTTP status codes:
HTTP status code Meaning 204
The task was found and the list of candidates was updated.
401
The calling user is not authorized.
403
The user is not allowed to add candidates to the task.
404
The requested task was not found.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/tasks/187/candidates
Request body{ "users": [ "string" ], "roles": [ "string" ] }
- Response Example
-
204 OK
POST /bpm-engine/api/tasks/{taskId}/candidates
- Replace candidates
- As of Version
-
2024 Spring
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Sets a list of users (specified by its IDs) and/or roles (specified by its names) as the candidates of a running task.
Current candidates of this task will be overwritten with the new ones, but users or roles will only be affected if you pass a value as the corresponding JSON object.
Example:
-
Only pass a
user
list but noroles
list with the following input:{ "users": [ "cb6e5625-caef-4825-9eb3-6cd1310354e6" ] }
-
Only the user candidates will be overwritten. The role candidates won’t be affected at all.
If you pass an empty array, all candidates of this type will be removed.
Response HTTP status codes:
HTTP status code Meaning 204
The task was found and the list of candidates was updated.
401
The calling user is not authorized.
403
The user is not allowed to add candidates to the task.
404
The requested task was not found.
-
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/tasks/187/candidates
Request body{ "users": [ "string" ], "roles": [ "string" ] }
- Response Example
-
204 OK
DELETE /bpm-engine/api/tasks/{taskId}/candidates
- Delete candidates
- As of Version
-
2024 Spring
- Request Method
-
DELETE
- Response Format
-
JSON
- Description
-
Deletes a list of users (specified by its IDs) and/or roles (specified by its names) from the candidates of a running task.
Response HTTP status codes:
HTTP status code Meaning 204
The task was found and the corresponding candidates were deleted.
401
The calling user is not authorized.
403
The user is not allowed to add candidates to the task.
404
The requested task was not found.
- Request Header
-
Content-Type: application/json
- Request Example
-
https://<host>/bpm-engine/api/tasks/187/candidates
Request body{ "users": [ "string" ], "roles": [ "string" ] }
- Response Example
-
204 OK
POST /bpm-engine/api/tasks/{taskId}/comment
- Create a comment
- As of Version
-
2021 Autumn
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Creates a comment with the message specified in the plain text request body for the task specified by
taskId
. It will be included in the process instance’s history.Response HTTP status codes:
HTTP status code Meaning 201
The request was successful and the comment is returned.
400
The request body is missing.
404
The requested task was not found.
- Request Header
-
Content-Type: text/plain
- Request Example
-
https://<host>/bpm-engine/api/tasks/00000000-0000-0000-0000-000000000123
Request BodyTest comment number 2.
- Response Example
-
{ "id": "00000001-0001-0001-0001-000000000001", "author": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "message": "Test comment number 2.", "time": "2021-11-09T13:53:20.339Z", "processInstanceId": "00000000-0000-0000-0000-000000000000", "taskId": "00000000-0000-0000-0000-000000000123" }
6.1.3. Modeling and Deployment of Process Definitions
The process definitions for BPM Engine are modeled locally via Flowable UI and deployed to the BPM Engine afterwards. For the deployment, the internal API of the BPM Engine itself has to be used. It can be made available for authorized users via configuration of the authentication
service or via port forwarding.
Process Definition
The process modeling requires the local installation of Flowable UI. A detailed description of the installation and usage is provided in the Flowable documentation.
By means of the Flowable UI, create your process definitions and group them in an application.
As of version 2021 Winter, Flowable Http tasks can call internal yuuvis® Momentum endpoints. In order to add the yuuvis® Momentum authentication headers that are required for internal requests, set the placeholder Authorization: %%YuuvisSystemInternal%%
for the Request header configuration parameter. If HTTP task is used to call external methods, this option should not be used. Other headers can be added as desired and required via the modeler.
Publish your application including your new versions of process definitions and export it in BAR or ZIP format.
The BAR format is the primary format for deployment that includes Flowable-specific pre-defined forms (not supported by a library-based client) that will be deployed in the BPM Engine. This may be of interest for custom clients that are using and supporting forms in Flowable format. Unfortunately, this format is a pure deployment format and cannot be imported back to Flowable modeler.
The ZIP format will be also accepted by BPM Engine, and can be reimported to a Flowable modeler as well. The Flowable-specific forms are included but will not be deployed by the Flowable BPM Engine.
Process Deployment
The exported application from the Flowable UI has to be imported to BPM Engine via its internal API. The corresponding endpoints can be configured in the file authentication-prod.yml to be accessible via Swagger UI for users with a specified administrative role. In productive systems, the internal API should not be accessible for yuuvis® Momentum users. Instead, you can use the internal REST interface of BMP Engine via port forwarding. Thus, the Swagger UI can be used only by Kubernetes administrators. Alternatively, you can also use a different tool of your preference, such as cURL.
Deployment via Swagger UI
In order to use the internal BPM Engine endpoints via Swagger UI, the following configuration is required to be added in the configuration file authentication-prod.yml
under authorization.accesses. The access will be managed by the authentication
service and has to be limited to users with a specified administrative role.
1
2
3
- endpoints: /bpm-engine/swagger-ui.html,/bpm-engine/swagger-ui/**,/bpm-engine/v2/api-docs/**,/bpm-engine/v3/api-docs/**
- endpoints: /bpm-engine/internal/**
access: hasAuthority('<role>')
If the configuration is applied and the logged-in user is authorized, the Swagger UI is available via the URL https://<host>/bpm-engine/swagger-ui.hmtl
.
-
Select the Internal Flowable App REST API from the dropdown menu in the top bar.
-
In the App Deployments section, click the POST /app-repository/deployments endpoint.
-
Click Try it out.
-
Type the ID of the tenant to which you want to deploy the new process definitions.
-
Select the exported Flowable application from your file system.
-
Execute the API call.
It is also possible to use the internal REST interface of the BPM Engine for the deployment of new process definitions without enabling user web access. Since those endpoints are accessible only for services within the yuuvis® Momentum cluster, port forwarding is required for the access to the Kubernetes pod for the bpm-engine
service.
Deployment via cURL
If Swagger is not activated in a system, process definitions can be deployed by other means, such as for instance cURL. The same access configuration rules apply as described before. In the following steps, replace the <*>
terms by your specific values.
-
Create a deployment. The following command deploys the exported Flowable application to the BPM Engine instance.
curl -u <username>:<password> -F 'upload=@\"<PATH TO THE APPLICATION .zip OR .bar FILE>"' -X POST "https://<HOSTNAME>/bpm-engine/internal/process-api/repository/deployments?tenantId=<tenantId WHERE THE APPLICATION IS TO BE DEPLOYED>" -H "accept: application/json" -H "Content-Type: multipart/form-data" -H "X-ID-TENANT-NAME: <tenantId WHERE THE APPLICATION IS TO BE DEPLOYED>"
-
Retrieve the deployments in order to check whether the deployment was successful.
curl -u <username>:<password> -X GET "https://<HOSTNAME>/bpm-engine/internal/process-api/repository/deployments?tenantId=<tenantID WHERE APPLICATION WAS DEPLOYED>" -H "accept: application/json" -H "X-ID-TENANT-NAME: <tenantID WHERE APPLICATION WAS DEPLOYED>"
-
List the deployed process definitions. The command retrieves a list of your available process definitions.
curl -X GET "https://<HOSTNAME>/bpm-engine/internal/process-api/repository/process-definitions?tenantId=<tenantID WHERE APPLICATION WAS DEPLOYED>" -H "accept: application/json" -H "X-ID-TENANT-NAME: <tenantID WHERE APPLICATION WAS DEPLOYED>"
-
From the retrieved list of process definitions, choose one process definition you want to use to instantiate a process. For the process creation, you can specify the process definition by its ID. Note that if you specify the ID of an older version of a process definition, this old version will be used for the instantiation of your process.
Alternatively, you can refer to a process definition by specifying its processDefinitionKey as shown in the command below. In this case, the current version of process definition will always be used for the process instantiation.
curl -u <username>:<password> -X POST "https://<HOSTNAME>/bpm-engine/internal/process-api/runtime/process-instances" -H "accept: application/json" -H "Content-Type: application/json" -d "\{ \"businessKey\": \"myBusinessKey\", \"name\": \"myProcessInstanceName\", \"processDefinitionKey\": \"<PROCESS DEF KEY TO BE STARTED>\", \"returnVariables\": true, \"tenantId\": \"<tenantID WHERE APPLICATION WAS DEPLOYED>\"}" -H "X-ID-TENANT-NAME: <tenantID WHERE APPLICATION WAS DEPLOYED>"
Custom Functionality Extension
As of version 2022 Winter, it is possible to add custom functionality to process definitions that is not supported by Flowable, e.g., notifying a logger. The custom extension is integrated as delegation in service tasks or event listeners.
As of 2023 Winter, scripts can be written in Groovy or JavaScript as well.
Dependency
Create a new project. Inject the flowable-engine dependency.
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>6.8.2</version>
<scope>provided</scope>
</dependency>
Java Implementation
The class with your custom extension has to implement the JavaDelegate Flowable interface as shown in the example below.
package my.company;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;
import java.util.logging.Logger;
public class LoggerDelegate implements JavaDelegate {
private static final Logger log = Logger.getLogger(LoggerDelegate.class.getName());
public void execute(DelegateExecution execution) {
log.info("\n\n ... LoggerDelegate invoked by "
+ "processInstanceId=" + execution.getProcessInstanceId()
+ ", processInstanceBusinessKey=" + execution.getProcessInstanceBusinessKey()
+ ", processDefinitionId=" + execution.getProcessDefinitionId()
+ ", activityId=" + execution.getCurrentActivityId()
+ ", flowElementId='" + execution.getCurrentFlowElement().getId() + "'"
+ ", flowElementName='" + execution.getCurrentFlowElement().getName() + "'"
+ ", executionId=" + execution.getId()
+ " \n\n");
}
}
Extension of 'bpm-engine' Image
Compile your project and copy the JAR into the /yuuvis/libs
bpm-engine
library folder.
You can use your custom Java class in your process definitions now.
6.1.4. Handling of Process Instances and Tasks
A process can be instantiated based on a process definition that refers to a process model created via Flowable Modeler UI and deployed to the BPM-ENGINE service. Especially, the concrete tasks included in the process instance are determined by the process model referenced via the process definition. See the Flowable Documentation.
The follow-up process model is included as an example in our installations. It is supported by yuuvis® Momentum client as reference implementation and is also compatible with our developer libraries.
Creating Process Instances
Processes instances are created by starting a process based on a specified process definition. All deployed and thus available process definitions can be retrieved via the GET /bpm-engine/api/process-definitions
endpoint. Reference one of the listed process definition objects for your concrete process instance creation by its key. Use the value for the processDefinitionKey in the request body for POST /bpm-engine/api/processes
.
The (first) task included in the process instance is now available for the assignee (if already pre-defined) or all referenced candidate users.
Retrieving Process Instances
Users can only retrieve process instances that they have started themselves.
There are two endpoints available:
-
GET /bpm-engine/api/processes
- Retrieves a list of processes of the currently active user that are matching the conditions defined in various query parameters. -
GET /bpm-engine/api/processes/{processInstanceId}
- Retrieves the process instance specified byprocessInstanceId
.
Working on Tasks
Retrieving Tasks
Users can only retrieve tasks that are assigned to them or for which they are a candidate user.
There are two endpoints available:
-
GET /bpm-engine/api/tasks
- Retrieves a list of tasks of the currently active user that are matching the conditions defined in various query parameters. -
GET /bpm-engine/api/tasks/{taskId}
- Retrieves the task specified by taskId.
Responsibilities
-
Assignee
-
Only the assignee of a task can take an action on it. An exception is the complete action as described below.
-
-
Candidate Users
-
In order to specify multiple users that should be able to take an action on a specific task, those users can be set as so-called candidate users. It is possible to assign candidate groups as well by specifying a role. Each user with this role will be a candidate user for the corresponding task.
-
All candidate users are allowed to claim the task and thereby assign it to themselves. As soon as the task is assigned to one of them, it will no longer be available for all other candidate users until the assignee returns it to them. All candidate users are allowed to complete the task without assigning it to themselves when no assignee is specified.
-
-
Owner
-
When the first assignee delegates the task to another user, the first assignee becomes the owner. The owner is not overwritten if further delegations are applied to the task. Whenever a subsequent assignee resolves the task, the owner will be set as assignee again. Thus, the owner is responsible for the task completion.
-
Actions and Identity Links
Users can take an action on a task specified by its ID via the POST /bpm-engine/api/tasks/{taskId}
endpoint. In the request body, the type of action is set as value for the action property. The following actions are available for the user(s) with the corresponding responsibility.
Value for 'action' | Responsibility | Effect on the Task |
---|---|---|
|
assignee, candidate users |
|
|
if assignee is |
|
if assignee is not null: assignee |
|
|
|
assignee |
|
|
assignee (if appointed via delegation) |
|
Each action that is applied to a task triggers the creation of a new identity link referring to the acting user in the individual task’s history, e.g.:
{
"type": "assignee",
"userId": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"groupId": null,
"timestamp": "2021-11-01T12:28:46.447Z"
}
Comments
In order to add messages to a task, comments can be created and assigned via the POST /bpm-engine/api/tasks/{taskId}/comment
endpoint. They will be included in the process history in a separate section. The following code block shows an example comment visualising the corresponding stored data set.
{
"id": "00000001-0001-0001-0001-000000000001",
"author": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"message": "This is the first example comment for the first task.",
"time": "2021-11-02T13:05:29.099Z",
"processInstanceId": "00000000-0000-0000-0000-000000000000",
"taskId": "00000000-0000-0000-0000-000000000123"
}
Process Instance History
The process history is available for active tasks as well as for completed tasks. It can be retrieved via the GET /bpm-engine/api/processes/{processInstanceId}/history
endpoint.
The response body is a JSON structure containing the following properties.
Parameter | Description | ||
---|---|---|---|
|
List of data sets, one for each task within the process. Each data set contains the following parameters: |
||
|
ID of the task instance. |
||
|
Task name. |
||
|
Task description. |
||
|
User ID of the current assignee. If the task is currently not assigned to a user, the value is |
||
|
User ID of the owner. |
||
|
Date and time of task creation. |
||
|
Date and time of last claim action on the task. If the task has not been claimed so far, the value is |
||
|
Date and time of task completion (action complete). If the task has not been claimed so far, the value is |
||
|
List of identity links stored for the corresponding task. |
||
|
Type of identity link, e.g., candidate. |
||
|
ID of the user to which the identity link refers. If multiple users are involved, the value is |
||
|
Role that defines the group of users to which the identity link refers. If only one user is involved, the value is |
||
|
Date and time of identity link creation. |
||
|
List of data sets, one for each comment that has been assigned to the process. |
||
|
ID of the comment. |
||
|
User ID of the user who assigned the comment to the process. |
||
|
Comment message. |
||
|
Date and time of the comment’s assignment. |
||
|
ID of the process instance containing the task to which the comment was assigned. |
||
|
ID of the task instance to which the comment was assigned. |
6.1.5. Configuration
Database Connection of 'bpm-engine'
The bpm-engine
service users the database connection that is configured via environment variables as described in the installation guide.
Setting up Identity Management for 'bpm-engine'
The BPM-ENGINE service is based on the workflow functionality of the open source software Flowable. The service is connected to Keycloak in order to obtain information on users and their roles present in the tenant. The Business Process Management can be used only if yuuvis® Momentum uses Keycloak as identity provider and role management system.
Flowable and Keycloak
If Keycloak is used as identity provider and role management system, users are registered as members of realms (corresponding to yuuvis® Momentum tenants) with defined roles assigned to them. Furthermore, users can be assigned to groups which can build a hierarchical structure.
The Keycloak realms and users are directly mapped to tenants and users in Flowable and thus in the BPM-ENGINE. The Keycloak groups are not mapped to Flowable. Keycloak supports the hierarchical group structure that is unique for every tenant. Hierarchical group structures are not supported in Flowable and in addition, since the group structure is unique for every tenant, it would not be possible to develop a model that is valid in multiple tenants and that assigns a user task to a specific group (such as "bookkeepers"). To resolve both of these integration issues, we map the users' Keycloak roles to Flowable groups. Since roles form a flat structure and can be assigned to users from different tenants, they correspond to the groups of users as defined in Flowable.
Once correctly configured, the Groups and Users interface in Flowable REST will provide information on users and groups within the BPM-ENGINE. However, it is not possible to edit users or groups via the BPM-ENGINE service. This has to be done in Keycloak.
Configuration for 'bpm-engine' Service
Following service configuration parameters are available.
Parameter | Description | Default Value | ||||
---|---|---|---|---|---|---|
|
Section of parameters defining BPM-internal settings. |
|||||
|
Section of parameters related to the BPM-ENGINE service. |
|||||
|
Specifies the master Flowable tenant which has access to all other tenants. As of version 2021 Autumn: If access to all tenants should be enabled also via |
|
||||
|
Specifies the role granting the permission to access all tenants. Users with the specified role furthermore have admin rights for processes and are thus able to manage all processes (not only their own ones, as it is the case for "normal" users). As of version 2021 Autumn: If access to all tenants should be enabled also via |
|
||||
|
Section of parameters for the connection of an identity provider. |
|||||
|
Section of parameters only required if Keycloak is used as identity provider. |
|||||
|
Boolean value that specifies if BPM Engine connects to Keycloak/ If |
|
||||
|
URL of the Keycloak server that should be used for authentication. |
|||||
|
Section of parameters specifying the access credentials for the technical user account used by the |
n/a |
||||
|
Username for technical user account. |
|||||
|
Password for technical user account. |
|||||
|
Section of parameters only required if Keycloak is not used as identity provider. |
|||||
|
Boolean value that specifies if BPM Engine connects to Keycloak/ If |
|
||||
|
URL to the identity provider or to the idm-controller of the |
|
Up to version 2022 Summer, BPM Engine has to be configured as follows. Especially, the conversion of the Keycloak roles into Flowable groups can be customized via the keycloak.idm.groups.role-filter
parameter.
Parameter | Description | Default Value | |||
---|---|---|---|---|---|
|
Section of parameters defining the connection of the |
||||
|
URL of the Keycloak server that should be used for authentication. |
|
|||
|
Section of parameters specifying the access credentials for the technical user account used by the |
n/a |
|||
|
username for technical user account |
||||
|
password for technical user account |
||||
|
Section of parameters defining conversion configurations for the connection between Keycloak and the |
||||
|
Section of parameters dealing with the conversion of Keycloak roles into BPM-ENGINE groups. |
- |
|||
|
Contains a regular expression that filters the roles from Keycloak such that only those Keycloak roles that match the condition are visible to the Example: With the filter |
|
6.2. BPM Admin UI
The BPM-ADMIN-UI service is a frontend application enabling the management of models, processes, tasks, and jobs via an administrative graphical user interface.
This service is not yet included in yuuvis® Momentum installations but is available only on request. Alternatively, you can use the Flowable REST API in order to directly call the endpoints of the BPM-ENGINE service. |
6.2.1. Configuration
Once logged in to the BMP Admin UI, users have the permission to manage all models and processes of all tenants. Therefore, the protection against unauthorized access has to be ensured. Per default, this security is achieved by granting access only within the Kubernetes cluster of yuuvis® Momentum. Users can access the system only from their local workstations via Kubernetes port forwarding within the Kubernetes cluster. However, the BPM Admin UI can be configured such that authentication is possible via other authentication gateways with appropriate access credentials.
Parameters
The parameters for the connection between BPM-ENGINE service and BPM-ADMIN-UI service are listed in the section bpm.admin.app.default-user-authentication of the configuration profile.
Parameter | Description | Default Value | |
---|---|---|---|
|
Boolean value that activates or deactivates the default authentication for the |
|
|
|
Section of parameters defining the access credentials and permissions of the technical user account used for the default authentication. |
||
|
Defines the id of the default user that will be written to appropriate logs. It does not have to exist in Keycloak since no subsequent authorization is performed. |
|
|
|
Defines the Flowable tenant that can be accessed by the If access to all tenants is needed, this parameter should be the same as the configuration parameter |
|
|
|
The roles that will be used to identify the |
as of 2021 Winter: |
Setting Options via User Interface
After accessing the BPM Admin as the graphical user interface provided by the bpm-admin-ui
service, the URL of the BPM Engine can be changed. This might be necessary if deployment has multiple BPM Engine instances within the same cluster. However, in most cases this is not needed since by default there is one instance of BPM Engine and the BPM Admin will connect to it by default. Only process-engine
is supported at the moment, since it is deployed with yuuvis® Momentum by default. Other engines cannot be managed and a toast error will occur.
When searching and managing the processes, the BPM Admin user may use a filter for tenant ids to improve the search results. Only requests affecting the specified tenant will be available. The filter must be set if the parameter bpm.admin.app.default-user-authentication.user.tenant
specifies a single tenant not having access to other tenants. By default, both BPM Engine and BPM Admin services are configured such that administration of all tenants is possible.
7. SAP® Integration
Combine yuuvis® Momentum with SAP.
There are separate services for the different SAP® interfaces:
-
The basic integration functionality is provided by the
repositorymanager
service. -
The
repositorymanager-cmis
service (orrmcmis
spring application) can be used to connect to SAP® via CMIS interface. -
The
repositorymanager-ilm
service (orrmilm
spring application) can be used to connect to SAP® via ILM controller.
7.1. Concept
The repositorymanager
service establishes the connection between SAP® and the yuuvis® Momentum system and organizes and manages storage and retrieval of documents in both yuuvis® Momentum and SAP.
The SAP® object types are mapped to yuuvis® Momentum object types that are defined in the repositorymanager
app schema. The access to yuuvis® Momentum is managed via a technical user account that has full access to objects of types defined in the repositorymanager
app schema.
Each tenant can have a single ILM repository and several ArchiveLink repositories (if needed), since ArchiveLink model includes the ContentRepository field.
7.1.1. Inserting a Document in yuuvis® Momentum by Barcode Upload
The Document and its Data
If a document is inserted into the yuuvis® Momentum system, the corresponding document will be given a barcode and an ArchiveLink version (AL version) is created. The barcode is specified during the capture process (e.g., a barcode label is applied to a document).
The barcode links the document with a business process until the SAP® system has linked an SAP® business object to the document ID.
At this point it is not yet allowed to set the 'Barcode sent to R3' document flag. All other index data of the document and components need to be already filled in, in particular the unique DocID.
In regular intervals, yuuvis® Momentum REPOSITORYMANAGER determines all documents that have a barcode and no BarcodesenttoR3 flag. For these documents, an entry will be inserted in the barcode file, which is written in the configured Work/Barcode directory.
Reporting the Document to the SAP® System
By calling the WriteBarcodeFile function, the REPOSITORYMANAGER service determines in cyclic intervals all barcodes and document IDs that have not yet been reported to the SAP® system. The corresponding values of the documents to be reported are written to a file in the Work\Barcode directory by the REPOSITORYMANAGER service. This file’s content may look as follows:
<Barcode1> FI <Document-ID1> 20090623 FAX
<Barcode2> FI <Document-ID2> 20090623 FAX
<Barcode3> FI <Document-ID3> 20090623 FAX
Barcode values cannot contain any spaces because they are used as separators here.
The BarcodesenttoR3 field’s value is set to true
to flag the processed documents. This field will be created in the REPOSITORYMANAGER service when reporting the barcode to the SAP® system.
This ensures that unsuccessfully processed documents are NOT processed again and again to avoid system overload.
The processing results are documented in KGS-success and KGS-error-file as usual. In case of error, manual correction is required.
To simplify error tracking and handling, it is possible to extend the schema by adding an optional barcodeProcessingError
field.
Referencing a Document in the SAP® System
When the barcode is reported to SAP, the document ID and the barcode are entered in the SAP® table BDS_BAR_EX for open external barcodes. This table includes all externally captured documents that own a barcode and are therefore identified by a document ID, but could not have been internally assigned to an SAP® object and a business process respectively in the SAP® system.
Barcode files are exchanged in the <WorkingDirectory> in the barcode subdirectory. If the exchange file was processed correctly by the content server, the barcodes are entered in the <WorkingDirectory>\barcode\successful\yyyymmdd.txt file. If barcodes were not processed correctly, they are entered in the <WorkingDirectory>\barcode\error\yyyymmdd.txt file.
A maximum of 5,000 barcodes can be reported in a reporting interval.
Linking a Document to an SAP® Object
In the SAP® system, a business process (SAP® object) can be assigned to a document. For example, the booking of a payment transaction. During this process, the barcode of a business transaction will be filed together with the SAP® object ID in the SAP® table BDS_BAR_IN of open internal barcodes.
The document ID is referenced with the barcode in the SAP® table for the open external barcodes and the barcode is referenced with an SAP® object ID in the table for the open internal barcodes. Thus, the SAP® object ID and the document ID can be linked. This is done automatically. The SAP® object ID and document ID are added to the SAP® link table TOAXX taking into account the repository. This completes the linking of a yuuvis® Momentum document to an SAP® process. After linking, the barcode is no longer known to the SAP® system and can only be searched in the yuuvis® Momentum system.
Data Flow Diagram
The following diagram depicts the data flow of when a document is given to the SAP® system.
7.1.2. Archiving of Data from the SAP® System
Receipts (documents), print lists, and reorg data (data backups) may be stored. In this case, the document ID is transferred to the yuuvis® Momentum system. Barcodes are not transferred here.
ArchiveLink Retention Propagation
If an ILM-Object contains a link to an ArchiveLink object, the REPOSITORYMANAGER service ensures the following:
-
If a legal hold or a retention date is specified for the ILM-object, these metadata are propagated to the linked ArchiveLink object itself.
-
Same behavior in case of lifting the legal hold.
An ArchiveLink object with a legal hold and/or with a retention date lying in the future are prevented from being deleted by ArchiveLink directly.
7.2. Basic 'repositorymanager' Service
7.2.1. Installation
Deployment
The repositorymanager
service is delivered as docker container image.
As of 2022 Summer, the installation via Helm chart is possible as well.
For the deployment to the yuuvis® Momentum cluster, you need a deployment and a service script as shown in the example code blocks below. The parameters have to be adjusted according to your own cluster. However, please use the /working-dir
path for the PersistentVolumeClaim
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Service
metadata:
namespace: $NAMESPACE
labels:
app: yuuvis
name: repositorymanager
yuuvis: "true"
name: repositorymanager
spec:
ports:
- name: "http"
port: 80
targetPort: 8010
type: ClusterIP
selector:
name: repositorymanager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-repositorymanager
namespace: $NAMESPACE
spec:
storageClassName: local-path
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: $NAMESPACE
labels:
app: yuuvis
name: repositorymanager
name: repositorymanager
spec:
replicas: 1
selector:
matchLabels:
name: repositorymanager
template:
metadata:
labels:
name: repositorymanager
spec:
containers:
- name: repositorymanager
image: docker.optimal-systems.org/team-kookaburra/$CI_PROJECT_NAME:commit-$CI_COMMIT_SHORT_SHA
imagePullPolicy: Always
env:
- name: JAVA_OPTS
value: -Xmx128m
- name: SPRING_CLOUD_CONFIG_URI
value: "http://configservice/config"
- name: SPRING_PROFILES_ACTIVE
value: prod,docker,kubernetes
ports:
- containerPort: 8010
volumeMounts:
- name: storage
mountPath: /working-dir
volumes:
- name: storage
persistentVolumeClaim:
claimName: data-repositorymanager
restartPolicy: Always
imagePullSecrets:
- name: osgitlab
Configuring the Kubernetes Cluster
The repositorymanager
service has to be accessible for the SAP® system which is running outside the yuuvis® Momentum Kubernetes cluster. We recommend the usage of a loadbalancer of your cloud provider or the implementation of an Ingress controller. Alternatively, you could open the corresponding node port for the connection to the SAP® system.
The following two sections provide an example configuration for both, the access via Ingress and via Node Port.
If your tests fail due to problems with the ILM protocol, please disable CORS
|
Access via NGINX Ingress Controller
The following steps result in a configuration where the REPOSITORY-MANAGER service is accessible via NGINX Ingress controller from outside the Kubernetes cluster.
-
Add the Helm repositories for the NGINX Ingress controller and for a certificate manager for automated TLS certificate management:
helm repo add nginx-stable https://helm.nginx.com/stable helm repo add jetstack https://charts.jetstack.io helm repo update
-
Install the certificate manager and the Ingress:
1 2 3 4 5 6 7 8 9 10 11
helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.8.0 \ --set installCRDs=true helm install nginx-ingress nginx-stable/nginx-ingress --set rbac.create=true # Validate that nginx is running kubectl get pods --all-namespaces -l app=nginx-ingress-nginx-ingress
-
Add the following ingress-repositorymanager.yaml file to the templates folder of the repositorymanager Helm chart. Adjust the values according to your installation.
Example 'ingress-repositorymanager.yaml' configurationapiVersion: cert-manager.io/v1 kind: Certificate metadata: name: repositorymanager.yourdns.net # Change value spec: secretName: repositorymanager-yourdns-net-cert # Change value dnsNames: - repositorymanager.yourdns.net # Change value issuerRef: group: cert-manager.io name: letsencrypt-prod kind: ClusterIssuer --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-prod ingress.kubernetes.io/ssl-redirect: "true" meta.helm.sh/release-name: repositorymanager meta.helm.sh/release-namespace: repositorymanagerwinter # Change value nginx.ingress.kubernetes.io/enable-cors: "false" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/rewrite-target: / name: repositorymanager-ingress spec: rules: - host: repositorymanager.yourdns.net # Change value http: paths: - backend: service: name: repositorymanager port: number: 80 path: / pathType: ImplementationSpecific tls: - hosts: - repositorymanager.yourdns.net # Change value secretName: repositorymanager-yourdns-net-cert # Change value
If you want to operate multiple instances of repositorymanager
service, they have to run in separate namespaces each of them with an own Ingress controller.
Access via Node Port
The following steps result in a configuration where the repositorymanager
service is exposed via Node Port to be accessible from outside the Kubernetes cluster.
Expose the repositorymanager
service via a Kubernetes Node port to the local network. In the example configuration shown in the code block below, the repositorymanager
service will be accessible in the local network by the IP address CLUSTER_IP:30036
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
kind: Service
apiVersion: v1
metadata:
name: repositorymanager
namespace: yuuvis
app: yuuvis
name: repositorymanager
yuuvis: 'true'
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8010
nodePort: 30036 # This should be unique value in range 30000-32767
selector:
name: repositorymanager
type: NodePort
Configuring the Cluster Firewall
The REPOSITORYMANAGER service, more precisely the barcode functionality, needs access directly from the pod where it is connected to the SAP® system. For this reason, a firewall entry needs to be added on cluster level to allow communication to the SAP® system.
Provide the IP:port info of the SAP® system that will have an RFC connection for the barcode functionality to work properly to the cluster administrator. The configurations have to be carried out on the KGS Administration Page that can be accessed via the following address: http://<host>/repositorymanager/cs/
The default port is 8010, the user name is admin
, and the password is admin
.
After logging in, you can change the login credentials via OSGi > Configuration > Application Framework Management Console:
Adjusting the Service Configuration
In case of a standard installation, the service configuration parameters are specified in the corresponding application.yml
file and are set to reasonable defaults. Those default values can be overwritten by specifying different values in the repositorymanager-prod.yml
configuration file. Especially, the parameters configuring the ActiveMQ connection have to be adjusted:
-
spring.activemq.broker-url
-
spring.activemq.user
-
spring.activemq.password
KGS/CS-Admins should limit the free access to SAP® systems to ensure that only relevant SAP® systems can store data for a certain tenant. |
Parameters of the repositorymanager-prod.yml
configuration file:
Property | Type | Description | Example value | Default value | ||
---|---|---|---|---|---|---|
|
String |
Default SAP® document type that is used if there is no barcode mapping for the yuuvis® Momentum content type (see |
TIF |
TIF |
||
|
String |
List of entries for mapping the barcode document type, separated by pipe characters. Entries consist of: yuuvis® Momentum content type, equals sign, SAP® document type. For each yuuvis® Momentum content type missing in the mapping list, the SAP® document type |
Image/TIFF=FAX|application/pdf=PDF |
Image/TIFF=FAX|application/pdf=PDF |
||
|
String |
Public URL of the yuuvis® Momentum authentication service. |
|
|
||
|
String |
Username of the technical user for the REPOSITORYMANAGER service’s access to yuuvis® Momentum.
|
|
|
||
|
String |
Password of the technical user for the REPOSITORYMANAGER service’s access to yuuvis® Momentum. |
|
|
||
|
String |
Tenant of the technical user for the REPOSITORYMANAGER service’s access to yuuvis® Momentum. |
|
|
||
|
String |
IP address and port used by ActiveMQ. |
|
|
||
|
String |
User name for ActiveMQ access. |
|
|
||
|
String |
Password for ActiveMQ access. |
|
|
The following code block shows an example configuration.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
repository-manager:
barcode:
cntType2docType: Image/TIFF=FAX|application/pdf=PDF
default-docType: TIF
core:
api:
url: https://client.con.yuuvis.org
username: root
password: optimal
tenant: default
spring:
activemq:
broker-url: tcp://repositorymanager-mq:61616
user: admin
password: admin
Multiple Instances of the 'repositorymanager' Service
If you use an Ingress controller, just create additional instances in separate namespaces with an own Ingress controller for each of them.
The following example deployment process is intended to explain the usage of multiple REPOSITORYMANAGER service instances exposed via Node port.
To achieve multi-tenancy, an independent instance of the REPOSITORYMANAGER service needs to be deployed for each individual tenant. The same service artifact can be used. In general, the following principles apply:
-
Each instance should have its own ActiveMQ pod, distributed as separate image.
-
Each pair of REPOSITORYMANAGER service and ActiveMQ instances should be deployed into its own namespace, have its own ports and profile configuration (default is prod).
-
Each pair of REPOSITORYMANAGER service and ActiveMQ must have its own tenant.
Namespaces, service ports and profiles should be specified in the deployment script. The following sections describe the required configuration steps. All scripts are applied via the command:
kubectl apply - f <filename>
Preparation
Decide on the namespace, and node ports to be used (one port for the REPOSITORYMANAGER service and two ports for the repositorymanager-mq service) as well as the profile in which the application will run (this determines the naming of the configuration file). For this example, the namespace will be repositorymanager-1, the ports are 30000 for the REPOSITORYMANAGER service, 30001 and 30002 for the ActiveMQ and the profile will be instance1. The cluster should use the repositorymanager app schema. The tenant to be used by the REPOSITORYMANAGER service should be created and configured to use it as described above for the configuration of a single instance.
Namespace
Create the namespace using the following YML script:
1
2
3
4
apiVersion: v1
kind: Namespace
metadata:
name: repositorymanager-1 # This is an example value that has to be replaced by the name of your namespace you want to use for the additional repositorymanager service instance.
ActiveMQ Service
Deploy the repositorymanager-mq
pod for ActiveMQ using the following two YML scripts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: repositorymanager-1 # Change value to the namespace specified in the namespace script before.
name: repositorymanager-mq
labels:
app: yuuvis
name: repositorymanager-mq
spec:
replicas: 1
selector:
matchLabels:
name: repositorymanager-mq
template:
metadata:
labels:
name: repositorymanager-mq
spec:
containers:
- image: docker.yuuvis.org/<image> # Change value
name: repositorymanager-mq
imagePullPolicy: Always
restartPolicy: Always
imagePullSecrets:
- name: changeme # Change value
This is an example script which requires the a specific secret to be present in the same namespace. Different clusters might require some changes. |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: Service
metadata:
namespace: repositorymanager-1
name: repositorymanager-mq
labels:
app: yuuvis
name: repositorymanager-mq
spec:
selector:
name: repositorymanager-mq
ports:
- name: dashboard
port: 8161
nodePort: 30001
- name: openwire
port: 61616
nodePort: 30002
type: NodePort
The ActiveMQ service exposes two ports, one to access the web admin page, internally on port 8161 and externally on 30001, the other to access the ActiveMQ itself, internally on port 61616 and externally on 30002. |
Deployment of 'repositorymanager' Service
Deploy the repositorymanager
service using the following two YML scripts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-repositorymanager
namespace: repositorymanager-1
spec:
storageClassName: local-path
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: repositorymanager-1
labels:
app: yuuvis
name: repositorymanager
name: repositorymanager
spec:
replicas: 1
selector:
matchLabels:
name: repositorymanager
template:
metadata:
labels:
name: repositorymanager
spec:
containers:
- name: repositorymanager
image: docker.optimal-systems.org/team-kookaburra/repositorymanager-momentum:commit-2d346b0e
imagePullPolicy: Always
env:
- name: JAVA_OPTS
value: -Xmx128m
- name: SPRING_CLOUD_CONFIG_URI
value: "http://configservice.yuuvis/config"
- name: SPRING_PROFILES_ACTIVE
value: instance1,docker,kubernetes
ports:
- containerPort: 8010
volumeMounts:
- name: storage
mountPath: /working-dir
volumes:
- name: storage
persistentVolumeClaim:
claimName: data-repositorymanager
restartPolicy: Always
imagePullSecrets:
- name: osgitlab
This script uses the image from OS GitLab which requires the osgitlab secret to be present in the same namespace. Different clusters might require some changes. Additionally, the environment parameter SPRING_CLOUD_CONFIG_URI should point to the configservice of the specific cluster. The SPRING_PROFILES_ACTIVE environment variable should contain the docker and kubernetes profiles as well as the service profile dedicated to that instance, in this case instance1.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Service
metadata:
namespace: repositorymanager-1
labels:
app: yuuvis
name: repositorymanager
yuuvis: "true"
name: repositorymanager
spec:
ports:
- name: "http"
port: 80
targetPort: 8010
nodePort: 30000
type: NodePort
selector:
name: repositorymanager
The REPOSITORYMANAGER service exposes one port to allow internal access via port 8010 and external access via port 30000. |
Configuration via 'configservice'
Use the configservice
of the cluster to create the repositorymanager-instance1.yml
file. This file contains the configuration for the service instance running with the profile instance1.
The following code block shows an example for the configuration:
1
2
3
4
5
6
7
8
9
10
core:
api:
url: http://client.yuuvis
username: root
password: optimal
tenant: instance1tenant
spring:
activemq:
broker-url: tcp://repositorymanager-mq:61616
The tenant name as well as credentials to access the yuuvis® Momentum system are provided as well as the URLs to access the system and ActiveMQ.
Once the configuration is created, the REPOSITORYMANAGER service should be restarted to apply the changes.
Access
Once the service is deployed and configured, a reverse proxy should be created to allow two-way communication between the REPOSITORYMANAGER service and SAP. This will also allow access to the KGS admin panel for service configuration.
7.2.2. Configuration
After installing the repositorymanager
service, further configurations of yuuvis® Momentum and the SAP® system are required.
Configuring the App Schema
The REPOSITORYMANAGER service requires the repositorymanager app schema shown in the code block below. It is imported to yuuvis® Momentum via the endpoint POST /api/system/apps/{app}/schema
.
The app schema contains the document object type definitions archiveLinkComponent
and ilmObject
.
Properties of 'archiveLinkComponent'
Objects of type archiveLinkComponent
will be used both for documents (logical placeholders) and components (actual documents with content). It contains metadata related to ArchiveLink documents and ArchiveLink components.
Property | Type | Description |
---|---|---|
|
String |
Date of creation |
|
String |
Time of creation |
|
String |
Date of the last modification |
|
String |
Time of the last modification |
|
String |
Name of the content repository. Maximum length is 30 characters. |
|
String |
ArchiveLink log version number (e.g., 0046) |
|
String |
Document protection: user-defined combination of the |
|
String |
Specifies that the document has to be retained due to legal reasons (legal hold), thus preventing the document or its components from being deleted. This property was introduced with component version 7.0. It is enabled for specific scenarios only. |
|
String |
Retention period for the document and its components. This property was introduced with component version 7.0. It is enabled for specific scenarios only. |
|
String |
Temporary unique ID that can be used to assign a document object located in yuuvis® Momentum to a business transaction in the SAP® system. |
|
Boolean |
This document flag indicates whether the barcode and thus the document have already been reported to SAP. |
|
Boolean |
Will be set to true in case KGS reports an error. |
|
String |
Component ID ( |
|
String |
MIME type ( |
|
String |
File name of the source file. As this name is always filed through Apache Tomcat’s working directory, the name is always a temporary file name. |
|
String |
Version number of the application (e.g., 1.0) |
|
String |
Character set |
|
String |
Compression with gzip is performed by the content server for components with a size that exceeds the adjustable threshold value CompressionSize. This offers advantages for storing, especially for storing print lists that have an uncompressed size bigger than 2 GB. By this compression, they are usually reduced to 10% of the original size. With this administrative information, the content server is able to determine the uncompressed size of the component and which compression parameters have been used. |
Properties of 'ilmObject'
The objects of type ilmObject
have the common ILM properties (URL and properties table), as well as a content length property and a type property.
Property |
Type |
Description |
|
string |
Specifies the ILM object type. Available values:
|
|
integer |
Content size in Bytes 0 for ILM collections |
|
table |
Table with name and value columns of type string |
|
string |
URL of the ILM object |
Combination with Library-based Client
If a client application for yuuvis® Momentum is used that is based on our developer libraries, the IDs of properties and object types should be localized.
An example key-value mapping is shown in the following code block.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"appRepositorymanager:Contentrepository_label": "Content Repository",
"appRepositorymanager:ArchiveLinkversion_label": "Archive Link Version",
"appRepositorymanager:Documentprotection_label": "Document Protection",
"appRepositorymanager:DocID_label": "Document ID",
"appRepositorymanager:Creationdate_label": "Creation Date",
"appRepositorymanager:Creationtime_label": "Creation Time",
"appRepositorymanager:Datelastmodification_label": "Last Modified Date",
"appRepositorymanager:Timelastmodification_label": "Last Modified Time",
"appRepositorymanager:Legalholdlock_label": "Legal Hold Lock",
"appRepositorymanager:Expirationdate_label": "Expiration Date",
"appRepositorymanager:Barcode_label": "Barcode",
"appRepositorymanager:BarcodesenttoR3_label": "Barcode Sent to R3",
"appRepositorymanager:BarcodeProcessingError_label": "Barcode Processig Error",
"appRepositorymanager:CompID_label": "Component ID",
"appRepositorymanager:Contenttype_label": "Content Type",
"appRepositorymanager:Filename_label": "File Name",
"appRepositorymanager:Applicationversion_label": "Application Version",
"appRepositorymanager:Charset_label": "Chartset",
"appRepositorymanager:Compressionstring_label": "Compression String",
"appRepositorymanager:archiveLinkComponent_label": "ArchiveLink object type",
"appRepositorymanager:archiveLinkComponent_description": "Type used for ArchiveLink documents and components",
"appRepositorymanager:timestampProperties_label": "Timestamp properties",
"appRepositorymanager:componentProperties_label": "Component properties",
"appRepositorymanager:documentProperties_label": "Document properties",
"appRepositorymanager:type_label": "Type",
"appRepositorymanager:url_label": "URL",
"appRepositorymanager:properties_label": "Properties",
"appRepositorymanager:contentlength_label": "Content Length",
"appRepositorymanager:ilmObject_label": "ILM object type",
"appRepositorymanager:ilmObject_description": "Type used for ILM collections and resources"
}
Configuration of the KGS SAP® Connector
Open the KGS Administration Page as described in the installation guide for the REPOSITORYMANAGER service. Go to Main > KGS SAP® Connector.
An SAP® connector is required for the RFC configuration later on.
In the Configuration Editor, configure a debug level between 0 and 4. For productive systems, value 0 is usually set.
The barcode scenario is set up with the following steps.
-
Create a bridge connection via Main > KGS SAP Connector > Bridge Status > Generate Bridge.
-
Create a connection via Main > KGS SAP Connector > Add config.
-
Edit the connection via Main > KGS SAP Connector > Edit. The following information needs to be entered: Description, SAP AS Host, SAP System Number, SAP Client, SAP User, SAP User Password, SAP Language
-
Configure the repositories via Main > Contentserver4ArchiveLink > Edit and adjust the values in the following tabs:
-
License - Specify the KGS-license key.
-
Barcode - Tick the Enable Barcode checkbox.
-
Protocol - For normal work mode, untick all checkboxes.
-
Common - Adjust only the debug level if necessary.
-
Security
-
Configure the default security level for the communication between SAP® and embedded tomcat:
0
certificate is not used
1
certificate is used, but not validated
2
certificate is used and validated
We recommend level 2 for productive systems.
-
Specify the clients that should be allowed to change the certificate via Allowed CSAdmin Clients. Avoid the use of a wildcard. Specify only the needed IP addresses instead.
-
-
RFC - Choose one of the connections you configured before.
-
Components - Usually no changes needed. In case you see a need, please contact your OS or KGS consultant.
-
Backend - Usually no changes needed. In case you see a need, please contact your OS or KGS consultant.
-
Content - Usually no changes needed. In case you see a need, please contact your OS or KGS consultant.
-
Index Export - If barcode upload is used, the time period for requesting new barcodes can be adjusted here. Please ensure that the period in productive systems is long enough to avoid overlapping runs (1800 s recommended).
-
ILM - Set
ILM
for the ILM Repository. Enter the user name and password of an existing SAP® account that should be used for the connection.
-
-
Assign a configuration at repository level or global level via Main > ContentServer4ArchiveLink > Edit > RFC > RFC Connection Name. The barcode configuration you create will be assigned. To use barcode synchronization from multiple SAP® systems, remove any global barcode configuration and use the configuration at repository level instead.
-
Repository level:
-
Global level:
-
-
Enable barcode via Main > ContentServer4ArchiveLink > Edit Configuration > Barcode > Enable barcode.
-
Define the barcode timer via Main > ContentServer4ArchiveLink > Edit Configuration > Index Export > BarcodeTimer. Recommended: 60 (seconds)
-
SAPMimeExtensionLookup
needs to be enabled to be able to correctly assign file formats to document types. EnableSAPMimeExtensionLookup
via Main > ContentServer4ArchiveLink > Edit Configuration > Common > SAPMimeExtensionLookup
KGS Logging
In the default configuration, KGS a log is created once per day. The log files are stored with a retention time of 365 days.
Configuration of the SAP® System
To connect the SAP® system with the HTTP content server and make all necessary settings, we recommend following the SAP® guidelines using the SPRO transaction under Netware > Application Server > Basis Services > ArchiveLink.
To customize the interface for print lists and outbound documents, we recommend attending the SAP® course BIT615. To file reorg data, we recommend attending the SAP® course BIT660.
The main transactions required to establish a connection are listed below:
Transaction OAC0 defines one or several repositories.
This and all further activities within the SAP® system have to be carried out by the SAP® system administrator or another authorized user of the customer.
These activities include:
-
For the first time:
-
Creation of a communication user (SU01) with the corresponding authorizations (SAP_BC_ENDUSER, SAP_BC_SRV_ARL_ADMIN, SAP_BC_SRV_ARL_USER, SAP_BC_SRV_COM_ADMIN)
-
ArchiveLink: maintenance of basic settings (OAG1)
-
Creation of number range intervals (OANR) for print lists
-
Create log (OAA3) or import prepared transports from OPTIMAL SYSTEMS with the log.
-
Creation of an archive device (name ARCH) as output device (SPAD), assignment of the SAP ArchiveLink archiver, hostspool access method (I: archiver)
-
-
One or several times; depending on how many content repositories have to be defined:
-
Creation of a content repository (OAC0)
DocArea
ArchiveLink
Filing method
HTTP content server
Log
OPTIMALA
Version no.
0046 or 0047
http script
cs/contentserver
Output device
ARCH
HTTP server
name or IP address of the server on which yuuvis® Momentum REPOSITORYMANAGER is running
Port number
The port used to access yuuvis® Momentum REPOSITORYMANAGER (default: 8010).
-
After successful configuration of yuuvis® Momentum REPOSITORYMANAGER, the certificate (OAC0/CSADMIN) has to be sent and activated for each repository.
-
7.3. CMIS Interface
As of version 2024 Spring.
The repositorymanager-cmis
service is an implementation of the CMIS standard. It is a microservice solution for connecting to SAP® S/4 and SAP® BTP, and implements a set of interfaces required by SAP®.
An SAP® system communicates via the WEB with the assigned CMIS service via the Business Technology Platform (BTP) provided by SAP.
The following services and required methods of the CMIS interface are supported. Support of further methods cannot be guaranteed and might change in the future.
CMIS service | Methods |
---|---|
|
|
|
|
|
|
|
|
|
|
7.3.1. Configuration
Configuring the App Schema
Download the XML file and apply it as app schema for the cmis
app. Enable the app for each tenant that should be able to use it.
The schema contains only property definitions and secondary object type definitions (SOTs). Some of them define general CMIS types, others are specific for SAP.
As :
and _
characters are not allowed in type IDs, the repositorymanager-cmis
service replaces them by 0 and 1 respectively. Thus, the resulting CMIS-specific SOTs are:
SOT | Description | Properties |
---|---|---|
|
Contains common properties of all CMIS objects. |
|
|
Represents a CMIS folder. |
- |
|
Represents a CMIS item. |
- |
|
Represents a CMIS document. It has properties used for versioning. |
|
|
The base type for all CMIS secondary types. |
- |
|
Used by SAP® to set holds on a document. |
|
All other types in the schema start with sapBo
and represent SAP® business objects.
Service Configuration of 'repositorymanager-cmis'
The repositorymanager-cmis
service internally uses rmcmis
as spring application name. As the service runs with the prod
profile,
it loads the rmcmis-prod.yml
configuration file that can contain the following parameters:
Parameter | Type | Description | Example value |
---|---|---|---|
|
String |
Username that the CMIS client needs to access yuuvis® Momentum. |
|
|
String |
Password that the CMIS client needs to use. |
|
|
String |
URL of the yuuvis core API. Default: |
|
|
String |
URL of the yuuvis config service. Default: |
|
|
String |
URL of the yuuvis® Momentum to be used by the technical user. |
|
|
String |
Tenant of the technical user that |
|
|
String |
Username of the technical user that |
|
|
String |
Password of the technical user that |
|
|
String |
Host where ClamAV is deployed. Most likely it will be a pod in the same namespace. If deployment is in a different namespace, include the full path to it. |
|
|
Int |
Port on which ClamAV is exposed. |
3310 |
|
String |
Platform on which ClamAV is deployed. Valid values are |
|
|
String |
Configuration parameter provided by Spring Boot frameworks, enables configuring service log level. Exact format of the property is given in the sample configuration file in the attachment of this page. Default: |
|
Access Configuration
For the repositorymanager-cmis
service, a cross-tenant service account is required. Its credentials are configured in the service’s deployment during installation.
Ingress Setup
As requests from SAP® to yuuvis® Momentum do not contain the tenant, the ingress must be configured such that it enriches those requests with the X-ID-TENANT-NAME
header.
The tenant header is only added if /repositorymanager/
is part of the endpoint URL. This URL should be adjusted to the naming of the gateway-route (see Gateway section).
nginx.ingress.kubernetes.io/configuration-snippet: |
add_header set-cookie 'tenant=sapcmis; Path=/; SameSite=Lax';
access_by_lua_block
{
if string.find(ngx.var.request_uri,"/repositorymanager/") ~= nil then ngx.req.set_header("X-ID-TENANT-NAME", "sapcmis") end
}
The ingress controller should be configured to target the authentication
service within the cluster.
Endpoint Configuration
The repositorymanager-cmis
service’s internal endpoints are accessible via https://<ingress-url>/repositorymanager/*
paths. They have to be added to the authorization.accesses
list in the authentication-prod.yml
configuration file.
Identity Provider Configuration
In the identity provider used by yuuvis® Momentum for authentication, enable requests to the ingress controller URL. For example, if Keycloak is used, set Redirect URIs and Web origins.
Storage Configuration
Each tenant that uses the CMIS interface needs an own storage configuration. On the Git server that manages all yuuvis® Momentum configuration files, create a repositories.json
file for each of those tenants.
Use the cluster-internal endpoint POST /system/api/resources/{resourceName}/path/{pathName}
with the following path parameter values:
-
repositories.json
as value forresourceName
-
|tenant|sapcmis|apps|rmcmis
value forpathName
(for thesapcmis
example tenant)
The request body contains the JSON configuration file as shown in the following example:
{
"repository-names": "Repo1,Repo2,Repo3"
}
7.3.2. Installation
Please see the installation guide.
7.3.3. Logging
All tenant-specific logs are prefixed with tenant[{tenantName}]
.
7.4. Implementation of SAP® ILM Protocol
As of version 2024 Summer.
To use the SAP® ILM functionality, connect to the SAP® ILM controller via repositorymanager-ilm
service.
Please check the supported SAP® versions.
Using retention propagation
If retention propagation functionality is desired (i.e. propagating retention to ArchiveLink documents), the repositorymanager-ilm service has to be combined with repositorymanager service with enabled ArchiveLink functionality.
|
7.4.1. Configuration
App Schema
The repositorymanager-ilm
service requires the app schema for the repositorymanager
app.
Parameters
The repositorymanager-ilm
service internally uses rmilm
as spring application name. As the service runs with the prod
profile,
it loads the rmilm-prod.yml
configuration file that can contain the following parameters:
Property | Type | Description | Example value |
---|---|---|---|
|
String |
ILM controller prefix which determines the path Default is |
|
|
String |
URI of the yuuvis® Momentum API gateway. Default is |
|
Ingress Setup
As requests from SAP® to yuuvis® Momentum do not contain the tenant, the ingress has to be configured such that it enriches those requests with the X-ID-TENANT-NAME
header.
nginx.ingress.kubernetes.io/configuration-snippet: |
add_header set-cookie 'tenant=sapilm; Path=/; SameSite=Lax';
access_by_lua_block
{
if string.find(ngx.var.request_uri,"/cs/ilm") ~= nil then ngx.req.set_header("X-ID-TENANT-NAME", "sapilm") end
}
The ingress controller should be configured to target the authentication
service within the cluster.
Endpoint Configuration
The repositorymanager-ilm
service’s internal endpoints are accessible via /repositorymanager-ilm/*
paths. They have to be added to the authorization.accesses
list in the authentication-prod.yml
configuration file.
As the connection uses WebDAV, the HTTP methods used by WebDAV have to be added as for controlling access to external services via authentication
service.
Identity Provider Configuration
In the identity provider that is used by yuuvis® Momentum for authentication, enable requests to the ingress controller URL. For example, if Keycloak is used, set Redirect URIs and Web origins.
7.4.2. Installation
Please see the installation guide.
7.4.3. Logging
All tenant-specific logs are prefixed with tenant[{tenantName}]
.
8. AI Platform
The Artificial Intelligence Platform is a set of APIs and tools that enable customers to set up and use AI functionalities by themselves, yet with low costs and high performance.
Customers can provide their own documents, train models using different algorithms provided by OPTIMAL SYSTEMS GmbH, evaluate trained models, and deploy to make predictions.
Every part of the AI Platform can be deployed on-premises or in the cloud.
8.1. Platform Overview
The artificial intelligence (AI) platform consists of two services.
-
The
kairos-api
service for the operation of the machine learning (ML) pipeline that provides models and -
the
predict-api
service for actual AI predictions based on the models.
The kairos-api
service can be connected to any document management system. In this documentation, only the combination with yuuvis® Momentum is considered. The models created and trained by the ML pipeline can be deployed to any Kubernetes cluster and used by any custom service.
The predict-api
service is a solution for the usage of pipeline-built models. It is used to integrate the AI functionality into the developer libraries for yuuvis® Momentum client applications.
8.2. API for AI Features
The predict-api
service provides the API for the retrieval of AI predictions. It calls the appropriate machine learning models, improves and validates results returned by the ML models, and finally creates responses for the calling party according to rules set in the inference schema.
The endpoints of the predict-api
service are provided in an own API that can be called by client applications.
-
Document Classification:
-
In the context of the AI platform, classification means the determination of suitable typification classes fitting for an object based on its full-text or PDF rendition. For one object, one prediction is provided that contains mappings of classes and their corresponding relevance probability as well as a reference on the object in yuuvis® Momentum via
objectId
. -
Instead of the class names used internally in the
predict-api
service, the prediction response bodies provide the object types as referenced in the inference schema.
-
-
Metadata Extraction:
-
The
predict-api
service can analyze the PDF rendition of binary content files assigned to objects in yuuvis® Momentum to extract specific metadata. Based on the models trained viakairos-api
service, predictions for values of specific object properties can be determined. The object properties must be listed in the inference schema where conditions for the values and settings for the prediction responses are also specified.
-
8.2.1. Endpoints of 'predict-api'
The endpoints allow for the development of client applications with integrated AI functionality.
All endpoints are available via the Swagger UI https://<host>/predict-api/swagger-ui.html
.
Object Classification
GET /predict-api/api/classification/{objectId}
- Retrieve classification prediction for a single object
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
Content-Type: application/json
X-ID-TENANT-NAME: tenant_name
- Description
-
Retrieves a classification prediction for a single object identified by its
objectId
.The object type IDs will be returned as defined in the inference schema along with their probability in percentage (level of confidence) in the
properties
section of the JSON response body.The response JSON further contains the
predictionId
that should be used for giving feedback to thepredict-api
service on the quality of received predictions, as well as thesystem:objectId
that was specified in the request URL.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/classification/da20c2fb-8071-45e9-b4bf-2af376cdf9b7
no request body
- Response Example
-
{ "predictions": [{ "properties": { "appImpulse:receiptsot|appImpulse:receiptType|Rechnung" : { "probability": 85.45 }, "appImpulse:receiptsot|appImpulse:receiptType|Order": { "probability": 12.35 }, "appImpulse:hrsot|appImpulse:hrType|Bewerbung": { "probability": 1.20 }, "Class4": { "probability": 0.98 }, "Class5": { "probability": 0.02 } }, "system:objectId": "da20c2fb-8071-45e9-b4bf-2af376cdf9b6", "predictionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }] }
POST /predict-api/api/classification
- Retrieve classification prediction for multiple objects
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Request Header
-
Content-Type: application/json
X-ID-TENANT-NAME: tenant_name
- Description
-
Retrieves classification predictions for multiple objects identified by their
objectId
specified in the JSON request body.The endpoint will return a JSON structure containing a list of
predictions
, one for eachobjectId
. Each individual prediction sub-structure is structured as already described for the endpointGET /predict-api/api/classification/{objectId}
.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/classification
{ "objects": [{ "properties": { "system:objectId": { "value": "da20c2fb-8071-45e9-b4bf-2af376cdf9b6" } } }, { "properties": { "system:objectId": { "value": "r6s5c2fb-1234-88e9-b4bf-2af376cdf7y7" } } }] }
- Response Example
-
{ "predictions": [{ "properties": { "Class1": { "probability": 98.45 }, "Class2": { "probability": 12.77 }, "Class3": { "probability": 1.38 }, "Class4": { "probability": 0.99 }, "Class5": { "probability": 0.02 } }, "system:objectId": "da20c2fb-8071-45e9-b4bf-2af376cdf9b6", "predictionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }, { "properties": { "Class1": { "probability": 81.23 }, "Class2": { "probability": 10.42 }, "Class3": { "probability": 2.97 }, "Class4": { "probability": 0.86 }, "Class5": { "probability": 0.01 } }, "system:objectId": "r6s5c2fb-1234-88e9-b4bf-2af376cdf7y7", "predictionId": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }] }
POST /predict-api/api/classification/feedback
- Send classification feedback to Model Serving
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Request Header
-
Content-Type: application/json
X-ID-TENANT-NAME: tenant_name
- Description
-
Sends feedback to the ML Pipeline informing about the user decision for one of the object types suggested in a prediction.
After the classification is done and the predicted document types are shown to the user, the user decides which one is the correct type and stores it. It is important to inform the ML Pipeline about this decision so it can be analyzed by Data scientists and that they can improve future models behavior.
In the JSON request body, the following parameters are expected:
Parameter Description predictionId
ID returned by the classification retrieval endpoints.
feedbackData.objectTypeId.value
ID of the object type selected by the user.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Request is bad.
403
Forbidden
404
Specified
predictionId
was not found.415
Unsupported Media Type
500
Internal Server Error: Error while storing feedback.
- Request Example
-
/predict-api/api/classification/feedback
{ "properties": { "predictionId": { "value":"3fa85f64-5717-4562-b3fc-2c963f66afa6" }, "feedbackData":{ "objectTypeId": { "value": "Rechnung" } } } }
- Response Example
-
(1) Successful
200 OK
(2) Not successful
400 Bad Request
{ "statusCode": 400, "timestamp": "2020-12-25T09:42:33.386+00:00", "message": "JSON parse error: Unrecognized field \"objectTyyyyypeId\" (class com.os.ai.predict.domain.classification.ClassificationFeedbackRequestData), not marked as ignorable..." }
POST /predict-api/api/classification/file
- Retrieve classification prediction for PDF
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
Content-Type: application/json
X-ID-TENANT-NAME: tenant_name
- Description
-
Retrieves classification predictions based on a PDF file. The file should be, e.g. a PDF rendition of a binary content file.
The endpoint will return a JSON structure containing a list of
predictions
with one entry that is structured as described for the endpointGET /predict-api/api/classification/{objectId}
.In this scenario, the document is not located in yuuvis® Momentum, so there is no objectId and yuuvis® Momentum features are not used.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/classification/file
Request BodyBinary content of PDF document
- Response Example
-
Response Body
{ "predictions": [{ "properties": { "Class1": { "probability": 98.45 }, "Class2": { "probability": 12.77 }, "Class3": { "probability": 1.38 }, "Class4": { "probability": 0.99 }, "Class5": { "probability": 0.02 } }, "predictionId": "3fa85f64-5717-4562-b3fc-2c963f66afa7", "system:objectId": {} }] }
Metadata Extraction
GET /predict-api/api/extraction/{objectId}
- Retrieve extraction prediction for a single object
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
Content-Type: application/json
X-ID-TENANT-NAME: tenant_name
- Description
-
Retrieves a metadata extraction prediction for the binary content file of a single object identified by its
objectId
.The property IDs will be returned according to the inference schema along with their probability in percentage (level of confidence) in the
properties
section of the JSON response body. The propertiespage
andboundingBox
(coordinates on thepage
) describe the location within the binary content file where the decisive information was identified.The response JSON further contains the
predictionId
that should be used for giving feedback to thepredict-api
service on the quality of received predictions, as well as thesystem:objectId
that was specified in the request URL.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/extraction/da20c2fb-8071-45e9-b4bf-2af376cdf9b6
no request body
- Response Example
-
Response Body
{ "predictions": [{ "properties": { "appAIInvoice:aiiCompanyName": [ { "value": "Lufthansa", "probability": 99.24, "boundingBox": [ 403, 729, 61, 14 ], "page": 0 }, { "value": "AKG Thermotechnik International GmbH & Co.KG", "probability": 93.24, "boundingBox": [ 413, 224, 93, 14 ], "page": 1 } ], "appAIInvoice:aiiIssueDate": [ { "value": "2018-01-26", "probability": 85.12, "boundingBox": [ 213, 234, 76, 14 ], "page": 1 } ] }, "system:objectId": "da20c2fb-8071-45e9-b4bf-2af376cdf9b6", "predictionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }] }
POST /predict-api/api/extraction
- Retrieve extraction prediction for multiple objects
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
Content-Type: application/json
X-ID-TENANT-NAME: tenant_name
- Description
-
Retrieves metadata extraction predictions for the binary content files of multiple objects identified by their objectId specified in the JSON request body.
The endpoint will return a JSON structure containing a list of
predictions
, one for eachobjectId
. Each individual prediction sub-structure is structured as described for the endpointGET /predict-api/api/extraction/{objectId}
.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/extraction
Request Body{ "objects": [{ "properties": { "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" } } }, { "properties": { "system:objectId": { "value": "da20c2fb-8071-45e9-b4bf-2af376cdf9b6" } } }] }
- Response Example
-
Response Body
{ "predictions": [{ "properties": { "appAIInvoice:aiiCompanyName": [ { "value": "Lufthansa", "probability": 99.24, "boundingBox": [ 403, 729, 61, 14 ], "page": 0 }, { "value": "AKG Thermotechnik International GmbH & Co.KG", "probability": 93.24, "boundingBox": [ 413, 224, 93, 14 ], "page": 1 } ], "appAIInvoice:aiiIssueDate": [ { "value": "2018-01-26", "probability": 85.12, "boundingBox": [ 213, 234, 76, 14 ], "page": 1 } ] }, "system:objectId": { "value": "cdc7095f-a5ce-486d-92a7-6d0955d969ee" }, "predictionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }, { "properties": { "appAIInvoice:aiiCompanyName": { "value": "Mercedes", "probability": 83.11 }, "appAIInvoice:aiiIssuedDate": { "value": "2009-10-12", "probability": 97.14, "boundingBox": [ 313, 424, 73, 14 ], "page": 0 } }, "system:objectId": { "value": "da20c2fb-8071-45e9-b4bf-2af376cdf9b6" }, "predictionId": "r6s5c2fb-1234-88e9-b4bf-2af376cdf7y7" }] }
POST /predict-api/api/extraction/feedback
- Send extraction feedback to Model Serving
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
HTTP status code
- Request Header
-
Content-Type: application/json
X-ID-TENANT-NAME: tenant_name
- Description
-
Sends feedback to the ML Pipeline informing about the user decision for one of the property values suggested in a prediction.
After metadata extraction is done and the predicted property values are shown to the user, the user decides on the validity of those data by accepting them or changing the shown values. It is important to inform the ML Pipeline about this decision so it can be analyzed by data scientists and that they can improve future models behavior.
In the JSON request body, the following parameters are expected:
Parameter Description predictionId
ID returned by the extraction retrieval endpoints.
feedbackData
Values for all properties the user was able to modify after retrieving the prediction (e.g.,
aiInvoiceNumber
,aiCompanyName
,aiAmount
,aiIssuedDate
):value
value selected/entered by the user
boundingBox
Optional, coordinates of the selected value on the page within the binary content file
page
Optional, page number where the value was found within the binary content file
Response HTTP status codes:
HTTP status code Meaning 200 OK
Feedback is logged successfully.
400 Bad request
Request is bad.
403 Forbidden
404 Not Found
Specified
predictionId
was not found.415 Unsupported Media Type
500 Internal Server Error
Error while storing feedback.
If an error is thrown, a JSON structure is returned as response body.
- Request Example
-
/predict-api/api/extraction/feedback
{ "properties": { "predictionId": { "value":"3fa85f64-5717-4562-b3fc-2c963f66afa6" }, "feedbackData": [ { "propertyName": "aiInvoiceNumber", "value": "RWTÜV", "boundingBox":[123, 222, 33, 14], "page": 1 }, { "propertyName": "aiCompanyName", "value": "CompanyName" }, { "propertyName": "aiAmount", "value": "234.44" }, { "propertyName": "aiIssuedDate", "value": "10.4.2020" } ] } }
- Response Example
-
(1) Successful
200 OK
(2) Not successful
400 Bad Request
{ "statusCode": 400, "timestamp": "2020-12-25T09:42:33.386+00:00", "message": "JSON parse error: Unrecognized field \"aiCompanssyName\" (class com.os.ai.predict.domain.extraction.ExtractionFeedbackRequestData), not marked as ignorable..." }
POST /predict-api/api/extraction/file
- Retrieve extraction prediction for PDF
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
Content-Type: application/json
X-ID-TENANT-NAME: tenant_name
- Description
-
Retrieves an extraction prediction based on a PDF file that is passed in the request body.
The endpoint will return a JSON structure containing a list of
predictions
with one prediction that is structured as already described for the endpointGET /predict-api/api/extraction/{objectId}
.In this scenario, the document is not located in yuuvis® Momentum, so there is no
objectId
and yuuvis® Momentum features are not used.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/extraction/file
Request BodyBinary content of PDF document
- Response Example
-
Response Body
{ "predictions": [{ "properties": { "appAIInvoice:aiiCompanyName": [ { "value": "Lufthansa", "probability": 99.24, "boundingBox": [ 403, 729, 61, 14 ], "page": 0 }, { "value": "AKG Thermotechnik International GmbH & Co.KG", "probability": 93.24, "boundingBox": [ 413, 224, 93, 14 ], "page": 1 } ], "appAIInvoice:aiiIssueDate": [ { "value": "2018-01-26", "probability": 85.12, "boundingBox": [ 213, 234, 76, 14 ], "page": 1 } ] }, "system:objectId": {}, "predictionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }] }
Dictionary Management
GET /predict-api/api/admin/dictionaries/{dictionaryId}
- Retrieve all records
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves all record from the Elasticsearch dictionary identified by its
dictionaryId
.Parameters in the JSON response body:
Parameter Type Description id
string
Unique elasticsearch record identifier
companyName
string
Name of already known company that will be used for comparison with the one extracted by the model
fullAddress
string
Address of that company
tenant
string
Tenant for which this company name is valid
Response HTTP status codes:
+
HTTP status code | Meaning |
---|---|
200 |
OK |
400 |
Bad Request |
403 |
Forbidden |
404 |
Not Found |
415 |
Unsupported Media Type |
500 |
Internal Server Error |
- Request Example
-
/predict-api/api/admin/dictionaries/company_name_dictionary
- Response Example
-
200 OK
Response Body[ { "id": "55c3270e-0d10-4222-a458-c9b0030dedcc", "companyName": "TestCompany1", "fullAddress": "testAddress1", "tenant": "tenant1" }, { "id": "d519e595-1c10-4bdc-a850-efdf44d5ce69", "companyName": "TestCompany2", "fullAddress": "testAddress2", "tenant": "tenant1" } ]
DELETE /predict-api/api/admin/dictionaries/{dictionaryId}
- Delete all records
- As of Version
-
2022 Winter
- Request Method
-
DELETE
- Response Format
-
HTTP status code
- Description
-
Deletes the records in the Elasticsearch dictionary identified by its
dictionaryId
. Dictionary represents elasticsearch index.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/admin/dictionaries/company_name_dictionary
- Response Example
-
200 OK
POST /predict-api/api/admin/dictionaries/{dictionaryId}/batchupdate
- Create or update multiple records
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Saves the records specified in a CSV file in the Elasticsearch dictionary identified by its
dictionaryId
.CSV file should contain 3 columns in this order (
id
,companyName
,fullAddress
) and values separated by;
.Tenant information is taken directly from the logged in user.
Parameters in the JSON response body:
Parameter Type Description id
string
Unique elasticsearch record identifier
companyName
string
Name of already known company that will be used for comparison with the one extracted by the model
fullAddress
string
Address of that company
tenant
string
Tenant for which this company name is valid
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/admin/dictionaries/company_name_dictionary/batchupdate
CSV file as input
text/csv
in the request body header - Response Example
-
200 OK
Response Body[ { "id": "55c3270e-0d10-4222-a458-c9b0030dedcc", "companyName": "TestCompany1", "fullAddress": "testAddress1", "tenant": "tenant1" }, { "id": "d519e595-1c10-4bdc-a850-efdf44d5ce69", "companyName": "TestCompany2", "fullAddress": "testAddress2", "tenant": "tenant1" } ]
POST /predict-api/api/admin/dictionaries/{dictionaryId}/entries
- Create single record
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Saves a record specified in the JSON request body in the Elasticsearch dictionary identified by its
dictionaryId
.id
is automatically generated and tenant information is taken from currently logged in user.Parameters in the JSON request body:
Parameter Type Description companyName
string
Name of already known company that will be used for comparison with the one extracted by the model
fullAddress
string
Address of that company
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/admin/dictionaries/company_name_dictionary/entries
Request body{ "companyName": "string", "fullAddress": "string" }
- Response Example
-
200 OK
Response Body{ "id": "55c3270e-0d10-4222-a458-c9b0030dedcc", "companyName": "TestCompany1", "fullAddress": "testAddress1", "tenant": "tenant1" }
POST /predict-api/api/admin/dictionaries/{dictionaryId}/entries/{entryId}
- Update specified record
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Update a record specified by its entryId with the data passed in the JSON request body in the Elasticsearch dictionary identified by its
dictionaryId
.If the record with specified entryId does not exist, a new one will be created.
Parameters in the JSON request body:
Parameter Type Description companyName
string
Name of already known company that will be used for comparison with the one extracted by the model
fullAddress
string
Address of that company
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/admin/dictionaries/company_name_dictionary/entries/1
Request body{ "companyName": "string", "fullAddress": "string" }
- Response Example
-
200 OK
Response Body{ "id": "1", "companyName": "TestCompany1", "fullAddress": "testAddress1", "tenant": "tenant1" }
DELETE /predict-api/api/admin/dictionaries/{dictionaryId}/entries/{entryId}
- Delete specified record
- As of Version
-
2023 Winter
- Request Method
-
DELETE
- Response Format
-
JSON
- Description
-
Deletes a record specified by its
entryId
from the Elasticsearch dictionary identified by itsdictionaryId
.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/admin/dictionaries/company_name_dictionary/entries/1
- Response Example
-
200 OK
Model Performance Metrics
Calculation of performances for different models.
POST /predict-api/api/admin/history/models/{modelid}/performance
- Retrieve tenant model performance.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Retrieves the tenant model performances specified by parameters. System context models used for the currently active tenant are also valid.
Parameters in the JSON request body:
Parameter Type Description startDate
LocalDateTime
Desired start date for getting records from the database
endDate
LocalDateTime
Desired end date for getting records from the database
Parameters in the JSON response body:
Parameter Type Description confusionMatrix
Object
Description can be found on the towards data science Website.
averageResponseTime
int
Average of all response times relevant for the model that is checked
accuracy,precision,recall,fmeasure
int
Description can be found on the towards data science Website.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/admin/history/models/model_1_Id/performance
Request body{ "startDate": "2021-04-01T12:18:04.512527", "endDate": "2021-04-01T19:18:04.512527" }
- Response Example
-
200 OK
Response Body{ "accuracy": 1.0, "precision": 0.0, "recall": 0.0, "confusionMatrix": { "TP": 0, "FP": 0, "TN": 6, "FN": 0 }, "averageResponseTime": 3771.0, "fmeasure": 0.0 }
POST /predict-api/api/system/history/models/{modelid}/performance
- Retrieve system model performance.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Description
-
Retrieves the system model performances specified by parameters.
Parameters in the JSON request body:
Parameter Type Description startDate
LocalDateTime
Desired start date for getting records from the database
endDate
LocalDateTime
Desired end date for getting records from the database
Parameters in the JSON response body:
Parameter Type Description confusionMatrix
Object
Description can be found on the towards data science Website.
averageResponseTime
int
Average of all response times relevant for the model that is checked
accuracy,precision,recall,fmeasure
int
Description can be found on the towards data science Website.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/system/history/models/model_1_Id/performance
Request body{ "startDate": "2021-04-01T12:18:04.512527", "endDate": "2021-04-01T19:18:04.512527" }
- Response Example
-
200 OK
Response Body{ "accuracy": 1.0, "precision": 0.0, "recall": 0.0, "confusionMatrix": { "TP": 0, "FP": 0, "TN": 6, "FN": 0 }, "averageResponseTime": 3771.0, "fmeasure": 0.0 }
History Logs
GET /predict-api/api/admin/history/models
- Retrieve information on tenant models
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieve information on models that are already used by the currently active tenant.
System context models used for that tenant are also valid.
Parameters in the JSON response body:
Parameter Type Description modelRunId
string
Unique model identifier set in property file of Predict-API
modelOriginType
string
Model type (TENANT or SYSTEM)
modelUsageType
string
Purpose type (extraction or classification)
Response HTTP status codes:
+
HTTP status code | Meaning |
---|---|
200 |
OK |
400 |
Bad Request |
403 |
Forbidden |
404 |
Not Found |
415 |
Unsupported Media Type |
500 |
Internal Server Error |
- Request Example
-
/predict-api/api/admin/history/models
- Response Example
-
200 OK
[
{
"modelRunId": "string",
"modelOriginType": "string",
"modelUsageType": "string",
}
]
POST /predict-api/api/admin/history/models/{modelId}/performance-logs
- Retrieve history request logs of the current tenant
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Description
-
Retrieves the tenant history request logs by the parameters specified in the JSON request body for the model identified by
modelId
.The model must have already been used in the current tenant. System context models used for that tenant are also valid.
Parameters in the JSON request body:
Parameter Type Description startDate
LocalDateTime
Desired start date for getting records from the database
endDate
LocalDateTime
Desired end date for getting records from the database
documentId
String
UUID that represents the document’s objectId
Parameters in the JSON response body:
Parameter Type Description uuid
long
Object unique identifier
documentId
String
This represents objectId of the document
modelRequest
String
Request that is used to call this model
modelResponse
String
Response returned by the model
predictions
String
Response returned by Predict-API for that request
modelsResponseInfo
String
Map of information about the model called in this specific request (Model label and information about the model – model type, request time, model identifier)
responseTime
long
Response time in total
predictionType
long
Type of the prediction – extraction or classification
sot
String
List of secondary object types used for this request
feedbackData
String
Feedback data in string format
tenant
String
Tenant name
isActive
Boolean
Flag if the record is relevant or not (softly deleted)
createdDate
LocalDateTime
Creation date of request
createdBy
String
Who created the request
lastModifiedDate
LocalDateTime
Date on which the request was last updated
lastModifiedBy
String
Who last updated the request
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/admin/history/models/model_1_Id/performance-logs
Request body{ "startDate": "2021-04-01T12:18:04.512527", "endDate": "2021-04-01T19:18:04.512527", "documentId": "string" }
- Response Example
-
200 OK
Response Body[ { "id": "long" "uuid": "UUID" "documentId": "string" "modelRequest": "string" "modelResponse": "string" "predictions": "string" "modelsResponseInfo": "string" "responseTime": "long" "predictionType": "string" "sots": "string" "feedbackData": "string" "tenant": "string" "isActive": true "createdDate": "localDateTime" "createdBy": "string" "lastModifiedDate": "localDateTime" "lastModifiedBy": "string" } ]
GET /predict-api/api/system/history/models
- Retrieve information on system context models
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Description
-
Retrieves information on the system context models already used in any tenant.
Parameters in the JSON response body:
Parameter Type Description modelRunId
string
Unique model identifier set in property file of Predict-API
modelOriginType
string
Model type (TENANT or SYSTEM)
modelUsageType
string
Purpose type (extraction or classification)
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/system/history/models
- Response Example
-
200 OK
[
{
"modelRunId": "string",
"modelOriginType": "string",
"modelUsageType": "string",
}
]
POST /predict-api/api/system/history/models/{modelId}/performance-logs
- Retrieve history logs of system context
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Description
-
Retrieve the history request logs of system context by the parameters specified in the JSON request body for the model identified by
modelId
.The model must have already been used in any tenant.
Parameters in the JSON request body:
Parameter Type Description startDate
LocalDateTime
Desired start date for getting records from the database
endDate
LocalDateTime
Desired end date for getting records from the database
documentId
String
UUID that represents the document’s objectId
Parameters in the JSON response body:
Parameter Type Description uuid
long
Object unique identifier
documentId
String
This represents objectId of the document
modelRequest
String
Request that is used to call this model
modelResponse
String
Response returned by the model
predictions
String
Response returned by Predict-API for that request
modelsResponseInfo
String
Map of information about the model called in this specific request (Model label and information about the model – model type, request time, model identifier)
responseTime
long
Response time in total
predictionType
long
Prediction type (extraction or classification)
sot
String
List of secondary object types used for this request
feedbackData
String
Feedback data in string format
tenant
String
Tenant name
isActive
Boolean
Flag if the record is relevant or not (softly deleted)
createdDate
LocalDateTime
Creation date of request
createdBy
String
Who created the request
lastModifiedDate
LocalDateTime
Date on which the request was last updated
lastModifiedBy
String
Who updated the request
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/predict-api/api/system/history/models/model_1_Id/performance-logs
Request body{ "startDate": "2021-04-01T12:18:04.512527", "endDate": "2021-04-01T19:18:04.512527", "documentId": "string" }
- Response Example
-
200 OK
Response Body[ { "id": "long" "uuid": "UUID" "documentId": "string" "modelRequest": "string" "modelResponse": "string" "predictions": "string" "modelsResponseInfo": "string" "responseTime": "long" "predictionType": "string" "sots": "string" "feedbackData": "string" "tenant": "string" "isActive": true "createdDate": "localDateTime" "createdBy": "string" "lastModifiedDate": "localDateTime" "lastModifiedBy": "string" } ]
8.2.2. Requirements
The predict-api
service is a Java Spring Microservice intended for use in Kubernetes and in combination with kairos-api
service. To find details on infrastructure requirements for the AI Platform components, see requirements and dependencies. If you want to use them for the AI integration in a client application based on our client libraries (e.g., yuuvis® client as reference implementation), also the requirements of the involved services must be considered.
8.2.3. Configuration
The inference schema needs to be defined according to your client application and deployed via the API of the kairos-api
service.
Default timeout value for the inference schema (if timeout is not set) can be configured with:
predict-api:
config:
default-timeout: 20
The endpoints of the predict-api
service are available for users with the YUUVIS_AI_PREDICT
role in the default configuration. Also, the admin and system roles can be customized for /admin/*
and /system/*
endpoints. The roles can be replaced by a custom role via the following configuration:
predict-api:
user:
authority:
api: YUUVIS_AI_PREDICT
admin: YUUVIS_TENANT_ADMIN
system: YUUVIS_SYSTEM_INTEGRATOR
To handle models provided by the kairos-api
service, the following configuration parameters are required. Models can be specified per tenant if tenant specific model is trained. Alternatively, default services can be used.
predict-api:
extraction:
label-to-model-info-map-per-tenant:
tenant1:
TRANSFORMERS:
- http://transformers.ml-infrastructure:5000
- tenant1ModelTransformers
- ML_FLOW
RULE_BASED:
- http://extraction-rule-based.ml-infrastructure:5000
- tenant1ModelRuleBased
- ML_FLOW
default:
TRANSFORMERS:
- http://transformers-default.ml-infrastructure:5000
- defaultModelTransformers
- ML_FLOW
RULE_BASED:
- http://extraction-rule-based-default.ml-infrastructure:5000
- defaultModelRuleBased
- ML_FLOW
Furthermore, a list of labels for individual models is required as shown in the example below.
The specified labels are processed with the corresponding model. In the example, INVOICE_ISSUER_NAME
and INVOICE_RECEIVER_NAME
are processed via the transformers model and via the rule-based-name
model. This allows the most suitable approach to be selected for each purpose.
issuer-receiver-name-labels
should specify labels used for company name extraction.
If a model should not be used, remove all entries from the corresponding labels list.
predict-api:
extraction:
transformers-labels:
- INVOICE_TOTAL_AMOUNT
- INVOICE_BASE_AMOUNT
- INVOICE_ISSUE_DATE
- INVOICE_NUMBER
- INVOICE_ISSUER_NAME
- INVOICE_RECEIVER_NAME
rule-based-labels:
- INVOICE_IBAN_NUMBER
- TAX_AMOUNT
- INVOICE_CURRENCY
- TAX_NUMBER_ISSUING_COMPANY
- TAX_NUMBER_RECEIVING_COMPANY
- INVOICE_SWIFTBIC_NUMBER
issuer-receiver-name-labels:
- INVOICE_ISSUER_NAME
- INVOICE_RECEIVER_NAME
Negative class for extraction models needs to fit the one in the trained models and can be configured with:
predict-api:
negative-class: O
Company name similarity postprocessing and database logging can be enabled/disabled with:
predict-api:
company-name-similarity:
enabled: false
db-logs:
enabled: true
If amount calculation postprocessing is enabled, labels for amounts should be specified in property file.
predict-api:
extraction:
amount-calculation-labels:
default:
TOTAL_AMOUNT: INVOICE_TOTAL_AMOUNT
BASE_AMOUNT:
TAX_AMOUNT: TAX_AMOUNT
default:
TOTAL_AMOUNT: INVOICE_TOTAL_AMOUNT
BASE_AMOUNT: INVOICE_BASE_AMOUNT
TAX_AMOUNT: TAX_AMOUNT
Classification properties are specified as follows:
-
URL to classification model service,
-
classification model identifier,
-
threshold that represents the limit to show prediction classes with certainty level above that value,
-
model label name
-
and flag that is used to specify which approach is used in classification model (if set to
true
– transformers approach is used, iffalse
– old tfidf approach is used)
predict-api:
classification:
url: http://classification.ml-infrastructure:5000
runId: defaultClassificationRunId
threshold: 0.50
label: CLASSIFICATION
useTransformers: true
The PDF converter component is used to extract information from a pdf document and convert it to a format that is suitable as model input.
predict-api:
pdf-converter:
url: http://pdf-converter.ml-infrastructure:5000
8.3. API for ML Pipeline
The machine learning (ML) pipeline is a processing chain with multiple jobs as shown in the overview image.
-
Preprocessing of DMS objects including metadata and binary content. Documents exported from external systems and their metadata can be used as well (e.g., 5,000 invoices received from different partners/suppliers). The data are managed on an S3 storage.
-
Training of a new model based on the now suitable formatted data. The training can be repeated with the change set of parameters to increase model performance.
-
Creation of a docker image for the model and deployment to any Kubernetes cluster.
The individual jobs are managed via kairos-api
endpoints.
Furthermore, the kairos-api
service is responsible for configuring the inference schema, that is in turn used by predict-api
to call the appropriate machine learning models for an object type.
8.3.1. Endpoints of 'kairos-api' Service
All endpoints are available via the Swagger UI https://<host>/kairos-api/swagger-ui.html
.
Inference Schema Management
GET /kairos-api/api/admin/schema
- Get Inference Schema for Tenant
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Retrieves the tenants' current inference schema.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/schema
no request body
- Response Example
-
Response Body
{ "tenant": "string", "classification": { "timeout": 10, "enabled": true, "aiClassifierId": "string", "objectTypes": [ { "objectTypeId": "string", "aiObjectTypeId": "string" } ] }, "extraction": { "timeout": 10, "enabled": true, "objects": [ { "objectTypeId": "string", "enabled": true, "timeout": 12, "propertyReference": [ { "propertyId": "string", "aiPropertyId": "string", "allowedValues": [ "string" ], "pattern": "string", "validationService": "string", "maxNumberOfPredictions": 3 } ] } ] } }
POST /kairos-api/api/admin/schema
- Update Inference Schema for Tenant
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Updates the tenants' inference schema.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/schema
Input is a JSON file with content explained in the inference schema.
GET /kairos-api/api/system/schema
- Get Global Inference Schema
- As of Version
-
2022 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Retrieves the global inference schema.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/system/schema
no request body
- Response Example
-
Response Body
{ "classification": { "timeout": 10, "enabled": true, "aiClassifierId": "string", "objectTypes": [ { "objectTypeId": "string", "aiObjectTypeId": "string" } ] }, "extraction": { "timeout": 10, "enabled": true, "objects": [ { "objectTypeId": "string", "enabled": true, "timeout": 12, "propertyReference": [ { "propertyId": "string", "aiPropertyId": "string", "allowedValues": [ "string" ], "pattern": "string", "validationService": "string", "maxNumberOfPredictions": 3 } ] } ] } }
POST /kairos-api/api/system/schema
- Update Global Inference Schema
- As of Version
-
2022 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Updates the global inference schema.
The global inference schema is available for all tenants. It will be used by tenants which do not have their inference schema.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/system/schema
Input is a JSON file with content explained in the inference schema.
Building and Deploying Docker Images
POST /kairos-api/api/admin/models/build-image
- Build and push a model docker image.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Creates a Kubernetes job that builds a model docker image and pushes it to a specified docker image registry. Response is UUID of the created Kubernetes job.
Parameters in the JSON response body:
Parameter Type Description dockerImage
String
Docker image tag that you want to use for the model that you are building. Must match the regular expression (^[a-zA-Z0-9_.-]+(/[a-zA-Z0-9_.-]+)+(:[a-zA-Z0-9_.-]+)?$)
artifactLocation
String
Location on S3 storage where model artifacts to be used for image build are located. Must match the regular expression (s3://([a-z0-9][a-z0-9\-.]{1,61}[a-z0-9])/(.+)$)
dockerImagePushSecretName
String
Name of the Kubernetes secret where to push the image with credentials for listed repository in
dockerImage
parameter. Secret should be present in the cluster.artifactLocationSecretName
String
Kubernetes secret with credentials to S3 storage where listed artifacts are located.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/build-image
Request body{ "dockerImage": "...", "artifactLocation": "s3://...", "dockerImagePushSecretName": "string", "artifactLocationSecretName": "string" }
- Response Example
-
200 OK
Response Body{ "jobUuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }
GET /kairos-api/api/admin/models/build-image/history
- Get all image build jobs.
- As of Version
-
2023 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Gets all image build job details to check their status. Paging and sorting (by start or end time) can be adjusted via query parameters. The result contains:
-
running image build operations including their start time,
-
finished image build operations including their start and end time, as well as their execution summary, and
-
interrupted image build operations, including their start time and end (interruption) time.
Optional query parameters:
Parameter Type Description page
int
Default is 0.
size
int
Default is 10.
sort
string
Allowed values are:
-
createdDate
-
endedDate
-
created date/DESC
(default)
Response object explained in
GET /kairos-api/api/admin/models/build-image/history/{uuid}
.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
-
- Request Example
-
/kairos-api/api/admin/models/build-image/history?page=0&size=1&sort=string
- Response Example
-
200 OK
Response Body{ "content": [ { "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "jobType": "string", "jobStatus": "string", "executionSummary": "string", "endedDate": "2023-11-13T15:45:33.976Z", "createdDate": "2023-11-13T15:45:33.976Z", "createdBy": "string", "lastModifiedDate": "2023-11-13T15:45:33.976Z", "lastModifiedBy": "string", "isActive": true, "tenant": "string", "runId": "string" } ], "totalElements": 1, "totalPages": 0, "last": true }
GET /kairos-api/api/admin/models/build-image/history/{jobUuid}
- Get specific image build job by UUID.
- As of Version
-
2023 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Gets specific image build job details by UUID.
Parameters in the JSON response body:
Parameter Type Description uuid
UUID
Unique record identifier
jobType
string
Job type = IMAGE_BUILD
jobStatus
string
Job Status - IS_RUNNING, COMPLETE, FAILED, INTERRUPTED
executionSummary
string
Execution summary description
createdDate
LocalDateTime
Date when request is created
createdBy
String
Information who created the request
lastModifiedDate
LocalDateTime
Date on which the request was last updated
lastModifiedBy
String
Information who updated the request
isActive
Boolean
Flag if the record is relevant or not (softly deleted)
tenant
String
Tenant name
runId
String
runId of the training pipeline
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/build-image/history/3fa85f64-5717-4562-b3fc-2c963f66afa6
- Response Example
-
200 OK
Response Body{ "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "jobType": "string", "jobStatus": "string", "executionSummary": "string", "endedDate": "2023-11-13T19:08:21.291Z", "createdDate": "2023-11-13T19:08:21.292Z", "createdBy": "string", "lastModifiedDate": "2023-11-13T19:08:21.292Z", "lastModifiedBy": "string", "isActive": true, "tenant": "string", "runId": "string" }
POST /kairos-api/api/admin/models/build-image/interrupt/{jobUuid}
- Interrupt/Delete image build and push job by UUID of the job.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Interrupts/Deletes image build and push job by UUID of the job.
There is no automated cleanup of preprocessing results that were saved to the S3 bucket. Administrators can maintain those results according to their needs.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/build-image/interrupt/3fa85f64-5717-4562-b3fc-2c963f66afa6
- Response Example
-
200 OK
POST /kairos-api/api/admin/models/deploy
- Deploy model to Kubernetes cluster.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
The endpoint deploys a model that is dockerized and located at the docker image registry that is specified in the JSON request body to the Kubernetes cluster. The image will be run after the proper deployment and Kubernetes service creation.
Parameters in the JSON request body:
Parameter Type Description modelName
string
The name of the model (deployment and service). Must match the regular expression (^[a-z0-9]([-a-z0-9]*[a-z0-9])?$). The number of characters is limited to 255 (RFC 1123 standard).
dockerImage
string
Docker image tag. Must match the regular expression (^[a-zA-Z0-9_.-]+(/[a-zA-Z0-9_.-]+)+(:[a-zA-Z0-9_.-]+)?$)
imagePullSecret
string
Image pull secret that will be used to pull image from the docker image registry. Should already be present in the cluster.
numberOfReplicas
int
Number of replicas. Default is 1.
memoryLimits
string
Memory limit for Kubernetes container. Use
Mi
orGi
as measure.memoryRequests
string
Memory requests for Kubernetes container. Use
Mi
orGi
as measure.containerPort
int
Port inside the model. Values are available in a range between 1 and 65535. Default is 8080.
environmentVariables
JSON key-value mapping
Environment variables that should be used for the model.
shouldAddToleration
boolean
Decides if toleration is used to place the container on a specific Node inside the cluster (
true
) or not (false
). Default isfalse
.If
true
, a Node with following taint is required:tolerations: - key: "dedicated" operator: "Exists" effect: "NoSchedule" nodeSelector: dedicated: machinelearning
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/deploy
Request body{ "modelName": "a3m45j7...", "dockerImage": "container-registry/image:tag", "imagePullSecret": "string", "numberOfReplicas": 1, "memoryLimits": "10Gi", "memoryRequests": "8Gi", "containerPort": 65535, "environmentVariables": { "additionalProp1": "string", "additionalProp2": "string", "additionalProp3": "string" }, "shouldAddToleration": true }
- Response Example
-
200 OK
Response Body{ "status": "string" }
POST /kairos-api/api/admin/models/health
- Check model availability.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Checks the health of the model specified with Kubernetes service name in the JSON request body by sending a ping request to the corresponding Kubernetes pod.
Parameters in the JSON request body:
Parameter Type Description modelName
string
The name of the model Kubernetes service. Must match the regular expression (^[a-z0-9]([-a-z0-9]*[a-z0-9])?$). The number of characters is limited to 255 (RFC 1123 standard).
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/health
Request body{ "modelName": "model1" }
- Response Example
-
200 OK
Response Body{ "status": "string" }
POST /kairos-api/api/admin/models/undeploy
- Undeploy/Delete model from Kubernetes cluster.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Undeploys/Deletes a model’s deployment and pod from the Kubernetes cluster.
Parameters in the JSON request body:
Parameter Type Description modelName
string
The name of the model (deployment and service). Must match the regular expression (^[a-z0-9]([-a-z0-9]*[a-z0-9])?$). The number of characters is limited to 255 (RFC 1123 standard).
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/undeploy
Request body{ "modelName": "string" }
- Response Example
-
200 OK
Response Body{ "status": "string" }
Preprocessing Operations
Manage preprocessing of raw data to convert them into a suitable format for the training. The preprocessing is performed by individual Kubernetes jobs.
POST /kairos-api/api/admin/preprocessing
- Start a preprocessing job.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Starts a preprocessing job that converts raw data into a suitable format for training processes.
Configuration parameters should be set in the property file of a service. For details, see configuration description of preprocessing service.
The data are read from and written to the configured S3 repository.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/preprocessing
- Response Example
-
200 OK
Response Body{ "jobUuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }
GET /kairos-api/api/admin/preprocessing/history
- Get all preprocessing jobs.
- As of Version
-
2023 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Gets all preprocessing job details to check their status. Paging and sorting (by start or end time) can be adjusted via query parameters. The result contains:
-
running preprocessing operations including their start time,
-
finished preprocessing operations including their start and end time, as well as their execution summary, and
-
interrupted preprocessing operations, including their start time and end (interruption) time.
Optional query parameters:
Parameter Type Description page
int
Default is 0.
size
int
Default is 10.
sort
string
Allowed values are:
-
createdDate
-
endedDate
-
created date/DESC
(default)
Response object explained in
GET /kairos-api/api/admin/models/build-image/history/{uuid}
. Only type is different - PREPROCESSINGResponse HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
-
- Request Example
-
/kairos-api/api/admin/models/preprocessing/history?page=0&size=1&sort=string
- Response Example
-
200 OK
Response Body{ "content": [ { "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "jobType": "string", "jobStatus": "string", "executionSummary": "string", "endedDate": "2023-11-13T17:39:54.727Z", "createdDate": "2023-11-13T17:39:54.727Z", "createdBy": "string", "lastModifiedDate": "2023-11-13T17:39:54.727Z", "lastModifiedBy": "string", "isActive": true, "tenant": "string", "runId": "string" } ], "totalElements": 1, "totalPages": 0, "last": true }
GET /kairos-api/api/admin/preprocessing/history/{jobUuid}
- Get specific preprocessing job by UUID.
- As of Version
-
2023 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Gets specific preprocessing job details by UUID.
Response object explained in
GET /kairos-api/api/admin/models/build-image/history/{uuid}
. Only type is different - PREPROCESSINGResponse HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/preprocessing/history/3fa85f64-5717-4562-b3fc-2c963f66afa6
- Response Example
-
200 OK
Response Body{ "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "jobType": "string", "jobStatus": "string", "executionSummary": "string", "endedDate": "2023-11-13T17:51:01.807Z", "createdDate": "2023-11-13T17:51:01.807Z", "createdBy": "string", "lastModifiedDate": "2023-11-13T17:51:01.807Z", "lastModifiedBy": "string", "isActive": true, "tenant": "string", "runId": "string" }
POST /kairos-api/api/admin/preprocessing/interrupt/{jobUuid}
- Interrupt/Delete preprocessing job by its UUID.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Interrupts/Deletes preprocessing job by its UUID.
There is no cleanup of preprocessing results that were saved to the corresponding bucket in the S3 repository. Repository administrators can maintain those results according to their needs.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/preprocessing/interrupt/3fa85f64-5717-4562-b3fc-2c963f66afa6
- Response Example
-
200 OK
Training of Models
POST /kairos-api/api/admin/training
- Start the training of a model.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Starts the pipeline training job in Kubernetes.
Configuration parameters should be set in the property file of a service. For details, see configuration description of training service.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/training
- Response Example
-
200 OK
Response Body{ "jobUuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }
GET /kairos-api/api/admin/training/history
- Get all training jobs.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Gets all training job details to check their status. Paging and sorting (by start or end time) can be adjusted via query parameters. The result contains:
-
running training operations including their start time,
-
finished training operations including their start and end time, as well as their execution summary, and
-
interrupted training operations, including their start time and end (interruption) time.
Optional query parameters:
Parameter Type Description page
int
Default is 0.
size
int
Default is 10.
sort
string
Allowed values are:
-
createdDate
-
endedDate
-
created date/DESC
(default)
Response object explained in
GET /kairos-api/api/admin/models/build-image/history/{uuid}
. Only type is different - TRAININGResponse HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
-
- Request Example
-
/kairos-api/api/admin/training/history?page=0&size=1&sort=string
- Response Example
-
200 OK
Response Body{ "content": [ { "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "jobType": "string", "jobStatus": "string", "executionSummary": "string", "endedDate": "2023-11-13T18:06:27.260Z", "createdDate": "2023-11-13T18:06:27.260Z", "createdBy": "string", "lastModifiedDate": "2023-11-13T18:06:27.260Z", "lastModifiedBy": "string", "isActive": true, "tenant": "string", "runId": "string" } ], "totalElements": 1, "totalPages": 0, "last": true }
GET /kairos-api/api/admin/training/history/{jobUuid}
- Get specific training job by UUID.
- As of Version
-
2023 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Gets specific training job details by UUID.
Response object explained in
GET /kairos-api/api/admin/models/build-image/history/{uuid}
. Only type is different - TRAININGResponse HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/training/history/3fa85f64-5717-4562-b3fc-2c963f66afa6
- Response Example
-
200 OK
Response Body{ "uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "jobType": "string", "jobStatus": "string", "executionSummary": "string", "endedDate": "2023-11-13T18:17:03.193Z", "createdDate": "2023-11-13T18:17:03.193Z", "createdBy": "string", "lastModifiedDate": "2023-11-13T18:17:03.194Z", "lastModifiedBy": "string", "isActive": true, "tenant": "string", "runId": "string" }
POST /kairos-api/api/admin/training/interrupt/{jobUuid}
- Interrupt/Delete training job by the job’s UUID.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
HTTP status code
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Interrupts/Deletes training job by UUID of the job.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/training/interrupt/3fa85f64-5717-4562-b3fc-2c963f66afa6
- Response Example
-
200 OK
Experiments
POST /kairos-api/api/admin/experiments/create
- Create experiment.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Creates the MLflow experiment. It returns experiment id of created experiment in MLflow tracking server.
Parameters in the JSON request body:
Parameter Type Description name
string
Name of the new experiment in MLflow
artifactLocation
string
If you want to override the default artifact location
tags
Object
Custom tags to set on MLflow experiment
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/experiments/create
Request body{ "name": "string", "artifactLocation": "string", "tags": [ { "key": "string", "value": "string" } ] }
- Response Example
-
200 OK
Response Body{ "experiment_id": "17" }
POST /kairos-api/api/admin/experiments/delete
- Delete experiment.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Deletes experiments from MLflow tracking server.
Request parameter is experiment id from MLflowW
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/experiments/delete
Request body{ "experiment_id": "1" }
- Response Example
-
200 OK
no response body
POST /kairos-api/api/admin/experiments/search
- Search experiments.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Searches experiments in MLflow tracking server.
Request and response property descriptions can be found on the MLflow Documentation Website. Default values for
maxResults
is 1000 and forviewType
is ALL.Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/experiments/search
Request body{ "maxResults": 10, "pageToken": "string", "filter": "string", "orderBy": [ "string" ], "viewType": "ACTIVE_ONLY" }
- Response Example
-
200 OK
Response Body{ "experiments": [ { "experimentId": "string", "name": "string", "artifactLocation": "string", "lifecycleStage": "string", "lastUpdateTime": 2018-01-26T15:21:170Z, "creationTime": 2018-01-26T15:21:170Z, "tags": [ { "key": "string", "value": "string" } ] } ], "nextPageToken": "string" }
Information on Models
POST /kairos-api/api/admin/models/search
- List registered models.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Lists registered models from MLflow tracking server. The response description can be found on the MLflow Documentation Website.
Parameters in the JSON request body:
Parameter Type Description name
int
Filter by registered model name.
version
int
Filter by registered model version.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/models/search
Request body{ "name": "string", "version": "string" }
- Response Example
-
200 OK
Response Body{ "registeredModels": [ { "name": "string", "creationTimestamp": 2018-01-26T15:21:170Z, "lastUpdateTimestamp": 2018-01-26T15:21:170Z, "latestVersions": [ { "name": "string", "version": "string", "creationTimestamp": 2018-01-26T15:21:170Z, "lastUpdatedTimestamp": 2018-01-26T15:21:170Z, "userId": "string", "currentStage": "string", "description": "string", "source": "string", "runId": "string", "status": "READY", "statusMessage": "string", "tags": [ { "key": "string", "value": "string" } ], "runLink": "string" } ] } ], "nextPageToken": "string" }
Information on Jobs
GET /kairos-api/api/admin/runs/get/{jobUuid}
- Get run information by job UUID.
- As of Version
-
2023 Winter
- Request Method
-
GET
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Gets MLflow run information by job UUID. Based on that UUID you are getting runId from your database and collecting the run details from MLflow tracking server.
Response object is explained on the MLflow Documentation Website.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/runs/get/3fa85f64-5717-4562-b3fc-2c963f66afa6
- Response Example
-
200 OK
Response Body{ "run": { "info": { "runId": "string", "runName": "string", "experimentId": "string", "status": "RUNNING", "startTime": 2018-01-26T15:21:170Z, "endTime": 2018-01-26T15:29:170Z, "artifactUri": "string", "lifecycleStage": "string" }, "data": { "metrics": [ { "key": "string", "value": 0, "timestamp": 0, "step": 0 } ], "params": [ { "key": "string", "value": "string" } ], "tags": [ { "key": "string", "value": "string" } ] }, "inputs": { "datasetInputs": [ { "tags": [ { "key": "string", "value": "string" } ], "dataset": { "name": "string", "digest": "string", "sourceType": "string", "source": "string", "schema": "string", "profile": "string" } } ] } } }
POST /kairos-api/api/admin/runs/search
- Search runs in MLflow tracking server.
- As of Version
-
2023 Winter
- Request Method
-
POST
- Response Format
-
JSON
- Request Header
-
X-ID-TENANT-NAME: tenant_name
- Description
-
Searches runs in MLflow tracking server.
Request and response property descriptions can be found on the MLflow Documentation Website.
Response HTTP status codes:
HTTP status code Meaning 200
OK
400
Bad Request
403
Forbidden
404
Not Found
415
Unsupported Media Type
500
Internal Server Error
- Request Example
-
/kairos-api/api/admin/runs/search
Request body{ "experimentIds": [ "string" ], "maxResults": 10, "pageToken": "string", "filter": "string", "orderBy": [ "string" ], "runViewType": "ACTIVE_ONLY" }
- Response Example
-
200 OK
Response Body{ "runs": [ { "info": { "runId": "string", "runName": "string", "experimentId": "string", "status": "RUNNING", "startTime": 2018-01-26T15:21:170Z, "endTime": 2018-01-26T15:29:170Z, "artifactUri": "string", "lifecycleStage": "string" }, "data": { "metrics": [ { "key": "string", "value": 0, "timestamp": 0, "step": 0 } ], "params": [ { "key": "string", "value": "string" } ], "tags": [ { "key": "string", "value": "string" } ] }, "inputs": { "datasetInputs": [ { "tags": [ { "key": "string", "value": "string" } ], "dataset": { "name": "string", "digest": "string", "sourceType": "string", "source": "string", "schema": "string", "profile": "string" } } ] } } ], "nextPageToken": "string" }
8.3.2. Inference Schema
The inference schema is a JSON configuration file defining the object types that will be available for the classification as well as the properties for which the metadata extraction should be done. At the same time, each internal aiObjectTypeId
for classification gets a corresponding objectTypeId
and each aiPropertyId
for metadata extraction gets a corresponding propertyId
. They will be used in the response bodies of the classification and extraction endpoints to be compatible with the connected client application.
The inference schema also defines timeouts, allowed values, patterns that should be met, whether the particular mapping is enabled or disabled, etc.
The inference schema can be defined for a specific tenant or for the whole instance. A tenant-specific inference schema will override the global inference schema.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
{
"tenant" : "ACME Inc.",
"classification" : {
"enabled" : true,
"timeout" : 2,
"aiClassifierId" : "DOCUMENT_CLASSIFICATION",
"objectTypes": [
{
"objectTypeId" : "invoiceIn",
"aiObjectTypeId" : "AI_INVOICE"
},
{
"objectTypeId" : "invoiceOut",
"aiObjectTypeId" : "AI_INVOICE"
},
{
"objectTypeId" : "creditMemoIn",
"aiObjectTypeId" : "AI_CREDIT_MEMO"
},
{
"objectTypeId" : "creditMemoOut",
"aiObjectTypeId" : "AI_CREDIT_MEMO"
}
]
},
"extraction" : {
"enabled" : true,
"timeout" : 5,
"objects" : [
{
"objectTypeId" : "invoiceIn",
"enabled" : true,
"timeout" : 10,
"propertyReference" : [
{
"propertyId" : "companyName",
"aiPropertyId" : "AI_INVOICE_COMPANY_NAME",
"allowedValues" : ["Lufthansa", "KLM", "Swiss"],
"pattern" : "/^[a-z]|\\d?[a-zA-Z0-9]?[a-zA-Z0-9\\s&@.]+$",
"maxNumberOfPredictions" : 5
},
{
"propertyId" : "baseAmount",
"aiPropertyId" : "AI_BASE_AMOUNT",
"pattern" : "^[0-9]*[.][0-9]*$",
"maxNumberOfPredictions" : 1
},
{
"propertyId" : "totalAmount",
"aiPropertyId" : "AI_INVOICE_TOTAL_AMOUNT",
"pattern" : "^[0-9]*[.][0-9]*$",
"maxNumberOfPredictions" : 1
},
{
"propertyId" : "invoiceDate",
"aiPropertyId" : "AI_INVOICE_DATE",
"pattern" : "^[0-9]*[.][0-9]*$",
"maxNumberOfPredictions" : 1
}
]
},
{
"objectTypeId" : "invoiceOut",
"enabled" : true,
"timeout" : 10,
"propertyReference" : [
{
"propertyId" : "companyName",
"aiPropertyId" : "AI_INVOICE_COMPANY_NAME",
"allowedValues" : ["Lufthansa", "KLM", "Swiss"],
"pattern" : "/^[a-z]|\\d?[a-zA-Z0-9]?[a-zA-Z0-9\\s&@.]+$",
"maxNumberOfPredictions" : 5
},
{
"propertyId" : "totalAmount",
"aiPropertyId" : "AI_INVOICE_TOTAL_AMOUNT",
"pattern" : "^[0-9]*[.][0-9]*$",
"maxNumberOfPredictions" : 1
}
]
},
{
"objectTypeId" : "creditMemoIn",
"enabled" : true,
"timeout" : 10,
"propertyReference" : [
{
"propertyId" : "companyName",
"aiPropertyId" : "AI_CREDIT_MEMO_TOTAL_AMOUNT",
"allowedValues" : ["Lufthansa", "KLM", "Swiss"],
"pattern" : "/^[a-z]|\\d?[a-zA-Z0-9]?[a-zA-Z0-9\\s&@.]+$",
"maxNumberOfPredictions" : 5
},
{
"propertyId" : "totalAmount",
"aiPropertyId" : "AI_CREDIT_MEMO_TOTAL_AMOUNT",
"pattern" : "^[0-9]*[.][0-9]*$",
"maxNumberOfPredictions" : 1
}
]
},
{
"objectTypeId" : "creditMemoOut",
"enabled" : true,
"timeout" : 10,
"propertyReference" : [
{
"propertyId" : "companyName",
"aiPropertyId" : "AI_CREDIT_MEMO_TOTAL_AMOUNT",
"allowedValues" : ["Lufthansa", "KLM", "Swiss"],
"pattern" : "/^[a-z]|\\d?[a-zA-Z0-9]?[a-zA-Z0-9\\s&@.]+$",
"maxNumberOfPredictions" : 5
},
{
"propertyId" : "totalAmount",
"aiPropertyId" : "AI_CREDIT_MEMO_TOTAL_AMOUNT",
"pattern" : "^[0-9]*[.][0-9]*$",
"maxNumberOfPredictions" : 1
}
]
}
]
}
}
The following parameters are available in the inference schema:
Parameter | Description | |||
---|---|---|---|---|
|
Tenant for which the inference schema will be applied. |
|||
|
Section of parameters for classification processes. |
|||
|
Boolean value specifying whether the document classification is activated ( |
|||
|
Time limit for the determination of a classification prediction in seconds. An error will be thrown if the calculation process could not be finished before the timeout was reached. |
|||
|
ID in the AI platform dictionary defining the model that will be used for the classification process. |
|||
|
A list of mappings, each of them containing the following keys. This list defines the object types that are available for the classification prediction. |
|||
|
The identification of an object type as it will appear in prediction response bodies. You can define a concatenation of several secondary object type IDs, catalog values, etc. that can be interpreted by your client application to show the prediction results in a proper format. |
|||
|
ID of the internal class label on which the model is trained. |
|||
|
Section of parameters for metadata extraction processes. |
|||
|
Boolean value specifying whether the metadata extraction is activated ( |
|||
|
Time limit for the determination of extraction predictions in seconds. The result will be returned even if the calculation process is still running for some models. Those models will be excluded from the response. |
|||
|
List of mappings for the individual object types containing the following keys. This list defines the object types for which metadata extraction will be available. |
|||
|
The ID of the object type as it will be referenced within each object’s metadata in the property |
|||
|
Boolean value specifying whether the metadata extraction is activated ( Ignored if |
|||
|
Optional time limit in seconds overwriting The result will be returned even if the calculation process is still running for some models. Those models will be excluded from the response. |
|||
|
A list of mappings, each of them containing the following keys. This list defines the properties for which metadata should be extracted for an object of type |
|||
|
The identification of a property as it will appear in prediction response bodies. You can define a concatenation of several secondary object type IDs, catalog values etc. that can be interpreted by your client application to show the prediction results in proper format. |
|||
|
ID of the internal property label on which the model is trained. |
|||
|
Optional limitation of the prediction response: List of values for the property specified by |
|||
|
Optional limitation of the prediction response: Condition for values for the property specified by |
|||
|
Optional parameter: An integer value defining the maximum number of values included in the prediction response for the property If not specified, the default value 1 will be used. |
To use the Artificial Intelligence Platform with a client application based on our client libraries (e.g., yuuvis® client as a reference implementation), objectTypeId
can be defined as a concatenation of app name and SOTs separated by pipes as can be seen in the following example:
{
"tenant" : "os__papi",
"classification" : {
"enabled" : true,
"timeout" : 10,
"aiClassifierId" : "DOCUMENT_CLASSIFICATION",
"objectTypes": [
{
"objectTypeId" : "appImpulse:hrdocsot|appImpulse:hrDocumentType|Bescheinigung",
"aiObjectTypeId" : "appImpulse:contractsot"
},
{
"objectTypeId" : "appImpulse:receiptsot",
"aiObjectTypeId" : "appImpulse:hrdocsot"
},
{
"objectTypeId" : "appImpulse:contractsot|appImpulse:contractType|Arbeitsvertrag",
"aiObjectTypeId" : "appImpulse:receiptsot"
},
{
"objectTypeId" : "appImpulse:hrdocsot|appImpulse:hrDocumentType|Arbeitsvertrag",
"aiObjectTypeId" : "appImpulse:basedocumentsot"
}
]
}
}
8.3.3. Requirements
Serving and platform management components are dockerized and can be deployed to any infrastructure that supports Docker/Kubernetes — on-premises or in the cloud.
To support the customers that have sensitive data and do not want their documents to leave their on-premises systems, the model training can be executed in their own infrastructure and once the models are dockerized, they can be used on-premises or in the cloud, according to customers' needs.
For details on infrastructure requirements, see requirements and dependencies.
8.3.4. Configuration
Service-specific Parameters
Parameter | Description | Default Value |
---|---|---|
|
Authority (role) user needs to access |
|
|
Authority (role) user needs to access |
|
|
Authority (role) user needs to access |
|
|
Name of the file in Git where inference schema is located. The file is read/updated via |
|
|
URL of the yuuvis® client application, used by |
|
|
URL where MLflow TS instance is located |
|
Preprocessing Service Parameters
When starting a preprocessing job via POST /kairos-api/api/admin/preprocessing
the service is triggered to create an instance of the job from an image provided by configuration. If the specified namespace (e.g., ml-infrastructure
) does not exist, it is created.
kairos-api:
k8s:
namespace: ml-infrastructure
preprocessing:
image: docker.optimal-systems.org/team-owl/preprocessing-service:0.0.1
image-pull-secret: preprocessing-service-registry-token
env:
secrets:
S3_CONFIG_DICT_KAIROS: aws-preprocessing-details
variables:
SOURCE_DIR: "s3:/test/pdfs/"
TARGET_DIR: "s3:/mlflow/pkl/"
METADATA_DIR: "s3:/test/metadata/"
REPORT_DIR: "s3:/mlflow/reports/"
REPORT_NAME: "test-kairos-api"
NUM_WORKERS: 1
SKIP: true
SYNCHRONIZE_DIRS: true
job:
ttl-seconds-after-finished: 120
Explanations and hints:
-
The image to be used for each started job is configured by image tag, image pull secret and credentials.
-
The namespace indicates where the preprocessing jobs should be located within the cluster.
-
Also,
env
variables for the preprocessing service can be listed inenv.variables
section. -
The
env
variables that represent security concerns such as AWS credentials can be read from secrets. Configure them in theenv.secret
section.The secret contains an env
variable with the same name but encrypted. -
The parameter
ttl-seconds-after-finished
is recommended to be set. It represents the number of seconds that Kubernetes leaves the job in the cluster for our manual analyses. If this time is expired, the job will be deleted from the cluster. -
The job watcher component monitors jobs within the namespace and reacts to events on jobs. The following event handlers are available:
onAdd
,onUpdate
, andonDelete
.
Training Service Parameters
The namespace
and ttl-seconds-after-finish
parameters are shared.
A job watcher will track the training jobs as well.
For more details on Kubernetes-related parameters, see configuration description of preprocessing service.
kairos-api:
k8s:
namespace: ml-infrastructure
training:
image: docker.optimal-systems.org/team-owl/kairos/transformers_extraction_train
image-pull-secret: kairos-registry-token
env:
secrets:
S3_CONFIG_DICT_KAIROS: aws-training-details
KAIROS_API_DB_USERNAME: kairosapidb-secret
KAIROS_API_DB_PASSWORD: kairosapidb-secret
variables:
MLFLOW_TRACKING_URI: "http://mlflow-tracking-server:5000"
MLFLOW_EXPERIMENT_ID: 0
IN_DATA_DIR: "s3:/data/pkl/"
MAX_EPOCHS: 1
TRAIN_BS: 32
VALID_BS: 32
TRAINING_LABELS: "{'matchers':{'INVOICE_RECEIVER_NAME':{'matcher':{'name':'MultiTokenTextMatcher','args':{'threshold':0.6}}},'INVOICE_ISSUER_NAME':{'matcher':{'name':'MultiTokenTextMatcher','args':{'threshold':0.6}}},'INVOICE_NUMBER':{'matcher':{'name':'MultiTokenTextMatcher','args':{'threshold':0.7}}},'INVOICE_ISSUE_DATE':{'matcher':{'name':'MultiTokenDateMatcher','args':{'max_iter_words':5,'date_formats':['%Y%m%d','%Y%m%d000000']}}},'INVOICE_TOTAL_AMOUNT':{'matcher':{'name':'DecimalMatcher'}},'INVOICE_BASE_AMOUNT':{'matcher':{'name':'DecimalMatcher'}}}}"
DOCLOAD_NUM_WORKERS: 3
DATASET_NUM_WORKERS: 3
KAIROS_API_DB_HOST: "postgres.infrastructure:5432"
KAIROS_API_DB_NAME: kairosapidb
job:
ttl-seconds-after-finished: 120
-
The image used here is used for model training. It is configured with image tag, image pull secret, and the URL to the MLflow tracking service that is internally used to run and log the training jobs.
-
An experiment can be configured under which the training will run.
-
The minio directory for storing the dataset is configured via bucket and folder as well as credentials to the minio instance.
-
Labels for the transformers-based training and some other training-related parameters are available.
-
The
env
variables can be read from secret (critical data - AWS credentials) or directly. -
The run ID is set to be UUID that is created during writing the job information in the database.
kairos-api
handles it as environment variableRUN_ID
.
Model Build Parameters
The job for model docker image build uses kaniko for which most configuration parameters are set.
However, the S3_ENDPOINT
parameter can be used to customize the location of the minio instance for storing the model artifacts.
kaniko-build:
image: gcr.io/kaniko-project/executor:latest
env:
variables:
DEBUG: true
S3_FORCE_PATH_STYLE: true
S3_ENDPOINT: "http://mlflow-minio.infrastructure:9000"
Database Schema
The kairos-api
service uses its own database. It is initialized with the installation of a separate Helm chart with ConfigMap
to create a valid database and user for our service and to grant all privileges to that user.
The database table job_details
is populated with information about the jobs. The status of each individual job is stored in the table as well. Following states are available: IS_RUNNING
, COMPLETE
, FAILED
, INTERRUPTED
.
Columns of the job_details
table:
Column Name | Type |
---|---|
|
BIGINT |
|
DATETIME |
|
VARCHAR(255) |
|
DATETIME |
|
VARCHAR(255) |
|
BOOLEAN |
|
VARCHAR(255) |
|
VARCHAR(255) |
|
VARCHAR(255) |
|
VARCHAR(255) |
|
DATETIME |
|
UUID |
|
VARCHAR(255) |
9. E-mail Archive
9.1. Introduction
This e-mail archive solution manages indexing and storing of e-mails in yuuvis® Momentum that were sent or received via an external e-mail provider. This compliant storage of e-mails is based on international regulations regarding privacy and data protection.
The e-mail archive can handle journaling reports or conventional e-mails. They are stored in yuuvis® Momentum as individual DMS objects with corresponding metadata as well as an internal text rendition for full-text search.
The service is designed to work primarily with Microsoft Exchange Online. It is also possible to connect other e-mail providers using SMTP. However, this documentation describes configurations and functionality for using of MS Exchange Online.
9.2. Architecture and Function
The e-mail archive contains three different services. The massmtp
and masmailbox
services are responsible for e-mail communication and the masstoragemomentum
service is responsible for storing mail messages in yuuvis® Momentum.
There are three different formats of e-mail retrieval from the e-mail provider:
-
conventional e-mails
-
Microsoft Exchange Online journal reports
-
non-deliverable reports
One of these formats is selected in the connection configuration of each individual mailbox. The concrete configuration parameters differ for a connection via massmtp
or masmailbox
service as described in the configuration section.
9.3. Journaling
An e-mail imported as journal report corresponds to exactly one DMS object in yuuvis® Momentum. It consists of metadata and binary content.
In the metadata, a participants
property is filled with a list of all e-mail addresses that are involved. This property simplifies the definition of proper access rights. Which addresses are actually added to the property depends on the journaling mode used.
9.3.1. Journal and Alternate Mode
This mode uses the masmailbox
service.
The journaling mailboxes have to be listed in mas-mailbox.journaling.mailboxes
.
Each e-mail that is successfully stored in yuuvis® Momentum is permanently deleted from the corresponding mailbox. |
The participants
property is filled with a list of all e-mail addresses that are involved as FROM, TO, CC or BCC.
The determined e-mail addresses are resolved as follows:
-
Mailing lists and mail-enabled security groups are split in their individual member addresses.
-
If secondary addresses are used for configured domains, they are turned to primary addresses (domain list and access to graph API required, find details in the configuration section).
9.3.2. Normal Mode
This mode uses the masmailbox
service.
The participants
property is filled with a list of all e-mail addresses that are involved as FROM, TO or CC.
The e-mail address resolving rules are the same as for the journal mode.
9.3.3. Journaling without Exchange Online
This mode uses SMTP via massmpt
service.
The type of accepted messages is configured via mas-smtp.message-mode
.
The bundled SMTP server can be bound to a configurable port and can work with or without TLS. The service extracts MailMessage objects from the received e-mails and provides them for storing in yuuvis® Momentum.
To avoid spam in yuuvis® Momentum, the processing can be limited to a list of allowed receivers as well as allowed senders.
The participants
property is filled with a list of all e-mail addresses that are involved as FROM, TO, CC or BCC.
The determined e-mails are not resolved. Mailing lists and secondary addresses are kept as they are.
9.4. Mailbox Archiving
This mode uses the masmailbox
service.
The mailboxes to be archived have to be listed in mas-mailbox.archiving.mailboxes
.
The service tags the e-mails within the mailboxes. Thus, the mailbox user can trace which e-mails are already stored in yuuvis® Momentum. |
When an e-mail is imported via mailbox archiving, a separate DMS object is created for each e-mail address involved as FROM, TO, CC or BCC. Each duplicate refers to the same binary content but has its own metadata. This allows the individual users to apply changes to the metadata of their own objects according to their wishes. For example, users can 'move' their e-mail objects in their own private folders without affecting the objects of other involved users.
The participants
property contains only the configured mailbox’s address. None of the e-mail addresses that are involved as FROM, TO, CC or BCC are included.
9.5. Deduplication
It is rather common that e-mail addresses are included in multiple mailing lists. As it is possible that two or more of those mailing lists are connected as mailboxes to the e-mail archive, users would find their e-mails twice or more in yuuvis® Momentum. To avoid this duplication, the e-mail archive behaves as follows.
Incoming e-mail | Already existing e-mail | Impact on the existing e-mail |
---|---|---|
Journal e-mail |
Journal e-mail |
The metadata of the existing e-mail is replaced by the metadata of incoming e-mail. |
Archive e-mail |
Archive e-mail |
|
Journal e-mail |
Archive e-mail |
The incoming e-mail is created as a new DMS object but refers to the already existing binary content. The user for which the e-mail already exists is removed from |
Archive e-mail |
Journal e-mail |
The incoming e-mail is created as a new DMS object but refers to the already existing binary content. The user for which the e-mail already exists is removed from |
9.5.1. Access Management
During the login, an app-specific webhook adds the user’s e-mail addresses as connectedEmails
parameter to the abac
section of the internal JSON web token (JWT).
The user’s roles grant the permissions to retrieve/update an e-mail DMS object in yuuvis® Momentum.
9.7. Installation
The e-mail archive solution can be installed via Helm chart.
9.8. Configuration
9.8.1. Schema 'mailarchiving'
The e-mail requires the following app schema. It must be imported into the yuuvis® Momentum system and the mailarchiving
app must be activated for the tenant.
App schema for 'mailarchiving' app
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schema xmlns="http://optimal-systems.org/ns/dmscloud/schema/v5.0/">
<!-- access control -->
<propertyStringDefinition>
<id>appMailarchiving:participants</id>
<propertyType>string</propertyType>
<cardinality>multi</cardinality>
<required>false</required>
</propertyStringDefinition>
<!-- grouping properties -->
<propertyStringDefinition>
<id>appMailarchiving:user</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>true</required>
</propertyStringDefinition>
<!-- report properties -->
<propertyTableDefinition>
<id>appMailarchiving:reportInfo</id>
<propertyType>table</propertyType>
<cardinality>single</cardinality>
<required>false</required>
<propertyStringDefinition>
<id>reportId</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>reportChannel</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyDateTimeDefinition>
<id>reportTime</id>
<propertyType>datetime</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyDateTimeDefinition>
</propertyTableDefinition>
<propertyStringDefinition>
<id>appMailarchiving:reportRecipients</id>
<propertyType>string</propertyType>
<cardinality>multi</cardinality>
<required>false</required>
</propertyStringDefinition>
<!-- message properties -->
<propertyDateTimeDefinition>
<id>appMailarchiving:messageReceivedTime</id>
<propertyType>datetime</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyDateTimeDefinition>
<propertyIntegerDefinition>
<id>appMailarchiving:messageSize</id>
<propertyType>integer</propertyType>
<cardinality>single</cardinality>
<required>false</required>
<minValue>0</minValue>
</propertyIntegerDefinition>
<propertyStringDefinition>
<id>appMailarchiving:messageBody</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appMailarchiving:messagePriority</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appMailarchiving:messagePrivacy</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyBooleanDefinition>
<id>appMailarchiving:messageHasAttachments</id>
<propertyType>boolean</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyBooleanDefinition>
<propertyStringDefinition>
<id>appMailarchiving:messageHeaders</id>
<propertyType>string</propertyType>
<cardinality>multi</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appMailarchiving:messageDigest</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<!-- mailbox properties -->
<propertyStringDefinition>
<id>appMailarchiving:mailboxName</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appMailarchiving:mailboxMessageId</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appMailarchiving:mailboxFolder</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<propertyStringDefinition>
<id>appMailarchiving:mailboxCategory</id>
<propertyType>string</propertyType>
<cardinality>single</cardinality>
<required>false</required>
</propertyStringDefinition>
<!-- secondary object types for report, message and mailbox -->
<typeSecondaryDefinition>
<id>appMailarchiving:reportData</id>
<baseId>system:secondary</baseId>
<propertyReference>appMailarchiving:reportInfo</propertyReference>
<propertyReference>appMailarchiving:reportRecipients</propertyReference>
</typeSecondaryDefinition>
<typeSecondaryDefinition>
<id>appMailarchiving:messageData</id>
<baseId>system:secondary</baseId>
<propertyReference>appMailarchiving:messageReceivedTime</propertyReference>
<propertyReference>appMailarchiving:messageSize</propertyReference>
<propertyReference>appMailarchiving:messageBody</propertyReference>
<propertyReference>appMailarchiving:messagePriority</propertyReference>
<propertyReference>appMailarchiving:messagePrivacy</propertyReference>
<propertyReference>appMailarchiving:messageHasAttachments</propertyReference>
<propertyReference>appMailarchiving:messageHeaders</propertyReference>
<propertyReference>appMailarchiving:messageDigest</propertyReference>
<propertyReference>appMailarchiving:user</propertyReference>
<propertyReference>appMailarchiving:participants</propertyReference>
</typeSecondaryDefinition>
<typeSecondaryDefinition>
<id>appMailarchiving:mailboxData</id>
<baseId>system:secondary</baseId>
<propertyReference>appMailarchiving:mailboxName</propertyReference>
<propertyReference>appMailarchiving:mailboxMessageId</propertyReference>
<propertyReference>appMailarchiving:mailboxFolder</propertyReference>
<propertyReference>appMailarchiving:mailboxCategory</propertyReference>
</typeSecondaryDefinition>
</schema>
9.8.2. Apps
The following two apps must be enabled for all tenants that use the e-mail archive:
The e-mail archive uses object types from both app schemata.
-
The secondary types (SOTs)
appSystemmail:email
andappMailarchiving:messageData
are assigned to every stored e-mail object. -
If the e-mail is a journal report, it additionally gets the
appMailarchiving:reportData
SOT. -
If the e-mail is retrieved from a mailbox, it additionally gets the
appMailarchiving:mailboxData
SOT.
9.8.3. Role Set
It is possible to define your own roles according to your needs.
To use the e-mail archive’s default roles, set the following role set for the mailarchiving
app via POST /api/system/apps/mailarchiving/permissions
.
Default role set for 'mailarchiving' app
<roleSet xmlns="http://optimal-systems.org/ns/dmscloud/roleset/">
<role>
<name>ROLE_MAILARCHIVING_ALL</name>
<permission>
<action>create</action>
<action>read</action>
<action>delete</action>
<action>write</action>
<condition>system:secondaryObjectTypeIds in ('appMailarchiving:messageData')</condition>
</permission>
</role>
<role>
<name>ROLE_MAILARCHIVING_JOURNALING</name>
<permission>
<action>read</action>
<condition>system:secondaryObjectTypeIds in ('appMailarchiving:messageData') and appMailarchiving:user in ('Journaling')</condition>
</permission>
</role>
<role>
<name>ROLE_MAILARCHIVING_OWN</name>
<permission>
<action>read</action>
<condition>system:secondaryObjectTypeIds in ('appMailarchiving:messageData') and appMailarchiving:participants IN @abac.mailboxes</condition>
</permission>
</role>
</roleSet>
Assigning the default roles to users grants the following permissions:
-
ROLE_MAILARCHIVING_ALL
grants all permissions on DMS objects having theappMailarchiving:messageData
SOT. -
ROLE_MAILARCHIVING_JOURNALING
grants theread
permission on DMS objects having theappMailarchiving:messageData
SOT andJournaling
as value forappMailarchiving:user
. -
ROLE_MAILARCHIVING_OWN
grants theread
permission on DMS objects having theappMailarchiving:messageData
SOT and one of the actual user’s e-mail addresses is included in theappMailarchiving:participants
.
9.8.4. Webhook
The e-mail archive uses a specific user.info
webhook to enrich the user information in the internal JSON web token with an abac
section containing the corresponding user’s e-mail addresses. The enrichment is only done for users with the roles listed in mas-storage-momentum.user-info.roles
.
The e-mail archive’s webhook retrieves the user’s e-mail addresses from two data sources:
-
yuuvis® Momentum
userservice
-
Azure AD via Graph API (if access is configured)
To configure the webhook, go through the following steps:
-
Retrieve the global
systemHookConfiguration.json
viaGET /api/system/systemhooks
. -
Copy the URL of the
user.info
webhook and paste the value to themas-storage-momentum.user-info.url
parameter. -
In the global
systemHookConfiguration.json
, replace theuser.info
webhook configuration by the following configuration and apply it viaPOST /api/system/systemhooks
.Webhook configuration{ "enable": true, "predicate" : "spel:true", "type": "user.info", "url": "http://mailarchiving-storage.mailarchiving/api/abac/${tenant}/${userId}", "useDiscovery" : false }
9.8.5. Common Configuration Parameters
The following parameters are configured in the application-mas.yml
configuration file that can be read by all services with activated mas
profile. In the default configuration, this applies to masstoragemomentum
and masmailbox
.
Encryption of values
All values within the configuration file can be encrypted. This is especially recommended for credentials.
|
Parameter | Type | Description | Example value |
---|---|---|---|
|
Comma-separated string values |
Domains that are part of Active Directory are used to resolve user mails, for each mail that is part of configured domains. If empty, no user mail resolving will be invoked. Read by |
|
|
String |
Configuration parameter used to determine a value for a single user mail from the Active Directory account. This value is used to populate Possible values are:
Read by |
|
|
String |
Application authentication parameter for the Azure portal. Read by |
|
|
String |
Application authentication parameter on Azure portal. Read by |
|
|
String |
Application authentication parameter on Azure portal. Read by |
9.8.6. Configuration of 'masmailbox' Service
In addition to the common configuration parameters, the masmailbox
service uses the following service-specific parameters. They are configured either during the installation or later in the masmailbox-prod.yml
configuration file in Git.
Parameter | Type | Description | Example value | ||
---|---|---|---|---|---|
|
Integer |
Maximum number of messages in one batch request to the mailbox. The next batch is requested as soon as the processing of the previous one is completed. Thus, the larger the batch size, the higher the performance but the higher the delay of some individual messages. Value should not be greater than 999. Default is 999 (recommended). |
999 |
||
|
Integer |
Expensive health check operations of resolving mailboxes against A.D. are cached. This parameter represents health cache duration in hours. Default is 6. |
6 |
||
|
List of mailbox configurations |
Each list entry requires the following parameters:
|
|
||
|
|
A note that is assigned to all successfully archived e-mails in the mailbox to inform the mailbox user. Default is |
|
||
|
|
A note that is assigned to all e-mails in the mailbox for which the archiving failed to inform the mailbox user. Default is |
|
||
|
|
List of primary mailboxes, shared mailboxes and distribution lists for mailbox archiving. Details here. |
|
||
|
List of Strings |
Active Directory groups of type 'Distibution group' for archiving |
|
||
|
Comma-separated string values |
Folders within the mailboxes from which the service should read the e-mails for archiving.
|
|
||
|
Comma-separated string values |
Folders within the mailboxes that should be skipped (means not archived).
|
|
9.8.7. Configuration of 'masstoragemomentum' Service
In addition to the common configuration parameters, the masstoragemomentum
service uses the following service-specific parameters. They are configured either during the installation or later in the masstoragemomentum-prod.yml
configuration file in Git.
Parameter | Type | Description | Example value |
---|---|---|---|
|
Boolean |
URI of the DMS that should receive requests from storage service. |
|
|
String |
Username for yuuvis® Momentum authentication. |
|
|
String |
Password for yuuvis® Momentum authentication. |
|
|
String |
Tenant in yuuvis® Momentum. |
|
|
Structure of mailbox-mappings |
Property contains multiple mailbox mappings. The yuuvis® Momentum user with the e-mail defined as key gets access to mails from the mapped mailboxes. The key part of configuration (i.e. mail address in square brackets and quotes) needs to be the same as in yuuvis® Momentum. |
|
|
String |
Original URL for retrieval of user roles via |
|
|
Structure of listed role per line starting with the dash (see Value example column for clarification). |
Represents a user role for which the Default:
|
|
9.8.8. Configuration of 'massmtp' Service
In addition to the common configuration parameters, the massmtp
service uses the following service-specific parameters. They are configured either during the installation or later in the massmtp-prod.yml
configuration file in Git.
Parameter | Type | Description | Example value | ||
---|---|---|---|---|---|
|
Integer |
Port on which SMTP will listen for the incoming messages. Must be greater than 1024. Default is 25000. |
25000 |
||
|
String |
Username for SMTP authentication. |
|
||
|
String |
Password for SMTP authentication. |
|
||
|
Boolean |
Value should be set to |
|
||
|
String |
In case TLS is required, this property should contain the path to the file with the SSL certification. |
<absolute file path> |
||
|
String |
In case TLS is required, this property should contain the password for the key-store-file. |
|
||
|
String |
In case TLS is required, this property should contain the value for key store type. Default is |
|
||
|
String |
List of comma-separated entries that represent allowed senders for incoming SMTP messages. If empty, all senders will be allowed.
|
|
||
|
String |
List of comma-separated entries that represent allowed recipients for incoming SMTP messages. If empty, all recipients will be allowed.
|
|
||
|
String |
Determines which kind of messages will be received via SMTP channel. Available values:
|
|
9.9. Maintenance
9.9.1. Health Checks
Calling the health check endpoint GET <service>/manage/health
for the individual services triggers multiple health checks for the corresponding components. The response JSON contains the following service-specific information.
Health Check for 'masstoragemomentum'
Parameter | Response Example for status UP | Response Example for status DOWN |
---|---|---|
DMS Health Check |
||
|
|
|
|
|
|
|
|
|
|
|
<error message> |
Schema Health Check |
||
|
|
|
|
|
<error message> |
User Directory Health Check |
||
|
|
|
Health Check for 'massmtp'
Parameter | Response Example for status UP | Response Example for status DOWN |
---|---|---|
SMTP Health Check |
||
|
|
|
|
|
|
|
|
|
|
|
|
Health Check for 'masmailbox'
(Example) Parameter | Response Example for status UP | Response Example for status DOWN |
---|---|---|
Mailbox Archiving Health Check |
||
|
|
|
|
|
|
|
|
|
|
|
|
Mailbox Journaling Health Check |
||
|
|
|
|
|
|
|
|
|
|
|
|
9.9.2. Logs
The logs of the individual services can be accessed via the following commands.
-
Check the pod number of the service for which you need the log:
kubectl get pods -n 'pod_namespace'
-
Get the logs of the corresponding pod:
kubectl -n 'pod_namespace' logs 'pod_name'
-
To export the logs to a file, add the following additional parameters:
kubectl -n 'pod_namespace' logs 'pod_name' > filename.log
Alternatively, a 3rd-party tool like, e.g., OpenLens can be used to manage pods and access logs:
-
Open OpenLens and connect to the cluster.
-
Select the Workloads tab on the left.
-
Select Pods from the expanded Workloads tab.
-
Find the pod that starts with the service name.
-
Select the Settings Icon of the pod and select Logs.
-
Optional: Export the logs by clicking Download on the bottom right.
9.10. Metrics
The metrics can be accessed via the services' ports using the endpoint https://<ip>:<port>/manage/metrics
.
For example, the number of stored e-mails can be retrieved via https://<ip>:<port>/manage/metrics/storage_messages_processed_total
.
Internal Endpoint
This endpoint is available only for services within the yuuvis® Momentum cluster. Never expose it for public access in the authentication-prod.yml configuration file.
|
Within the yuuvis ® Momentum cluster, this endpoint can be called by monitoring tools such as Prometheus. The cluster admin can extend the prometheus configuration as shown in the following example.
scrape_configs:
- job_name: "masstorage"
scrape_interval: 15s
metrics_path: '/manage/prometheus'
static_configs:
- targets: ["localhost:8130"]
- job_name: "massmtp"
scrape_interval: 15s
metrics_path: '/manage/prometheus'
static_configs:
- targets: ["localhost:8120"]
- job_name: "masmailbox"
scrape_interval: 15s
metrics_path: '/manage/prometheus'
static_configs:
- targets: ["localhost:8110"]
10. Release Information
10.1. Version Maintenance
yuuvis® Momentum is released in a release train strategy, with one release per quarter. The releases are labelled with a year and season, e.g., 2023 Spring, 2023 Summer, 2023 Autumn etc. In the regular maintenance package, a one-year long-term support (LTS) release is included.
10.1.1. Regular Maintenance
Every Winter release will always be treated as a regular LTS release and will be maintained for the duration of one year and one quarter, until the next Winter release is available, which then supersedes the previous LTS release. There are no further features added in an LTS version during the maintenance period. For example, 2022 Winter will be the regular LTS version, and will be supported for an additional quarter after 2023 Winter is released, which is until 2024 Spring. During this time, new features will be made available in releases 2023 Spring, 2023 Summer, 2023 Autumn and ultimately 2024 Winter which will then become the new regular LTS release.
All releases between two Winter releases (Spring, Summer and Autumn) will supersede each other sequentially in the order of their release. For example, release 2023 Spring will be maintained until release 2023 Summer (three months). After 2023 Summer is released, 2023 Spring will not be maintained anymore, and all fixes will be available in the 2023 Summer version only.
10.1.2. Updates and Compatibility
Update is possible and guaranteed:
-
Between two successive regular LTS releases, for example 2022 Winter to 2023 Winter. We furthermore require that all hotfixes are applied to the previous regular LTS before the update.
-
Between all releases from the release train of the same year, for example 2023 Spring to 2023 Summer or 2023 Autumn.
We make no further statements about version compatibility of different releases. We expect furthermore that releases are installed completely and do not allow mixing of components from different releases. The individual components within a release will respect and follow the semantic versioning, where major component version denotes API breaking changes.
10.2. Requirements and Dependencies
yuuvis® Momentum is a product with a lot of variety for customers. The core services can be combined with different third-party software products, selected by the customers according to their needs.
The systems listed have been tested in the listed versions together with the current release in the OPTIMAL SYSTEMS release tests and their compatibility has been ensured.
yuuvis® Momentum uses standardized interfaces and integration technologies, meaning that yuuvis® Momentum also works with a wide range of older or more recent versions of the systems listed and with other unlisted systems. OPTIMAL SYSTEMS does not guarantee compatibility for systems not listed in the system requirements and performs its services subject to restrictions (in particular, no damage repair) in accordance with the prevailing maintenance contracts. In addition, OPTIMAL SYSTEMS guarantees compatibility with a listed system up until the date that the manufacturer guarantees regular (for example, not extended, expanded, individually agreed) support. |
The system requirements describe the infrastructure needed for a productive yuuvis® Momentum system to provide adequate operational performance. This information is a set of non-binding guidelines. OPTIMAL SYSTEMS can only give a guarantee for a specific system environment on the basis of a customized hardware constellation. |
10.2.1. Core
Kubernetes
Kubernetes is required for installation and operation of yuuvis® Momentum instances. The versions listed below are supported.
Kubernetes Version |
---|
1.19 |
1.20 |
1.21 |
1.22 |
1.23 |
1.24 |
1.25 |
1.26 |
1.27 |
1.28 |
1.29 |
1.30 |
Helm
Deployments for yuuvis® Momentum are offered via Helm charts and thus require the installation of Helm. The supported versions are listed below.
Helm Versions |
---|
3.2.4 |
Databases
yuuvis® Momentum requires a relational database instance to store and manage metadata and content files. Many software products are available and can be combined with yuuvis® Momentum. We highly recommend providing yuuvis® Momentum with an exclusive database to ensure performance.
The system requirements for the individual manufacturers must be observed for operation of the relevant database system.
yuuvis® Momentum supports the following databases:
Database Management System | Version | |
---|---|---|
PostgreSQL |
14.x |
|
15.x |
||
16.x |
||
CockroachDB |
19.2.1 - 20.2 and 21.1 |
|
Microsoft SQL Server |
2012 (32- and 64-bit) |
|
2014 (32- and 64-bit) |
||
2016 (32- and 64-bit) |
||
2017 (32- and 64-bit) |
||
2017 (32- and 64-bit) |
||
2019 (32- and 64-bit)
|
Search Engine
yuuvis® Momentum works together with the open source search engine Elasticsearch. The following versions are tested with the current yuuvis® Momentum release.
Elasticsearch Versions |
---|
7.17.x (as of 2023 Autumn) |
7.16.x |
7.9.x |
7.3.x |
In order to operate Elasticsearch together with yuuvis® Momentum, the following plugins are additionally required. Please install a version that is supported by your Elasticsearch version.
-
Intrafind Linguistic Plugin
-
ICU Analysis Plugin
Redis
In order to ensure synchrony in internal processes of yuuvis® Momentum, an in-memory data structure store is required. Our tested recommendation is Redis.
Redis Versions |
---|
6.x |
7.x |
Messaging Systems
yuuvis® Momentum uses the OASIS Advanced Message Queuing Protocoll (AMQP) Version 1.0 for internal messaging. The messaging systems of the corresponding versions listed below are tested with yuuvis® Momentum. Since RabbitMQ does not support AMQP Version 1.0, an additional plugin is required.
Messaging System | Versions | Additional Required Plugin |
---|---|---|
ActiveMQ |
5.15.4 |
- |
RabbitMQ |
3.8.9 - 3.12 |
rabbitmq_amqp1_0 |
Git
We strongly recommend to use Git as config store for yuuvis® Momentum, that acts as a version control system at the same time. In general, any git server should be sufficient. However, we tested the git servers listed below with the corresponding versions.
Git Server | Minimum Required Version |
---|---|
Gogs |
0.11.91 |
Gitea |
1.12.0 |
GitLab |
11.10.8 |
Identity Provider
For operation of yuuvis® Momentum, an authentication provider is required. In general, any authentication provider supporting the OAuth 2.0 protocol can be combined with yuuvis® Momentum. However, we perform all our tests with Keycloak. The supported versions are listed below.
Keycloak Versions |
---|
7.0.0 |
10.0.2 |
11.0.2 |
15.0.2 |
19.0.2 |
22.0.2 (as of 2023 Autumn) |
23.0.6 (as of 2024 Spring) |
24.0.2 (2023 Winter - 2024 Summer) |
Storage
S3 Store
yuuvis® Momentum is working with an S3 directory that has to be connected via a service supporting the S3 protocol. All our tests are performed with MinIO, that can operate as store and as protocol service at the same time. It can also be used to connect an S3 store of a different provider to yuuvis® Momentum.
MinIO Versions |
---|
RELEASE.2020-10-18T21-54-12Z |
Optional: Further Supported Archive Drivers
The repository
Service allows to connect additional archives. The following archive drivers are supported. The configuration parameters have to be specified in the application-storage.yml
configuration file.
Provider | Version | Supported Protocols | Archive-Internal Retention |
---|---|---|---|
Cloudian HyperStore |
7.2 |
s3-based |
supported |
Dell EMC ECS (Elastic Cloud Storage) |
DellECM-ECS-CE-3.7 |
S3 REST API |
supported |
NetApp |
file system-based |
supported |
|
Azure Blob Storage |
REST API |
supported |
|
Google Cloud Storage |
REST API |
supported |
|
File System |
not supported |
The following archives are connected via archive
service. As most of the drivers are now directly available via repository
service, they are labeled as deprecated for the archive
service. We recommend the drivers of the repository
service if they are available, as they are faster and no additional archive
service is required.
The configuration parameters have to be specified in the application-storage.yml
configuration file as well.
Provider | Version | Supported Protocols | Archive-Internal Retention |
---|---|---|---|
Hitachi Content Platform |
7.3.0.6 |
s3-based |
supported |
deprecated: iTernity Compliant Archive Software (iCAS) |
3.7 |
iCAS |
supported |
deprecated: Cloudian HyperStore |
7.2 |
s3-based |
supported |
deprecated: Dell EMC ECS (Elastic Cloud Storage) |
DellECM-ECS-CE-3.7 |
S3 REST API |
supported |
deprecated: NetApp |
file system-based |
supported |
|
deprecated: Azure Blob Storage |
REST API |
supported |
10.2.2. Client Development
Developer Libraries
- yuuvis® Momentum Services
-
In addition to the yuuvis® Momentum core services, the developer libraries require further services. Please check their third-party requirements.
-
Web-API Gateway (API-WEB)
-
VIEWER Service
-
BPM-ENGINE Service (only for process and task management)
-
TENANT-MANAGEMENT Service (only idm-controller endpoints)
yuuvis® Momentum client as reference implementation uses the full functionality of the developer libraries. Thus, all listed services are required. -
Web API
- yuuvis® Momentum Services
-
In addition to the yuuvis® Momentum core services, the Web-API Gateway requires further services. Please check their third-party requirements.
-
USERSERVICE
-
SOTHOOK
-
BPM-ENGINE Service
-
TENANT-MANAGEMENT Service (only idm-controller endpoints)
-
yuuvis® architect
- yuuvis® Momentum Services
-
In addition to the yuuvis® Momentum core services, yuuvis® architect requires further services. Please check their third-party requirements.
-
Web-API Gateway (API-WEB)
-
TENANT-MANAGEMENT Service
-
Keycloak
As yuuvis® architect uses admin- and system-controller of the Tenant Management API, Keycloak as required as identity management system. The same versions as for the Tenant Management API are supported.
-
Content Viewer API
- yuuvis® Momentum Services
-
In addition to the yuuvis® Momentum core services, the VIEWER Service requires further services.
-
office365
Service (only for Office 365 integration)
-
Office 365 Integration
To integrate the Microsoft Office 365 editing functionality, you need an authentication license for the Microsoft Office 365 Platform.
The viewing functionality of Microsoft Office 365 is available without a dedicated license.
User Profile API
- Database
-
For operation of the
userservice
, a database is required. The same database systems as for the core services are supported.
10.2.3. Administration Tools
Tenant Management API
- Identity Management Provider
-
In order to operate the idm-controller of the Tenant Management API, the service requires an authentication provider supporting OAuth2, e.g., Keycloak. If you do not use Keycloak, you need to implement a custom proxy that converts the request formats. An example implementation is available on request as a beta version.
In order to operate also the admin- and system-controller of Tenant Management API, Keycloak is required as identity management provider. The supported versions are listed below.
Keycloak Versions 11.0.2 (up to 2021 Winter)
15.0.2 (2022 Spring, 2022 Autumn)
19.0.2 (2022 Winter - 2023 Summer)
22.0.2 (2023 Autumn)
24.0.2 (2023 Winter - 2024 Summer)
Service 'keycloak-proxy'
- Keycloak
-
The service supports only Keycloak as authentication provider. The supported versions are listed below.
Keycloak Versions 11.0.2 (up to 2021 Winter)
15.0.2 (2022 Spring, 2022 Autumn)
19.0.2 (2022 Winter - 2023 Summer)
22.0.2 (2023 Autumn)
24.0.2 (2023 Winter - 2024 Summer)
10.2.4. Business Process Management
BPM Engine API
- Database
-
For operation of the BPM Engine, a database is required. Following providers and versions are supported:
Database Management System Version PostgreSQL
9.4 - 11.10.0
Microsoft SQL Server
2012 (32- and 64-bit)
2014 (32- and 64-bit)
2016 (32- and 64-bit)
2017 (32- and 64-bit)
As of 2021 Winter: 2019 (32- and 64-bit)
- Identity Management Provider
-
The BPM Engine needs access to the identity provider that is used for the yuuvis® Momentum cluster. The identity provider has to support the Custom IDM API shown below (e.g., Keycloak). If you want to use an identity provider that does not support the Custom IDM API, the TENANT-MANAGEMENT Service is required.
Custom IDM API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
openapi: 3.0.1 info: title: Custom IDM API version: v1.0 paths: /roles: get: tags: - Roles description: Get all roles operationId: getRoles responses: '200': description: Indicates request was successful and the roles are returned. content: application/json: schema: type: array items: $ref: '#/components/schemas/CustomIdmRoleResponse' /roles/{roleId}/users: get: tags: - Roles description: Get all users with given role. operationId: getRoleMembers parameters: - name: roleId in: path description: Identifier of the role required: true schema: type: string example: YUUVIS_TENANT_ADMIN responses: '200': description: Indicates request was successful and the members are returned. content: application/json: schema: type: array items: $ref: '#/components/schemas/CustomIdmUserResponse' /users: get: tags: - Users description: Get all users operationId: getUsers parameters: - name: page in: query description: Zero-based page index (0..N) schema: type: integer default: 0 - name: size in: query description: The size of the page to be returned schema: type: integer default: 20 - name: sort in: query description: 'Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.' schema: type: array items: type: string responses: '200': description: Indicates request was successful and the users are returned. content: application/json: schema: type: object title: PageResponse properties: objects: type: array items: $ref: '#/components/schemas/CustomIdmUserResponse' numItems: type: integer format: int32 example: 50 totalNumItems: type: integer format: int64 example: 1234 hasMoreItems: type: boolean example: true /users/{userId}: get: tags: - Users description: Get an user operationId: getUserById parameters: - name: userId in: path description: Identifier of the user required: true schema: type: string example: YUUVIS_TENANT_ADMIN responses: '200': description: Indicates request was successful and the user is returned. content: application/json: schema: $ref: '#/components/schemas/CustomIdmUserResponse' components: schemas: CustomIdmRoleResponse: type: object properties: name: type: string CustomIdmUserResponse: type: object properties: id: type: string username: type: string firstName: type: string lastName: type: string email: type: string roles: type: array items: type: string
10.2.5. AI Platform
- Database
-
The AI Platform requires a SQL database to log model metrics. While PostGreSQL is our most frequently tested database driver, multiple other solutions have been proven to work with the platform.
Database Management System Version PostGreSQL
9.4 - 11.10.0
Microsoft SQL
2012, 2014, 2016, 2017, 2019
CockroachDB
20.2, 21.1
- Elasticsearch
-
The
predict-api
service can infer models that make use of Elasticsearch backend to improve prediction quality.Elasticsearch Version 7.16.3
10.2.6. SAP® Integration
Requirements of 'repositorymanager'
-
ActiveMQ
-
Space for PersistentVolumeClaim
Requirements of 'repositorymanager-cmis'
- SAP® compatibility
-
-
SAP® S/4HANA CLOUD, PUBLIC EDITION and all subsequent releases
-
SAP® Basis release 752
-
- Storage
- Antivirus Engine
-
-
The installation of the
repositorymanager-cmis
service contains ClamAV as default.
-
Requirements of 'repositorymanager-ilm'
- SAP® compatibility
-
-
SAP® NetWeaver 7.5
-
SAP® S/4HANA 2020 and all subsequent releases
-
- Instance of 'repositorymanager' serivce
-
For retention propagation, an instance of the
repositorymangager
service with enabled ArchiveLink functionality is required.
10.2.7. E-mail Archive
- E-Mail Provider
-
The service requires an e-mail provider. The following systems are supported:
-
Microsoft Exchange Online
-
Every system using the SMTP protocol
-
- Further 3rd Party Requirements
-
In some specific use cases, the following 3rd party software is required:
-
In case the mailbox is pulling from MS Exchange Online: Graph API is required
-
In case premium journaling for MS Exchange 2016/2019 is used: CAL enterprise license is required
-
- Recommended 3rd Party Software
-
-
Prometheus – used for scraping and graphical visualization of operation data
-
Grafana – can be used for a more elaborated visualization of operation data
-
10.3. Installation Guide
This installation guide will help you to install yuuvis® Momentum via Helm charts to operate it in a Kubernetes cluster. We assume readers are familiar with Kubernetes and Helm commands. Start with Helm charts for testing purposes and replace default third-party software according to your preferences.
Each yuuvis® Momentum installation contains the core services provided in the yuuvis Helm chart. Most of our optional additional services are available via separate Helm charts as well.
After the installation, we recommend testing your system, e.g., with Postman.
10.3.1. Requirements
Check the requirements and recommendations of third-party software in order to set up a productive yuuvis® Momentum system.
10.3.2. Installation
-
Clone the
yuuvis-api-helm-charts
repository as working directory (see Docker Images). -
Adjust the
values.yaml
configuration files in all Helm charts you want to install.-
Add your credentials for the
docker.yuuvis.org
registry. Replace allchangeme
default passwords.For any questions about credentials please contact our support department.
-
If you want to operate multiple instances of individual services within your Kubernetes cluster, you can enable the PodDisruptionBudget for those services via the
pdb
parameters. After the installation, the corresponding<service>-pdb.yaml
Kubernetes configuration files ensure that NOT all instances of the corresponding service are shut down at the same time, e.g., for service updates.-
Set a minimum number of instances for
pdb.minAvailable
that always have to be kept running,OR
-
set a maximum number of instances for
pdb.maxUnavailable
that are allowed to be shut down at the same time. Setpdb.minAvailable: null
.
-
Ensure that your resulting minimum number of running instances is lower than the total number of instances. Otherwise, it is not possible to restart the corresponding service at all. -
If you want to specify a Kubernetes node where to operate your yuuvis® Momentum services, you can use the
nodeSelector
configuration parameter for the individual services.
-
All yuuvis® Momentum services reach out to the configservice
on startup to retrieve their configuration files, which results in a short delay before that services are fully operable. The yuuvis
chart configures the authentication
and organization
services for OAuth2 with the tenant myfirsttenant
(in the default configuration).
Helm Chart 'infrastructure'
The infrastructure
Helm chart provides third-party software that can be combined with yuuvis® Momentum in order to build a test system. You should replace those components according to your preferences and needs in your productive system:
Infrastructure Component | Function |
---|---|
PostgreSQL |
database service |
Elasticsearch |
search engine |
Minio |
object storage |
Gitea |
self-hosted Git service |
RabbitMQ |
message broker |
Keycloak |
identity and access management service |
Redis |
in-memory data structure store |
In order to install and use the set of third-party software provided in the infrastructure Helm chart, follow these steps:
-
Add the required Helm repositories:
helm repo add minio https://charts.min.io/ helm repo add bitnami https://charts.bitnami.com/bitnami helm repo add gitea-charts https://dl.gitea.io/charts/ helm repo add codecentric https://codecentric.github.io/helm-charts/
-
Update the Infrastructure dependencies:
cd infrastructure helm dep up helm repo add stable https://charts.helm.sh/stable cd ..
-
Adjust the
values.yaml
file:-
Adjust the docker registry credentials.
-
Specify the address of your yuuvis® Momentum cluster by setting your
CLUSTER_IP
or yourauthentication
service’sLOAD_BALANCER_IP
for the parameteryuuvis.authentication.ip
. -
Optionally change passwords.
-
Optionally change the used storage classes.
-
-
Install the infrastructure services. Naming the chart during installation is necessary as each service would otherwise receive a default prefix from Kubernetes, making it difficult for the yuuvis® Momentum services to interact with them later. This also enables us to rollback our installation.
kubectl create namespace infrastructure helm install infrastructure ./infrastructure --namespace infrastructure
-
Wait until the jobs are done.
kubectl get jobs -n infrastructure
There are two jobs preparing the git server and the Keycloak environment that need to be completed.
NAME COMPLETIONS DURATION AGE gogsrepo-init 1/1 83s 8m4s keycloak-create-selfsigned-cert 1/1 8m4s 8m4s
-
Run the following command to see if the
infrastructure
chart was deployed (STATUS DEPLOYED).helm list --namespace infrastructure
Helm Chart 'yuuvis'
-
Adjust the
values.yaml
file:-
Adjust the docker registry credentials.
-
If you are using Keycloak as identity provider, specify its address by setting your
CLUSTER_IP
or your Keycloak’sLOAD_BALANCER_IP
for the parameteryuuvis.keycloak.address
. -
In the section
initjob
, use the parametercreaterealm
to activate (true
, default) or deactivate (false
) the creation of an initial tenant including an administrative user. This user will have all default roles. If you do not change the default configuration, a tenantmyfirsttenant
with a userroot
will be created in Keycloak. -
If you change
createrealm
tofalse
, configure your tenant(s) in theoauth2
section or after the installation in theapplication-oauth2.yml
configuration file in your git repository.
-
-
Navigate to the root Helm chart directory within the cloned repository.
-
Install the Helm chart. Naming this chart prevents randomization of service identifiers and gives us the ability to rollback all associated services.
kubectl create namespace yuuvis helm install yuuvis ./yuuvis --namespace yuuvis
-
Wait for the pods to be ready:
kubectl get po -n yuuvis
Helm Chart 'client'
-
Adjust the docker registry credentials.
-
Check the profiles to be activated for the
userservice
in theyuuvis.client.userservice.profiles
. During the deployment, they will be set as value for theSPRING_PROFILES_ACTIVE
environment variable.-
Use
dbsprostgres
(default),dbsmssql
ORdbscockroach
to specify the database type. -
Use
swagger
to enable the creation of a Swagger UI.
-
-
Adjust the database credentials
yuuvis.client.userservice.database.address
,yuuvis.client.userservice.database.user
andyuuvis.client.userservice.database.password
. During the deployment, they will be set as values for the environment variablesDB_HOST
,DB_USER
andDB_USER
. -
Install the Helm chart:
helm install client ./client --namespace yuuvis
-
Wait for the pods to be ready:
kubectl get po -n yuuvis
The installation of the
client
Helm chart will change the app-specificsystemHookConfiguration.json
for theclientsystem
app. Services referring to this configuration will only read it once at startup. Thus, the corresponding services must be restarted to apply the new configuration. For example, restart the API Gateway via:kubectl rollout restart deployment api -n yuuvis
-
To enable users to create objects, define a suitable role and assign it to them.
Helm Chart 'bpm'
-
Adjust the docker registry credentials.
-
Check the profiles to be activated for the
bpm-engine
service in theyuuvis.bpm.engine.profiles
. During the deployment, they will be set as value for theSPRING_PROFILES_ACTIVE
environment variable.-
Use
dbsprostgres
(default) ORdbsmssql
to specify the database type. -
Use
swagger
to enable the creation of a Swagger UI. -
Use
oauth2
to enable the usage of the authentication parameters in theapplication-oauth2.yml
configuration file.
-
-
Adjust the database credentials
yuuvis.bpm.engine.database.address
,yuuvis.bpm.engine.database.user
andyuuvis.bpm.engine.database.password
. During the deployment, they will be set as values for the environment variablesdb.host
,db.user
anddb.pwd
. -
Install the Helm chart:
kubectl get po -n yuuvis helm install bpm ./bpm --namespace yuuvis
Helm Chart 'rendition'
-
Install the Helm chart:
kubectl get po -n yuuvis helm install rendition ./rendition --namespace yuuvis
Helm Chart 'repositorymanager'
This Helm chart installs the repositorymanager
service. It is a connector that provides a solution for ArchiveLink and ILM protocols of SAP.
It is possible to have more than one instance of the repositorymanager
service. To use that possibility, the repositorymanager
service will not be part of yuuvis
namespace. Every instance has to be created in a new namespace.
CORS Ingress
For the communication with SAP® protocols, please disable CORS e.g. via |
-
Adjust the docker registry credentials and the chart’s
values.yaml
configuration file. -
Install the Helm chart:
-
Check if the core services in the
yuuvis
namespace are running:kubectl get po -n yuuvis
-
Create a new namespace for every
repositorymanager
instance, e.g. xxxxxkubectl create namespace xxxxx
-
Ensure that the correct values are set in the
values.yml
(credentials, ports, profile, tenant…)helm install repositorymanager ./repositorymanager --namespace xxxxx
-
Helm Chart 'repositorymanagerilm'
This Helm chart installs the repositorymanager-ilm
service. It is a connector to the SAP® via ILM protocol.
-
Adjust the docker registry credentials and
repositorymanager-ilm
service configuration parameters in the chart’svalues.yaml
configuration file. -
Install the Helm chart:
-
Check if the core services in the
yuuvis
namespace are running:kubectl get po -n yuuvis
-
Create a new namespace for every
repositorymanager-ilm
service instance, e.g.repositorymanagerilm
kubectl create namespace repositorymanagerilm
-
Ensure that the correct values are set in the
values.yml
(docker credentials and image version, profile, tenant…)helm install repositorymanagerilm ./repositorymanagerilm --namespace repositorymanagerilm
-
Helm Chart 'repositorymanagercmis'
This Helm chart installs the repositorymanager-cmis
service. It is a connector to SAP® via CMIS interface.
-
Adjust the docker registry credentials and
repositorymanager-cmis
service configuration parameters in the chart’svalues.yaml
configuration file. -
Install the Helm chart:
-
Check if the core services in the
yuuvis
namespace are running:kubectl get po -n yuuvis
-
Create a new namespace for every
repositorymanager-cmis
service instance, e.g.repositorymanagercmis
kubectl create namespace repositorymanagercmis
-
Ensure that the correct values are set in the
values.yml
(docker credentials and image version, profile, tenant…) -
Especially, configure the credentials for the cross-tenant service account that should be used by the
repositorymanager-cmis
servicerepositorymanager-cmis: yuuvis: technical: gateway: https://myhost.net tenant: testtenant username: testuser password: changeme
-
Start the actual installation process.
helm install repositorymanagercmis ./repositorymanagercmis --namespace repositorymanagercmis
-
Helm Chart 'mailarchiving'
The Helm chart contains the following services for installation:
-
mailarchivingsmtp
(installs themassmtp
service) -
mailarchivingmailbox
(installs themasmailbox
service) -
mailarchivingstorage
(installs themasstoragemomentum
service)
The Helm charts are constructed in such a way that each service can be independently installed. The installation of mailarchivingstorage
is required. It creates an application-mas.yml
configuration file. It will be read by the masstoragemomentum
service and by the masmailbox
service as well (if mailarchivingmailbox
is installed as described below).
In addition to mailarchivinstorage
, you can install mailarchivingsmtp
and/or mailarchivingmailbox
according to your needs.
Installation steps:
-
Install the
mailarchivingstorage
Helm chart:-
Change the needed values in the
mailarchiving/mailarchivingstorage/values.yml
file. Detailed information on configuration parameters are available in the service description section.Using 'masmailbox'If you wantmasmailbox
to run, ensure that correct Exchange Online Access credentials are added. This precondition is not needed for runningmassmtp
. -
Start the installation.
# Check if yuuvis core services running (namespace yuuvis is example, yuuvis core services can be in namespace with another name) kubectl get po -n yuuvis # For every instance create new namespace e.g. xxxxx kubectl create namespace xxxxx # Make sure correct values are set in values.yml (credentials, ports, profile, tenant...) helm install mailarchivingstorage ./mailarchiving/mailarchivingstorage --namespace xxxxx
-
-
Optional: Install the
mailarchivingsmtp
Helm chart:-
Change needed values in
mailarchiving/mailarchivingsmtp/values.yml
-
Start the installation.
# Check if yuuvis core services running (namespace yuuvis is example, yuuvis core services can be in namespace with another name) kubectl get po -n yuuvis # Check if storage service running in xxxxx namespace kubectl get po -n xxxxx # Make sure correct values are set in values.yml (credentials, ports, profile, tenant...) helm install mailarchivingsmtp ./mailarchiving/mailarchivingsmtp --namespace xxxxx
-
-
If wanted: Install the
mailarchivingmailbox
Helm chart-
Please change needed values in
mailarchiving/mailarchivingmailbox/values.yml
-
Start the installation.
# Check if yuuvis core services running (namespace yuuvis is example, yuuvis core services can be in namespace with another name) kubectl get po -n yuuvis # Check if storage service running in xxxxx namespace kubectl get po -n xxxxx # Make sure correct values are set in values.yml (credentials, ports, profile, tenant...) helm install mailarchivingmailbox ./mailarchiving/mailarchivingmailbox --namespace xxxxx
-
10.3.3. Deinstallation
Helm does not delete persistent volumes. Those data have to be deleted manually. |
Helm Chart 'infrastructure'
-
The rollback of the installation is possible via:
helm uninstall infrastructure --namespace infrastructure
-
After uninstalling, run the following two commands:
kubectl delete clusterrole create-selfsigned-cert kubectl delete clusterrolebinding create-selfsigned-cert
Helm Chart 'monitoring'
-
The rollback of the installation is possible via:
helm uninstall monitoring --namespace monitoring helm uninstall prometheus-operator --namespace infrastructure
-
Delete the final setup for monitoring via:
kubectl delete servicemonitor --all -n infrastructure and kubectl delete prometheusrule --all -n infrastructure
Helm Chart 'yuuvis'
-
The rollback of all associated services is possible via:
helm uninstall yuuvis --namespace yuuvis
10.4. Update Guide
When updating your yuuvis® Momentum installation, manual configuration changes are required for some services.
After adjusting the configurations, the version update can be done via Helm.
We provide a detailed update guide for the following Update processes:
-
from version 2024 Spring to version 2024 Summer
For updates from other versions to 2024 Summer, we recommend to update version by version. Please refer to the individual breaking changes and configuration requirements on your own responsibility.
10.4.1. From 2024 Spring to 2024 Summer
Handling the Breaking Changes
The following breaking changes are incompatible changes, and therefore you need to be aware of them and take action accordingly. |
Infrastructure
- Identity Provider
-
Support of Keycloak 24
Keycloak 24 is now supported as identity provider. The following services require the new version:
-
tenant-management
service -
bpm-engine
service -
keycloak-proxy
service -
architect
service
-
Core
- DMS Objects
-
Text Rendition via Lifecycle
As the full-text indexing is now managed via lifecycle, the following services are obsolete and no longer part of yuuvis® Momentum installations:
-
controller
service -
textextractor
service
Instead, the
renditiontextworker
service is installed. This change requires the following configuration steps:-
Create a cross-tenant service account for the
renditiontextworker
service. -
Configure its credentials via environment variables for the
renditiontextworker
service:-
YUUVIS_TENANT
- The tenant in which the cross-tenant service account is created. -
YUUVIS_USER
- The username of the cross-tenant service account. -
YUUVIS_PASSWORD
- The password of the cross-tenant service account.
-
-
Optional: The values can be protected in a Kubernetes secret.
-
Optional: If you want to store the calculated text renditions in the rendition repository, set the parameter
rendition.store.text: true
in a service-specific YAML configuration file, e.g.renditiontextworker-prod.yml
. -
Adjust the global system hook configuration:
-
Remove the AMQP hook that connects the
lc.textextraction
queue:Previous 'systemhookconfiguration.json'{ "systemhooks": { "amqp": [ ... { "bulkSize": 10, "enable": true, "password": "secret", "predicate": "spel:(contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null && contentStreams[0]['range'].length() > 0) ? true : false", "queue": "lc.textextraction", "type": "object.insert.document", "url": "10.10.6.243:5674", "user": "clouduser" } ... ], "lifecycle": [...], "webhooks": [...] } }
-
Add the following lifecycle hook configuration:
New 'systemhookconfiguration.json'{ "systemhooks": { "amqp": [...], "lifecycle": [ ... { "type" : "dms.request.objects.upsert.database-before", "enable" : true, "predicate" : "spel:contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null", "tagname": "system:ren:text", "tagstate": 1 } ... ], "webhooks": [...] } }
-
-
Enabling specific new Features
SAP® Integration
- 'repositorymanager' Service
-
Configuration handling
-
Before updating the
repositorymanager
service, check thewebapp/cs
configuration directory. Delete all configuration folders that should be replaced by the default configuration. -
If a default configuration folders is missing in the
webapps/cs
directory (e.g.,conf
,META-INF
,WEB-INF
) during the version update, it is added with the default configuration settings. -
Especially, if the KGS version after the update will not be compatible with the version before the update, delete the
WEB-INF
folder before the update. Otherwise the incompatible configuration is kept and has to be manually adjusted.
-
- SAP® ILM Controller
-
Activation of SAP® ILM Controller
Requirementsrepositorymanager
service version 4 with enabled ILM functionality is required.-
Check current configuration
-
In the cluster that contains your
repositorymanager
4, open therepositorymanager-prod.yaml
configuration file. -
Note the tenant for which the service is configured (
core.api.tenant
property).
-
-
Installation of 'repositorymanager-ilm'
-
Install the new service via Helm chart in the same cluster.
-
Adjust the
rmilm-prod.yml
configuration file as shown below. -
Check if an ingress controller with correct tenant information is created for the
repositorymanger-ilm
service. Both servicesrepositorymanger-ilm
andrepositorymanager
have to use the same tenant. -
If the yuuvis® Momentum api gateway uses a different namespace than
repositorymanager-ilm
, set the value in therepositorymanager-ilm.yuuvis.api-url
property.
-
-
Configure Connection in the SAP
-
Deprecated configuration:
The Target Host is the ingress configuration that directly exposes the service. The path prefix is
cs/ilm
. Username and password used for this connection are the username and password configured in the KGS. -
New configuration:
The Target Host is the ingress that contains information on the tenant used by the
repositorymanager-ilm
service (in this examplesapilm
).The path prefix now also contains
repositorymanager-ilm
service`s URL as used by the ingress, followed by/cs/ilm
.Username and password for Basic Authentication can be any user within the tenant that has read/write rights on the
repositorymanager
app.
-
-
Update the Helm Charts
-
All Helm charts except the infrastructure chart can be updated to a new version via:
helm upgrade -n <namespace> <chart name> <chart location>
For the concrete individual charts this means:
helm upgrade -n yuuvis yuuvis yuuvis helm upgrade -n yuuvis bpm bpm helm upgrade -n yuuvis client client helm upgrade -n yuuvis rendition rendition
-
The third-party infrastructure components have to be updated via individual docker images:
-
Use our current Docker image for Elasticsearch as it includes the required plug-ins.
-
Optionally, use our Keycloak Docker image.
-
Updates for all further third-party components are within the customer’s responsibility.
-
10.5. Docker Images
The services are available at: http://docker.yuuvis.org/yuuvis/
10.5.1. Helm Charts on GitHub
Version | Helm charts on Git Hub |
---|---|
2024 Summer |
10.5.2. Core Services
Service Name | tag - product v. 2024 Summer |
---|---|
Gateway |
|
API |
api-gateway:4.19.2 |
Basic Core Services |
|
authentication |
authentication:4.19.2 |
SYSTEM |
system:4.19.2 |
repository |
repository:4.19.2 |
registry |
registry:4.19.2 |
index |
index:4.19.2 |
search |
search:4.19.2 |
contentanalyzer |
contentanalyzer:4.19.2 |
Archive Services |
|
archive |
archiveservice:4.19.2 |
Rendition Services |
|
controller |
controller:4.19.2 |
renditiontextworker |
textextraction-worker-service:2.10.2 |
rendition |
renditionservice:2.10.2 |
rendition-repository |
rendition-repository:2.1.1 |
Structural Services |
|
Rollback Administration |
|
commander* |
commander:4.19.2 |
Infrastructure |
|
elasticsearch |
2023-08-07 |
Test and Example Infrastructure |
|
KEYCLOAK |
keycloak:24.0.2-stable1 |
\* service of special interest for DevOps | ** obsolete when using Kubernetes
10.5.3. Additional Services
Service Name | tag - product v. 2024 Summer |
---|---|
Client Services |
|
API-WEB |
api-web:1.19.2 |
CLIENT |
client:5.5.1 |
ARCHITECT |
architect:2.4.0 |
VIEWERSERVICE |
viewerservice:3.0.10 |
USERSERVICE |
userservice:1.13.2 |
SOTHOOK |
sothook:4.19.0 |
OFFICE365 |
provider-client:2.0.2 |
DASHLET |
dashlet-microservice:2.0.1 |
PROVIDER |
provider:3.0.0 |
HOST |
wopi-host:3.0.0 |
SCHEDULER |
provider-scheduler:3.0.0 |
ADMIN |
provider-admin:3.0.1 |
Tenant Management Services |
|
TENANT-MANAGEMENT |
tenant-management:1.16.3 |
METRICS |
metricsservice:1.4.2 |
KEYCLOAK-PROXY |
keycloak-proxy:24.0.0 |
Business Process Management (BPM) |
|
BPM-ENGINE |
bpm-engine:0.14.2 |
BPM-ADMIN-UI |
bpm-admin:0.9.1 |
AI Integration |
|
PDF-CONVERTER |
kairos/pdf-converter:1.4.1 |
PREDICT-API |
kairos/predict-api:2.1.0 |
KAIROS-API |
kairos/kairos-api:2.1.0 |
SAP Integration |
|
REPOSITORYMANAGER |
repositorymanager:4.3.3 |
REPOSITORYMANAGER-MQ |
repositorymanager-mq:1.2.1 |
REPOSITORYMANAGER-CMIS |
repositorymanager-cmis:5.0.0 |
REPOSITORYMANAGER-ILM |
repositorymanager-ilm:5.0.0 |
Mailarchiving Integration |
|
STORAGE |
mailarchiving-storage:2.1.6 |
SMTP |
mailarchiving-smtp:2.1.6 |
MAILBOX |
mailarchiving-mailbox:2.1.6 |
10.6. Standard Ports and Profiles
10.6.1. Core Services
Name | Function | Configuration Profiles | Standard Ports |
---|---|---|---|
Gateway |
|||
|
API gateway |
|
7450-7459 |
Basic Core Services |
|||
|
user authentication, session management |
|
80 |
|
schema management |
|
7400 |
|
management of the binary storage |
|
7500-7509 |
|
management of object metadata in the relational database |
|
7510-7519 |
|
indexing in Elasticsearch |
|
7291-7300 |
|
processing of queries |
|
7221-7230 |
|
synchronous full-text extraction and determination of the MIME type |
|
7430-7439 |
Archive Services |
|||
deprecated: |
connector for storage solutions |
|
7530-7539 |
Rendition Services |
|||
|
As of 2024 Summer: asynchronous full-text extraction |
|
|
|
generation of renditions of submitted documents |
|
7341 |
Rollback Administration |
|||
|
command tool for rollbacks |
|
7412 |
10.6.2. Additional Services
Name | Function | Configuration Profiles | Standard Ports |
---|---|---|---|
Client Services |
|||
|
web-api gateway, bundling of higher-level functions in one client API, adds more features like custom forms, localization, and object type icons to the system. |
|
7550 |
|
reference client based on core and framework libraries that can be used for custom client development |
|
80 |
|
supports custom form modeling including form scripts, localization of technical names, and user management. |
|
80 |
|
offers client-side viewing capability for certain file types |
|
80 |
|
stores user settings and caches user information |
|
8080 |
|
fills the property |
|
10779 |
Tenant Management |
|||
|
tenant management API with endpoints for maintaining tenants and their users |
|
8080 |
deprecated: `metrics` |
provides tenant specific metrics. The tenant management API offers exposed endpoints of this service. |
- |
8080 |
Business Process Management (BPM) |
|||
|
Flowable-based BPM engine |
|
8080 |
|
admin user interface for the BPM engine |
- |
8080 |
E-Mail Archive (as of 2024 Spring) |
|||
|
Receiving messages from alternate mailboxes. |
|
8110 |
|
SMTP server. |
|
8120 |
|
SMTP server. |
|
8130 |
Auto ML Platform (beta version - not yet included in installations) |
|||
|
- |
- |
- |
ML Training Pipeline |
- |
- |
- |
|
- |
- |
- |
10.7. Changelog and Bugfixes
The following tables contain technical information on processed tasks during the development of product version 2024 Summer.
10.7.1. Changelog
Click to show.
Key | Summary | Description |
---|---|---|
AI-1963 |
Include tax percentage in prediction result |
Predict-API returns only tax amount as part of the response. Even if tax percentage is returned from rule_based model.
|
AI-1972 |
Reverse Charge |
As a user of the invoice compliance check service, I would like to be able to know if the invoice I received falls under the reverse charge regulation to be able to handle it properly Acceptance criteria:
|
AI-2011 |
Include Supply date in Predict API |
Incude Supply date in Predict-API response |
AI-2024 |
Add tax exemption in Predict API response |
As a predict API user, I want to recieve the response of the tax exemption model to be able to provide input to the ICC Acceptance criteria:
|
BUD-2971 |
Tenant Management-API is upgraded to Keycloak 24 |
As a system operator I want to use keycloak in version 24. Acceptance criteria:
|
BUD-3012 |
Tenant Management API supports several profiles |
As a system integrator, I would like to be supported in creating tenants via profiles that are different so that I can save time through automation. The profiles are different e. g. in regards to the e-mail and theming settings. Acceptance criteria:
"themes": { "login": "eca", "account": "yuuvis", "admin": "yuuvis", "email": "eca"} * TM should support several profiles |
BUD-3015 |
Patch method for API-web to add text resources |
As an editor of text resources, I would like to be supported in the ability to add text resources through API-Web. Acceptance criteria:
|
BUD-3054 |
Reserved SQL words should be escaped |
As an administrator I would like to use SQL reserved keywords when creating names in schema etc. without breaking the functionality. Acceptance creteria:
|
ERA-9961 |
It is possible to execute scripts on a running process instance |
As a model developer, I would like to execute scripts in context of a running process instance, to be able to change the state of variables in process, or to test the scripts that I am currently developing. Acceptance criteria:
|
OKTO-5220 |
Consistent use of options for webhooks |
Options are used in many processes (e.g. metadata update). Some are important for webhooks (e.g. "action"), others were originally developed for internal purposes ("preserve_missing_properties", "waitForSearchConsistency"). As a developer, I would like to find a standardised use of the options for all webhooks in order to enable better integration. Acceptance criteria:
|
OKTO-5260 |
Switching the controller for asynchronous text completion to tags |
As a system integrator, I would like to be able to better understand and individualise the post-completion text. To do this, the post-completion text should be converted to tags in order to be able to use the existing query and control options. Acceptance criteria:
|
OKTO-5676 |
Repository encryption |
As a system integrator, I need the option of storing certain data in encrypted form on the storage medium in order to comply with legal requirements. Acceptance criteria:
|
OKTO-5713 |
Partial upload of files for a better upload of large documents |
As an API user, I would like to have the option of uploading large files in packets in order to facilitate uploads in the event of unstable or slow connections. Acceptance criteria:
|
OKTO-5967 |
Direct connection of the google cloud storage to yMomentum |
As a system integrator, I would like to be able to store data in google cloud directly via the repository service, without having to go through Minio or the archive service, in order to achieve a faster and less error-prone connection. Currently, google cloud storage can be connected to yMomentum via Minio as an S3 proxy. In the first case, the Minio proxy, which has been discontinued by the manufacturer, is also required. In the second case, the archive driver writes additional information to the medium that is not required for the simple storage of data. Acceptance criteria:
|
OKTO-6005 |
Support of WebDav HTTP methods in the core |
As a developer, I would like to be able to provide an extension within the system that uses the WebDAV verbs in order to use the authentication methods of the system and not have to implement them myself. Acceptance criteria:
|
OKTO-6017 |
Tables in responses always have columnNames |
As an API user, I would like the column names of the tables to always be returned in order to have standardised access to the data. Current behaviour:
Acceptance criteria:
|
OKTO-6063 |
Direct connection to iCas (iTernity) from Repository |
Currently, when objects are stored via the iTernity driver, they are always stored via the archive service. Additional information is also stored at this point, which is not the case when storing via the repository. As a system integrator, I would like to be able to store data on the iTernity without the additional archive data also being stored. The driver for iTernity should also be transferred to the repository. Acceptance criteria:
|
10.7.2. Bugfixlog
Click to show.
Key | Description | Support Calls |
---|---|---|
AI-1962 |
Fix multiple points parsing exception |
|
AI-1998 |
Model Image build failing with mlflow version 2.3.x |
|
BUD-2969 |
Misleading error message text |
|
BUD-3003 |
PDFs with form fields cause browser-warning when focus is changed |
|
BUD-3004 |
API-web memory issue |
|
BUD-3017 |
Versions for signed documents cannot be displayed |
00066962 |
BUD-3036 |
Missing situation parameter in deleteForm endpoint |
|
BUD-3037 |
Client framework / quick search component issue |
|
BUD-3051 |
Column configuration icon is not displayed in the client when a folder is opened |
00067544 |
BUD-3055 |
If you try to select a user from a filter list which has a scrollbar with the arrow keys it does not scroll to the selected item |
00067785 CIM-5885 |
BUD-3068 |
Search in tables does not work |
|
BUD-3070 |
Question regarding the query of a folder regarding the number of contained folders and documents |
00067516 CIM-5588 |
BUD-3075 |
History tab is not available |
|
BUD-3078 |
Users are not displayed |
|
BUD-3079 |
Backend respondns 422 when opening filters |
|
DB-8290 |
After Hotfix 21, XML instead of JSON is sent to webhooks with dms.request.objects.upsert.storage-before |
|
OKTO-5942 |
Application returns 401 Unauthorized error |
|
OKTO-5945 |
NPE for incorrect configuration in the application-storage.yml for evaluating the repository |
|
OKTO-5961 |
After Spring Boot update: Multipart parser modifies the content of certain PDF documents |
|
OKTO-5973 |
Auth-Svc: OPTIONS requests are not routed |
|
OKTO-5976 |
Auth-Svc: Since the Spring Boot Update, expiry dates are entered in internal JWTs with an accuracy of milliseconds. The services expect values accurate to the second. |
|
OKTO-5978 |
Auth-Svc: Gibt man einen unbekannten Mandant per API-Aufruf mit, dann bekommt man Status 500 |
|
OKTO-5985 |
Error 422 encountered while loading Folders menu |
|
OKTO-5987 |
Hits disappear when using the highlight function |
|
OKTO-5995 |
Search IndexOutOfBoundsException: Index 0 outside the limits for length 0 |
|
OKTO-6009 |
NPE for schema validation with verbose=true |
10.7.3. Hotfixes
2024 Summer
06 - 05 Sep 2024
- Hotfixes for
-
component version date api-gateway
4.19.2
04.09.2024
authentication
4.19.2
04.09.2024
archiveservice
4.19.2
04.09.2024
commander
4.19.2
04.09.2024
index
4.19.2
04.09.2024
registry
4.19.2
04.09.2024
repository
4.19.2
04.09.2024
search
4.19.2
04.09.2024
system
4.19.2
04.09.2024
- Solved tickets
-
ticket number description component support call OKTO-6078
Commander: During post-indexing, the tag: system:ren:text is also set with the status 1
yuuvis MOMENTUM core
05 - 29 Jul 2024
- Hotfixes for
-
component version date tenant-management
1.16.3
26.07.2024
- Solved tickets
-
ticket number description component support call DB-8441
Tenant-management: get tenant data broken
yuuvis Momentum tenant-management
04 - 16 Jul 2024
- Hotfixes for
-
component version date api-web
1.19.2
03.07.2024
- Solved tickets
-
ticket number description component support call DB-8395
Issue with handling emoji characters
yuuvis Momentum api-web
CIM-5351, 00070289
03 - 01 Jul 2024
- Hotfixes for
-
component version date rendition-repository
2.1.1
28.06.2024
renditionservice
2.10.2
28.06.2024
textextraction-worker-service
2.10.2
28.06.2024
- Solved tickets
-
ticket number description component support call DB-8392
Rendition repository cannot updateObjectToHashTable
yuuvis MOMENTUM rendition-plus
02 - 20 Jun 2024
- Hotfixes for
-
component version date provider-admin
3.0.1
12.06.2024
- Solved tickets
-
ticket number description component support call DB-8347
Admin portal can not be accessed
yuuvis MOMENTUM Office 365 service
00069565, CIM-6027
01 - 17 Jun 2024
- Hotfixes for
-
component version date api-web
1.19.1
14.06.2024
client
5.5.1
14.06.2024
- Solved tickets
-
ticket number description component support call DB-8300
can not fetch app specific resource
yuuvis MOMENTUM client, yuuvis MOMENTUM web-api-gateway
10.8. New Features
Here you will find some of the new release’s highlights. Check out the Change Log for further information on all changes.
10.8.1. 2024 Summer
Released on 11 JUN 2024.
Infrastructure
- Identity Provider
-
Support of Keycloak 24
Keycloak 24 is now supported as identity provider.
Breaking ChangePlease note that some services require Keycloak version 24.
Core
- Architecture
-
Continued: Merging Groups of Core Services
As already started with product version 2024 Spring, the performance and scalability is improved by merging individual services. As a next step, all archive drivers provided by the
archive
service are now provided by therepository
service as well. This means, the drivers for iCas and Hitachi Content Platforms are now available as well. Thearchive
service is now obsolete.Furthermore, the
contentanalyzer
service is merged into therepository
service as well.Services up to 2024 Spring Service that provides functions of both as of 2024 Summer -
repository
-
archive
-
contentanalyzer
repository
-
- DMS Objects
-
Text Rendition via Lifecycle
The asynchronous full-text creation is now integrated in the document lifecycle management and controlled by tagging. Thus, it is possible to adjust the processing for custom solutions. Furthermore, the text renditions can now be stored in the rendition repository like PDF and slide renditions.
Breaking ChangeThe
textextractor
andcontroller
services are removed from the core system and replaced by the newrenditiontextworker
service. Find the configuration changes in the Breaking Changes list.Partial Upload of Large Content Files
The import of DMS objects with large binary content files might be very slow and often leads to timeouts. It is now possible to partially upload the binary content. This means that the actual upload of the binary content is separated from the creation of the DMS object. Furthermore, the content is partially uploaded in pieces. Thus, the upload process is split in sub-processes that can be restarted separately in case of a failure.
The process is controlled via a new set of DMS endpoints.
- Webhooks
-
Standardized Set of Options
The DMS objects passing through the individual system hook entry points contain a standardized set of options that contain processing-related information.
Trace ID Header for Webhooks
The requests sent to the available webhooks contain the
X-B3-TraceId
header now.This header is NOT available for the webhooks of type user.info
. - Binary Storage Connection
-
New Archive Driver for Google Cloud
The
repository
service provides a new archive driver that allows connecting google cloud storage. The configuration parameters are specified in theapplication-storage.yml
configuration file.Repository Encryption
The
repository
service can apply an encryption to binary content files before storing them. Thus, storage administrators cannot open and read the stored binary content files. The encryption can be activated in thestorage.repositories
section in theapplication-storage.yml
configuration file.As encryption impairs the performance of your system, only use it when necessary. Especially range requests for sections of very large content files might be slow. The entire content has to be decrypted before the requested range can be retrieved.
Administration Tools
- Tenant Management API
-
Theming and Specialization of Tenant Creation Profiles
To allow for more specific configuration settings, it is now possible to store multiple tenant creation profiles. They are identified by a
name
query parameter that is now available for the following endpoints:Furthermore, the new
themes
parameter section is available in tenant creation profiles.
Client Development
- Web API
-
PATCH Update for Localization Resources
The new endpoint
PATCH /api-web/api/resources/text/{locale}
allows updating the localization of some particular keys in the corresponding localization resource file.
Business Process Management
- BPM Engine
-
Evaluation of Scripts on Process Instances
The new endpoint
POST /bpm-engine/api/processes/{processInstanceId}/evaluate
allows evaluating Javascript or Groovy scripts on a running process instance.
SAP® Integration
- Repositorymanager
-
New configuration handling
After an update of the
repositorymanager
service, the previous configuration stored in thewebapp/cs
directory can be reused now. - ILM Controller
-
New Interface for SAP® ILM
The new
repositorymanager-ilm
service can connect to the SAP® ILM interface.
10.8.2. 2024 Spring
Released on 21 MAR 2024.
Infrastructure
- Identity Provider
-
Subsequently added with 2024 Summer:
Support of Keycloak 24
Keycloak 24 is now supported as identity provider.
Breaking ChangePlease note that some services require Keycloak version 24.
Core
- Architecture
-
Merging Groups of Core Services
To improve scalability and performance, some groups of two or three services are merged into one. The lower number of services reduces the number of cluster-internal calls as well as the minimum resources for smallest yuuvis® Momentum installations. For example, merging the
audit
service into theregistry
service halves the number of database connections.Moreover, most archive drivers provided by the
archive
service are now provided by therepository
service as well. Using the drivers in therepository
service increases the performance especially for very large binary content files and mass imports. It furthermore allows to disable the additional archiving of metadata in the binary storage.The requests to the API and cluster-internal API are NOT affected. The Kubernetes cluster is configured such that all previous individual services' names are still available and requests are redirected to an instance of the new merged service.
Breaking ChangeCustomers who do not use the preconfigured Helm charts for installation/update but directly refer to the individual services' Docker images have to adapt their processes to the new core architecture.
The following services are merged:
Services up to 2023 Winter Merged into Service as of 2024 Spring -
system
-
configservice
-
organization
system
-
audit
-
registry
registry
-
repository
-
archive
repository
(not yet completed, to be continued in version 2024 Summer) -
- Binary Storage Connection
-
New Driver for Hitachi Content Platform Archives
The driver for Hitachi Content Platform as binary storage is updated and renamed.
Breaking Change-
previous driver name:
hcp_s3
-
new driver name:
hcp-s3
Please note the retention options for those storages as well. Retention times cannot be subsequently extended in Hitachi Content Platform archives. If a binary content file is stored with a retention time (either via configured
defaultRetentionInDays
or via object propertysystem:rmExpirationDate
), this time is fixed in the archive metadata during the entire storage time.Subsequently added with 2024 Summer:
Connecting Azure directly to 'repository' service
The two archive drivers for Azure storages are both supported by the
repository
service now. As this connection does not require an additional step viaarchive
service, it reduces the processing time and used resources for content-related requests.The feature is described in the documentation starting with product version 2024 Summer for
azure_blobstore
andazure_objectretention
. -
- DMS Objects
-
Metadata Extraction for E-mails
During the import of e-mails, their file type (EML or MSG) can be determined and specific metadata can be automatically extracted.
Lifecycle Hooks
The lifecycle hooks are a new and easy way to automatically add tags to DMS objects during object creation or update processes. Thus, for tagging automation, it is not anymore required to create a custom service and connect it via webhook.
Separated Permission for Tagging
A
tag
action is now available for configuring permissions in role sets. It allows to configure roles for service accounts that grant editing rights for tags but not for metadata or content. Thus, custom services can control asynchronous processing chains in the document lifecycle.In combination with the
read
permission, thetag
permission allows the usage of the following endpoints:Rendition for 256-bit Encrypted PDF
It is now possible to retrieve renditions for binary content files of 256-bit encrypted PDF format.
Keys within Structured Data Properties
Structured data properties accept JSON values with keys containing capital letters. The keys must now match the regular expression
[a-zA-Z][a-zA-Z0-9]*
similar to the convention for type IDs.Update Metadata and Content
The endpoint
POST /api/dms/objects/{objectId}
supports multipart request bodies to update metadata and content within one request.Breaking ChangeIf your system uses webhooks triggered by update actions, you need to adjust your predicate. Details here. - Search
-
Case-insensitive Metadata Search
It is now possible to specify case-insensitive search conditions on string metadata.
Client Development
- Web API
-
New Endpoint for Updating Task Candidates
The process variables of an existing process instance can be updated via the new endpoint
POST /api-web/api/tasks/{taskId}/candidates
.
Administration Tools
- Tenant Management API
-
Replaced Metrics Endpoints
The core API offers metrics endpoints with the information but improved processing as of 2023 Summer. The METRICS service is no longer used and can be removed from installation. Thus, the following metrics endpoints of the Tenant Management API are deprecated and will not be available anymore in product version 2023 Winter:
-
GET /tenant-management/api/system/tenants/{tenant}/metrics
-
GET /tenant-management/api/admin/metrics
Breaking Changein product version 2023 Winter -
- yuuvis® architect
-
Task Editor History Aspect Area
The new Editor history aspect area within the task details view contains information on user assignments and unassignments, delegations and resolving of the task.
Editing Process Variables
In the Summary aspect area within the process details view, the process variables can be edited (if available) for running processes.
E-Mail Archive
- New
-
New E-mail Archive
A new solution for e-mail archiving is now available. It supports journaling as well as mailbox archiving. Communication is possible via SMTP and/or Graph API.
Business Process Management
- BPM Engine
-
New Endpoints for Candidates Management
The following new endpoints are provided by the BMP Engine:
-
GET /bpm-engine/api/tasks/{taskId}/candidates
- Retrieve candidates -
PUT /bpm-engine/api/tasks/{taskId}/candidates
- Add candidates -
POST /bpm-engine/api/tasks/{taskId}/candidates
- Replace candidates -
DELETE /bpm-engine/api/tasks/{taskId}/candidates
- Delete candidates
New Endpoint for Updating Process Variables
The process variables of an existing process instance can be updated via the new endpoint
PUT /bpm-engine/api/processes/{processInstanceId}/variables
. -
SAP® Integration
- CMIS Interface
-
New CMIS Interface for SAP® connection
The new
repositorymanager-cmis
service can connect to SAP® via CMIS interface.
10.8.3. 2023 Winter
Released on 04 DEC 2023.
Infrastructure
- Identity Provider
-
Subsequently added with 2024 Summer:
Support of Keycloak 24
Keycloak 24 is now supported as identity provider.
Breaking ChangePlease note that some services require Keycloak version 24.
Core
- Core API
-
Batch Update with 'greedy' Parameter
The
greedy
query parameter is now available for the PATCH/api/dms/objects
endpoint. It allows to update as many requested DMS objects as possible even if one or more of them cannot be processed.Breaking ChangeThe response format is changed even ifgreedy
is not assigned to the request URL. This breaking change affects also webhooks that are triggered after a successful update process.Configuration of 'authentication' Service
The
authentication
service is now scalable in the default configuration and always requires theredis
profile.Furthermore, custom services to be accessible via
authentication
service only need to be registered via URL (and permissions if necessary) in theauthorization.accesses
section of theauthentication-prod.yml
configuration file. - Storage
-
Subsequently added with 2024 Summer:
Connecting Azure directly to 'repository' service
The two archive drivers for Azure storages are both supported by the
repository
service now. As this connection does not require an additional step viaarchive
service, it reduces the processing time and used resources for content-related requests.The feature is described in the documentation starting with product version 2024 Summer for
azure_blobstore
andazure_objectretention
.
Client Development
- Web API
-
App Form and Icon Paths
The app-specific forms and icons are managed with a new path structure.
Breaking ChangePlease note the required manual actions described in the breaking changes.Batch Update For DMS Objects
The new endpoint
PATCH /api-web/api/dms/objects
allows to update the metadata of multiple DMS objects with one request.Batch Deletion For DMS Objects
The new endpoint
DELETE /api-web/api/dms/objects
deletes multiple DMS objects with one request.Improved Resources Management supporting Apps
The resource-controller is now responsible for the entire resources management that is available via Web API. Its endpoints allow for app-specific resource management as well. Meanwhile, the
/api-web/api/admin/resources/*
and/api-web/api/system/resources/*
endpoints are deprecated.Reduction of Header Size for Web API
As already introduced for the core services with product version 2023 Autumn, also the Web API supports keeping user roles and other project-specific information in an internal cache instead of transporting them via internal JWT now.
Searching in Table Rows
The search via Web API allows to specify filters to search for query terms appearing in the same table row.
Relaxed Admin Role Filtering
Users with the role
YUUVIS_TEANANT_ADMINISTRATOR
are NOT ANYMORE excluded from result lists in the default configuration.Deletion of Client Resources
The following new endpoints of the Web API allow for the deletion of corresponding client-specific resources:
- Developer Libraries
-
Full-text Search Configuration
The
main.json
allows to configure two parameters to adjust the Web API’s full-text search behavior.
Administration Tools
- Tenant Management API
-
Reduction of Header Size for Tenant Management API
As already introduced for the core services with product version 2023 Autumn, also the Tenant Management API supports keeping user roles and other project-specific information in an internal cache instead of transporting them via internal JWT now.
Properties for the Initial Admin User
During a new tenant creation via
POST /tenant-management/api/system/tenants
endpoint, first name and last name can be passed as further properties to the initial admin user. - yuuvis® architect
-
Form Modeling for Table Properties
The form modeling supports table properties now.
Filters for Tasks
Filters can be applied to the tasks list now.
Permissions Management
The new Permissions Management view of yuuvis® architect provides an administrative graphical user interface for role set creation and modification.
Reassigning Tasks
It is possible to specify a new responsible user for tasks that were unassigned before.
Business Process Management
- BPM Engine
-
Scripting Languages for Modelling
It is now possible to use scripts in Groovy or Javascript languages for modelling.
Reduction of Header Size for BPM Engine
As already introduced for the core services with product version 2023 Autumn, also BPM Engine supports keeping user roles and other project-specific information in an internal cache instead of transporting them via internal JWT now.
Available Query Parameters for Task Lists
The following query parameters are now available for
GET /bpm-engine/api/tasks
allows to specify filters to search for query terms appearing in the same table row.-
nameLikeIgnoreCase
-
businessKeyLike
-
createdBefore
-
createdAfter
-
completedBefore
-
completedAfter
-
isCompleted
-
visibleTo
-
AI Platform
- API for Machine Learning Pipeline
-
New 'kairos-api' Endpoints
The
kairos-api
service for management of the machine learning pipeline offers the following new endpoints:-
Training of Models:
-
POST /kairos-api/api/admin/training
- Start the training of a model. -
GET /kairos-api/api/admin/training/history
- Get all training jobs. -
GET /kairos-api/api/admin/training/history/{jobUuid}
- Get specific training job by UUID. -
POST /kairos-api/api/admin/training/interrupt/{jobUuid}
- Interrupt/Delete training job by the job’s UUID.
-
-
Building and Deploying Docker Images:
-
POST /kairos-api/api/admin/models/deploy
- Deploy model to Kubernetes cluster. -
POST /kairos-api/api/admin/models/health
- Check model availability. -
POST /kairos-api/api/admin/models/undeploy
- Undeploy/Delete model from Kubernetes cluster.
-
-
10.8.4. 2023 Autumn
Released on 22 AUG 2023.
Infrastructure
- Identity Provider
-
Support of Keycloak Version 22
Customers using Keycloak as identity provider for yuuvis® Momentum can now update to Keycloak version 22.
Breaking Change-
The update of Keycloak requires configuration adjustment.
-
The core system does not necessarily need an update of the Keycloak version. In contrast, the following services do not support previous Keycloak versions:
-
tenant-management
-
keycloak-proxy
-
-
- Search Engine
-
Support of Elasticsearch 7.17.x
yuuvis® Momentum supports Elasticsearch version 7.17.x now. A docker image including the required plugins is available.
Core
- Schema
-
Schema Label
A new
label
string field can be specified in aschema XML file
. It can be used to specify a project-specific schema versioning information. - Tenant Separation
-
Support of multiple Elasticsearch Instances
To realize high performance while the workload increases, it is now possible to configure multiple Elasticsearch instances in the
application-es.yml
configuration file. Furthermore, the connection to Elasticsearch can now be secured by username and password.Breaking ChangeThe configuration structure is changed. Even if you continue using only one Elasticsearch instance, you need to adjust yourapplication-es.yml
configuration file.Selection of Repository by Condition
It is now possible to configure a
predicate
for each repository in theapplication-storage.yml
configuration file to realize, e.g., a tenant-specific storage for binary content files. Thus, the used repository can be selected not only for each single content file during the import but also by configured conditions. - Document Lifecycle
-
Audit Entry for Deletion of an Object Version
The deletion of an object version is now documented in the audit trail with a specific audit entry.
- Search
-
Full-text in Search Results
It is possible to display the text rendition for individual DMS objects in result lists if available. The search query term is highlighted. Client applications, e.g., may display a full-text excerpt that contains the search term in result lists of full-text search queries. Thus, the users can better evaluate the relevance of individual search results.
SUM() Function for Search Queries
The new
SUM()
function forsearch queries
allows to retrieve the sum of integer property values in a single result. - Access Management
-
Reduction of Header Size
In order to reduce the header size for requests to the API gateway, it is possible to keep user roles and other project-specific information in an internal cache instead of transporting them via internal JWT. The feature can be activated by setting
authorization.cacheUserAttributes: true
in theauthentication-prod.ym
configuration file.The feature is NOT yet supported by BPM und client development components of yuuvis® Momentum. - Storage
-
Archive Driver for Azure using Object Retention
The new archive driver
azure_objectretention
allows storing binary content files with retention times specified by the metadata of the corresponding DMS objects.Object Lock Configuration for S3 and Azure Archives
For the archive drivers
s3
,ecs-s3
andazure_objectretention
, the retention mode can be configured in theapplication-storage.yml
configuration file. Thus, you can decide to allow the manipulation of objects under retention by an archive administrator or not. - Custom Extensions
-
Extending the Core API
It is possible to add custom endpoints to the API provided via
api
gateway. Theapi
gateway forwards the requests to the configured custom URL including the assigned JWT.It ist NOT possible to overwrite existing endpoints of the
api
gateway.
Client Development
- Web API Gateway
-
Web API Full-text Search on Specified Field
The Web API query language provides a search operator to force the search for the field to be a full-text search, even if it contains wildcards. Thus, these searches are case-insensitive and wildcard-capable.
Administration Tools
- Tenant Management API
-
Replaced Metrics Endpoints
The core API offers metrics endpoints with the information but improved processing as of 2023 Summer. The METRICS service is no longer used and can be removed from installation. Thus, the following metrics endpoints of the Tenant Management API are deprecated and will not be available anymore in product version 2023 Winter:
-
GET /tenant-management/api/system/tenants/{tenant}/metrics
-
GET /tenant-management/api/admin/metrics
Breaking Changein product version 2023 Winter -
- yuuvis® architect
-
New Tasks List View
The Process Management (BPM) part of yuuvis® architect offers a tasks list view in addition to the processes list view for tenant administrators.
Business Process Management (BPM)
- BPM Engine API
-
Options for Task Lists
The endpoint for the retrieval of task lists
GET /bpm-engine/api/tasks
accepts two new query parameters.-
isCompleted
filters running and/or completed tasks. -
visibleTo
allows to display only the tasks that are visible for a specified user.
Furthermore, the task’s metadata contain the ` endTime` property.
-
10.8.5. 2023 Summer
Core
- Schema
-
Extended Schema Validation
The response of the endpoints for update or validation of a schema is extended with an additional changes section. It informs about differences between the current schema and the schema in the request body, and about the consequences for already existing DMS objects.
- Contents and Renditions
-
Slide Renditions for E-Mail formats MSG and EML
It is now possible to retrieve a slide rendition for binary content files of MSG or EML e-mail formats.
Slide Renditions for Image formats PBM and JNG
It is now possible to retrieve a slide rendition for binary content files of PBM and JNG image formats.
Improved Text Extraction from large MS Office Content Files
The text extraction via
contentanalyzer
service is improved, especially for the handling of large binary content files of Microsoft Office file types. The length of extracted full-text is now limited by a configurable parameter. Thus, overloads and downtimes of thecontentanalyzer
service due to huge content files with much text can be avoided.Mime Type Determination for Office 365 File Types
The
contentanalyzer
service can now determine the mime types for the file types of the current Microsoft Office 365 integration. - Document Lifecycle
-
Deletion of Binary Content
A new endpoint allows to remove the binary content of a DMS object. A new version without content is created while the previous content is still assigned to the previous object version.
Parameter 'waitForSearchConsistency' for Deletion Endpoints
The boolean query parameter
waitForSearchConsistency
is now available for the following endpoints:-
DELETE /api/dms/objects/{objectId}
-
DELETE /api/dms/objects
If the parameter is set to
false
, the success response of the corresponding endpoint does not wait for the update of the search index. Thus, the waiting time for the response is far shorter. However, search requests sent immediately after the change request may be processed before the search index is updated and thus may deliver recently deleted objects. -
- Access Management
-
Attribute-based Access Control
In the definition of roles, it is now possible to specify conditions on project-specific user attributes that are provided in a separate section of the internal JWT. The additional user attributes have to be provided via
user.info
webhook.At the same time, the boolean parameters
accountNonExpired
,accountNonLocked
,credentialsNonExpired
and enabled are removed from the JWT as they were unused. - Storage
-
Support of Azure Blob Storage
Azure Blob Storage can be connected via
archive
service. The configuration is specified in theapplication-storage.yml
configuration file. - Database
-
Metrics Endpoints for DMS Object Count
The metrics endpoints
GET /api/system/tenants/{tenant}/metrics/{metric}
andGET /api/admin/metrics/{metric}
can now provide the number of DMS objects within one specific tenant. In addition, the number of folder objects is provided separately. The information might be used for billing purposes as well as for an emptiness check before removing a tenant from the system.Database Connections Optimizations
In the context of resources optimization measures, the number of database connections within the cluster is reduced. The individual services do not use their own database connection pools anymore. Instead, the connections are centralized now. The new default configuration is documented here:
application-dbs.yml
.This feature has been subsequently added to yuuvis® Momentum product versions 2023 Spring and 2022 Winter LTS as well.
Client Development
- Web API
-
Representation of User Attributes
It is possible to configure the representation of user attributes in order to replace IDs by more user-friendly strings like username, first name or last name.
Parameter 'scope' for Search Queries
The
scope
parameter can be used to execute a search request on either metadata only or full-text rendition of content only or on both.
Administration Tools
- Tenant Management API
-
Log-out Process Improvement
The log-out process is improved by a new redirection configuration in
application-oauth2.yml
.
- yuuvis® architect
-
Process Management
It is now possible to delete or refresh process instances via yuuvis® architect.
10.9. Breaking Changes
The following Breaking Changes are incompatible changes we had to deploy into operation, and therefore you—as a yuuvis® user—need to be aware of them and take action accordingly.
10.9.1. 2024 Summer
Infrastructure
- Identity Provider
-
Support of Keycloak 24
Keycloak 24 is now supported as identity provider. The following services require the new version:
-
tenant-management
service -
bpm-engine
service -
keycloak-proxy
service -
architect
service
-
Core
- DMS Objects
-
Text Rendition via Lifecycle
As the full-text indexing is now managed via lifecycle, the following services are obsolete and no longer part of yuuvis® Momentum installations:
-
controller
service -
textextractor
service
Instead, the
renditiontextworker
service is installed. This change requires the following configuration steps:-
Create a cross-tenant service account for the
renditiontextworker
service. -
Configure its credentials via environment variables for the
renditiontextworker
service:-
YUUVIS_TENANT
- The tenant in which the cross-tenant service account is created. -
YUUVIS_USER
- The username of the cross-tenant service account. -
YUUVIS_PASSWORD
- The password of the cross-tenant service account.
-
-
Optional: The values can be protected in a Kubernetes secret.
-
Optional: If you want to store the calculated text renditions in the rendition repository, set the parameter
rendition.store.text: true
in a service-specific YAML configuration file, e.g.renditiontextworker-prod.yml
. -
Adjust the global system hook configuration:
-
Remove the AMQP hook that connects the
lc.textextraction
queue:Previous 'systemhookconfiguration.json'{ "systemhooks": { "amqp": [ ... { "bulkSize": 10, "enable": true, "password": "secret", "predicate": "spel:(contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null && contentStreams[0]['range'].length() > 0) ? true : false", "queue": "lc.textextraction", "type": "object.insert.document", "url": "10.10.6.243:5674", "user": "clouduser" } ... ], "lifecycle": [...], "webhooks": [...] } }
-
Add the following lifecycle hook configuration:
New 'systemhookconfiguration.json'{ "systemhooks": { "amqp": [...], "lifecycle": [ ... { "type" : "dms.request.objects.upsert.database-before", "enable" : true, "predicate" : "spel:contentStreams != null && contentStreams.size() > 0 && contentStreams[0]['range'] != null", "tagname": "system:ren:text", "tagstate": 1 } ... ], "webhooks": [...] } }
-
-
10.9.2. 2024 Spring
Infrastructure
- Identity Provider
-
Subsequently added with 2024 Summer:
Support of Keycloak 24
Keycloak 24 is now supported as identity provider. The following services require the new version:
-
tenant-management
service -
bpm-engine
service -
keycloak-proxy
service -
architect
service
-
Core
- Operations und DMS Objects
-
Update Metadata and Content
The endpoint
POST /api/dms/objects/{objectId}
supports multipart request bodies to update metadata and content within one request. It triggers the creation of an audit entry 302 (OBJECT_METADATA_DOCUMENT_CHANGED). If your system uses webhooks triggered by updates, you need to add the new action code to thepredicate
in the webhook configuration. Webhooks of the following types are affected: *dms.request.objects.upsert.storage-before
*dms.request.objects.upsert.database-before
*dms.response.objects
*dms.response.objects.update
Action: Adjust your
predicate
values as shown in the following example:previous 'predicate'"predicate" : "spel:T(java.util.List).of(300).contains(options['action']) && ...
new 'predicate'"predicate" : "spel:T(java.util.List).of(300,302).contains(options['action']) && ...
- Architecture
-
Merging Groups of Core Services
To improve scalability and performance, some groups of two or three services are merged into one. The lower number of services reduces the number of cluster-internal calls as well as the minimum resources for smallest yuuvis® Momentum installations.
The requests to the API and cluster-internal API are NOT affected. The Kubernetes cluster is configured such that all previous individual services' names are still available and requests are redirected to an instance of the new merged service.
Customers who do not use the preconfigured Helm charts for installation/update but directly refer to the individual services' Docker images have to adapt their processes to the new core architecture.
The following services are merged:
Services up to 2023 Winter Merged into Service as of 2024 Spring -
system
-
configservice
-
organization
system
-
audit
-
registry
registry
-
search
-
index
search
-
repository
-
archive
repository
-
- Binary Storage Connection
-
New Driver for Hitachi Content Platform Archives
The driver for Hitachi Content Platform as binary storage is updated and renamed.
-
previous driver name:
hcp_s3
-
new driver name:
hcp-s3
Please note the retention options for those storages as well. Retention times cannot be subsequently extended in Hitachi Content Platform archives. If a binary content file is stored with a retention time (either via configured
defaultRetentionInDays
or via object propertysystem:rmExpirationDate
), this time is fixed in the archive metadata during the entire storage time. -
Business Process Management
- BPM Engine API
-
New Format for Identity Links
The
identityLinks
section of thePOST /bpm-engine/api/processes/{processInstanceId}/history
endpoint’s JSON response has a new structure.
Administration Tools
- Tenant Management API
-
Replaced Metrics Endpoints
The core API offers metrics endpoints with the information but improved processing as of 2023 Summer. Thus, the metrics endpoints of the Tenant Management API are deprecated already as of product version 2023 Autumn and will be now finally removed.
Action: Use the core API’s metrics endpoints instead.
10.9.3. 2023 Winter
Infrastructure
- Identity Provider
-
Subsequently added with 2024 Summer:
Support of Keycloak 24
Keycloak 24 is now supported as identity provider. The following services require the new version:
-
tenant-management
service -
bpm-engine
service -
keycloak-proxy
service -
architect
service
-
Core
- DMS Endpoints and Webhooks
-
Batch Update with 'greedy' Parameter
The response of the
PATCH /api/dms/objects
is changed due to the introduction of thegreedy
query parameter.HTTP status code 2023 Winter HTTP status codes up to 2023 Autumn -
207 Multi-Status
The response always returns this HTTP status code. However, the JSON response body contains the HTTP status codes for the processing of each individual object. Those sub-requests can be successful or failed.
-
404 Not Found – One object was not found.
-
403 Forbidden – The user has no
write
permission for one object. -
422 Unprocessable Entity – A validation error occurred for one object.
-
200 Ok – All objects are successfully updated.
The new behavior affects webhooks of the following types as well. Their individual entry points are now passed by ALL batch updates (not only purely successful batch updates anymore). The object lists contain the HTTP status codes resulting from the sub-requests mentioned above.
-
Client Development
- Web API
-
App Form and Icon Paths
The paths for app forms and app icons have been changed. Please back up the app forms and app icons before updating the system to 2023 Winter and reimport them after the update is complete.
Business Process Management
- BPM Engine API
-
Rename Available Database Profiles
The
bpm-engine
service requires exactly one database profile. The available profiles are renamed as follows:New profile name as of 2023 Winter Previous profile name dbspostgres
postgres
dbsmssql
mssql
If you do not replace the corresponding profile name in the active profiles for the service, it uses a local database and all workflow-related data are stored only during runtime.
Action: In the
bpm-engine
service’s Kubernetes deployment file, find the active profiles that are listed under theSPRING_PROFILES_ACTIVE
environment variable. Replace the profile name, e.g.,postgres
bydbspostgres
.
10.9.4. 2023 Autumn
Infrastructure
- Identity Provider
-
Support of Keycloak Version 22
Keycloak version 22 requires the
scope
configuration parameter. It has to be configured in theapplication-oauth2.yml
configuration file.The
infrastructure
Helm chart for yuuvis® Momentum 2023 Autumn contains Keycloak version 22.The update to the Keycloak 22 is optional for the core system, but MANDATORY for tenant-management
service andkeycloak-proxy
service.
Core
- Search Engine Connection
-
Support of multiple Elasticsearch Instances
To realize high performance while the workload increases, it is now possible to configure multiple Elasticsearch instances. Furthermore, the connection to Elasticsearch can now be secured by username and password.
Action: To continue using the same Elasticsearch instance for all tenants, replace the
spring.data.elasticsearch
parameters as shown in the example below in yourapplication-es.yml
configuration in the Git root directory.-
The
spring.datasource
parameters used up to product version 2023 Summer:spring.data.elasticsearch.cluster-name: 'my-es-cluster' spring.data.elasticsearch.cluster-nodes: '12.23.5.678:9012' spring.data.elasticsearch.repositories.enabled: true
-
The new configuration structure used as of product version 2023 Autumn:
storage: searchdatabases: database1: datasource: dbsource1 predicate: 'spel:true' default: true searchdatasources: dbsource1: urls: '12.23.5.678:9012' index: 'exampleindex'
To use different Elasticsearch instances for individual tenants, please read the documentation of the
application-es.yml
configuration file. -
Client Development
- User Profile API
-
Rename Available Database Profiles
The
userservice
requires exactly one database profile. The available profiles are renamed as follows:New profile name as of 2023 Autumn Previous profile name dbspostgres
postgres
dbsmssql
mssql
dbscockroach
cockroach
If you do not replace it in the active profiles for the service, it uses a local database and all
userservice
-related data are stored only during runtime.Action: In the
userservice
's Kubernetes deployment file, find the active profiles that are listed under theSPRING_PROFILES_ACTIVE
environment variable. Replace the profile name, e.g.,postgres
bydbspostgres
.
10.9.5. 2023 Spring
Core
- Metrics
-
New Metrics Endpoints
The
audit
service requires a Redis connection now. If you use the Helm charts for your version update, your configuration is automatically adjusted and thus you do not need the following action.
Action: Restart theaudit
service with theredis
profile. - DMS Endpoints
-
Batch Deletion with 'greedy' Parameter
The
DELETE /api/dms/objects
endpoint’s response is different even in the default request withgreedy=false
.New behavior Previous behavior The HTTP status code is always 207 in case of a proper request now.
Distinction between defined HTTP status codes 200, 403, 404, 409.
The response body contains the DMS objects (completed as far as possible) that were referenced by objectId in the request body. The options section contains the
system:deletionResult
that specifies success or failure of the individual objects' deletion.No response body in case of successful deletion of all referenced objects. Error in JSON format as soon as one object could not be deleted.
The entry points for the webhooks
dms.request.objects.delete
,dms.response.objects
anddms.response.objects.delete
are reached with the complete objects list even if some referenced objects cannot be deleted.The entry points for the
dms.request.objects.delete
,dms.response.objects
anddms.response.objects.delete
are NOT reached as soon as at least one referenced object cannot be deleted.
Client Development
- Web API
-
New idm-controller
The following endpoints were moved from the user-controller to the new idm-controller. They are scheduled to be permanently removed with the next product version.
Endpoint in user-controller up to 2022 Winter Endpoint in idm-controller as of 2023 Spring GET /api-web/api/users/users
GET /api-web/api/idm/users
GET /api-web/api/users/{userId}
GET /api-web/api/idm/users/{userId}
GET /api-web/api/users/whoami
GET /api-web/api/idm/whoami
Action:
Update the access configuration for the individual endpoints of the Web-API gateway in the
authentication-prod.yml
configuration file. The example code block shows the new default configuration for new installations.### api-web - endpoints: /api-web/swagger-ui.html,/api-web/swagger-ui/**,/api-web/**/v3/api-docs/** - endpoints: /api-web/api/system/** access: hasAuthority('YUUVIS_SYSTEM_INTEGRATOR') - endpoints: /api-web/api/admin/** access: hasAuthority('YUUVIS_TENANT_ADMIN') - endpoints: /api-web/api/dms/**,/api-web/api/bpm/**,/api-web/api/resources/**,/api-web/api/users/**,/api-web/api/idm/**
Business Process Management (BPM)
- BPM Engine API
-
Filtering of Task Lists
The
GET /bpm-engine/api/tasks
endpoint for the retrieval of a task list now accepts the boolean query parameterisAssigned
instead offilter
.Action: Adjust your requests considering following behavior:
-
If
isAssigned=true
, the endpoint retrieves only tasks that are assigned to the currently logged-in user. -
If
isAssigend=false
, the endpoint retrieves only tasks without an assignee for which the currently logged-in user is a candidate user. -
If
isAssigned
is not specified in the request URL, the endpoint retrieves tasks that are assigned to the currently logged-in user as well as tasks without an assignee for which the currently logged-in user is a candidate user.
-
10.9.6. 2022 Winter (LTS)
Infrastructure
- Identity Provider
-
Support of Keycloak Version 19
To use Keycloak version 19, it is required to manually adjust the endSessionUri parameter for each tenant in the application-oauth2.yml configuration file.
Action: In each tenant configuration, remove the redirect URI from the URL as shown below for the testyuuvis example tenant.up to Keycloak version 15:endSessionUri: http://${keycloak.host}/auth/realms/testyuuvis/protocol/openid-connect/logout?redirect_uri=${redir}
for Keyclaoak version 19:endSessionUri: http://${keycloak.host}/auth/realms/testyuuvis/protocol/openid-connect/logout
Core
- Database Connection
-
Tenant-specific Database Configuration
It is now possible to configure different databases to be used for storing metadata of individual tenants. Configurations for previous product versions are not supported anymore. The spring.datasource parameters in the application-dbs.yml configuration file are ignored.
Action: If you use the TENANT-MANAGEMENT service in your installation, apply the breaking change for the METRICS service configuration first. Afterwards, apply the new configuration to the core services as described here. To continue using the same database for all tenants, replace the spring.datasource parameters as shown in the example below in your application-dbs.yml configuration in the Git root directory.
The spring.datasource parameters used up to product version 2022 Autumn:spring.datasource.url: jdbc:postgresql://abc/def spring.datasource.username: yuuvis spring.datasource.password: changeme123 spring.datasource.driver-class-name: org.postgresql.Driver
The new configuration structure used as of product version 2022 Winter:storage: databases: defaultdb: datasource: defaultds predicate: 'spel:false' default: true datasources: defaultds: url: 'jdbc:postgresql://abc/def' username: yuuvis password: changeme123 driver-class-name: 'org.postgresql.Driver'
To use different databases for individual tenants, please read the documentation of the application-dbs.yml configuration file.
Administration Tools
- Tenant Management API
-
METRICS service database
As the METRICS service still uses only one database for the data of all tenants, it uses an own configuration file with its own database connection parameters now.
Actions:-
Create a copy of the previoulsy used application-dbs.yml configuration file and save it as application-dbstmp.yml configuration file. The file should now contain the spring.datasource parameters as shown in the following example.
spring.datasource.url: jdbc:postgresql://abc/def spring.datasource.username: yuuvis spring.datasource.password: changeme123 spring.datasource.driver-class-name: org.postgresql.Driver
-
In the METRICS service deployment, replace the dbs profile by the dbstmp profile.
-
Continue with the database reconfiguration of the core services.
-
Client Development
- Developer Libraries
-
Task Properties in Inbox
The inbox provided by the @yuuvis/core library uses the briefRepresentation parameter of the Web-API gateway bpm-controller endpoints as described below. Thus, the retrieved tasks are presented with a reduced data set to the users of a client application.
Action: If you want to display the full property set of tasks, set disableBriefRepresentation for the inbox service.
- Web API
-
bpm-controller Endpoints
The optional query parameter briefRepresentation is available for the task retrieval endpoints. Per default, the response will contain only a reduced data set in order to reduce the processing time.
Action: In order to keep the behavior of the previous versions, set the query parameter briefRepresentation=false for each request to the corresponding endpoint.
10.9.7. 2022 Autumn
Client Development
- Developer Libraries
-
Angular Version Update
The client libraries use Angular 14 now. In case you extended your client with further (third party) libraries, please ensure that they are compatible with Angular 14.
Action: If necessary, update your external libraries to a version that supports Angular 14.Subsequently added with 2022 Winter:
Task Properties in Inbox
The inbox provided by the @yuuvis/core library uses the briefRepresentation parameter of the Web-API gateway bpm-controller endpoints as described below. Thus, the retrieved tasks are presented with a reduced data set to the users of a client application.
Action: If you want to display the full property set of tasks, set disableBriefRepresentation for the inbox service. - Web API
-
Subsequently added with 2022 Winter:
bpm-controller Endpoints
The optional query parameter briefRepresentation is available for the task retrieval endpoints. Per default, the response will contain only a reduced data set in order to reduce the processing time.
Action: In order to keep the behavior of the previous versions, set the query parameter briefRepresentation=false for each request to the corresponding endpoint.
Administration Tools
- Tenant Management API
-
idm-controller Endpoints
The optional query parameter
briefRepresentation
is available for the endpointGET /tenant-management/api/idm/users
. Per default, the response will contain only a reduced data set in order to reduce the processing time. Especially, roles and groups of the listed users are not included in the default response anymore.
Action: In order to keep the behavior of the previous versions, set the query parameterbriefRepresentation=false
for each request to the endpoint.
10.9.8. 2022 Summer
Core
- Access Management
-
Validation of Internal JSON Web Tokens
The internal endpoint of the
authentication
service for the validation of internal JSON Web Tokens (JWTs) is now available via a different URL.
>>GET /jwt/verify
Action: Custom microservices that called the endpoint/authentication/jwt/verify
have to use the URLhttp://authentication-internal/jwt/verify
instead.
10.9.9. 2022 Spring
Core
- Git Connection
-
Performance Optimization for
configservice
Local and remote resources on the git server are synchronized now at regular intervals of 5 minutes. Thus, changes applied directly to the remote resources on the git server are NOT available until the regular synchronization process is passed. The resources are always cached. The availability of the git server is not checked anymore in case of resource retrieval requests. It is no longer possible to set the parameter
fail-if-git-not-available=true
.Furthermore, the Helm charts create a persistent volume claim for each
configservice
instance that will be used for service initialization after a service restart.In case multiple instances of the
configservice
are running, the synchronization of the individual local resources is done at regular intervals of 5 minutes as well. Thus, requests for resources that have been modified less than 5 minutes ago might lead to the retrieval of a deprecated version of those resources. Resources created less than 5 minutes ago might be not available.
Client Development
- Developer Libraries
-
Object Creation Permissions
The permission to create new objects is now enabled via a create permission within one of the roles defined via a role set. The
YUUVIS_CREATE_OBJECT
role does no longer allow object creation. You need to adjust your corresponding role set accordingly.Action: Update your roles as described here. Use the following condition:
<condition>system:objectTypeId = 'appClient:minidoc' AND system.secondaryjectTypeIds = 'appClient:minidoc'</condition>
- Web API
-
New Swagger UI Version for Web-API Gateway
The new Swagger version is available under a new URL.
Action: Adjust the endpoint URL pattern in authentication-prod.yml configuration file has follows:... ### api-web - endpoints: /api-web/swagger-ui.html,/api-web/swagger-ui/**,/api-web/**/v3/api-docs/** ... ...
- User Profile API
-
Migration of User Information Endpoints.
The user information endpoints
GET /userservice/api/users
andGET /userservice/api/users/{userId}
are not available anymore.
Action: Use the endpointsGET /api-web/api/users/users
andGET /api-web/api/users/{userId}
instead.
Administration Tools
- Tenant Management API
-
New Swagger UI Version
The new Swagger version is available under a new URL.
Action: Adjust the endpoint URL pattern in authentication-prod.yml configuration file has follows:... ### tenant-management - endpoints: /tenant-management/swagger-ui.html,/tenant-management/swagger-ui/**,/tenant-management/**/v3/api-docs/** ... ...
10.9.10. 2021 Winter
Core
- Git Connection
-
Subsequently added with 2022 Spring:
Performance Optimization for
configservice
Local and remote resources on the git server are synchronized now at regular intervals of 5 minutes. Thus, changes applied directly to the remote resources on the git server are NOT available until the regular synchronization process is passed. The resources are always cached. The availability of the git server is not checked anymore in case of resource retrieval requests. It is no longer possible to set the parameter
fail-if-git-not-available=true
.Furthermore, the Helm charts create a persistent volume claim for each
configservice
instance that will be used for service initialization after a service restart.In case multiple instances of the
configservice
are running, the synchronization of the individual local resources is done at regular intervals of 5 minutes as well. Thus, requests for resources that have been modified less than 5 minutes ago might lead to the retrieval of a deprecated version of those resources. Resources created less than 5 minutes ago might be not available.
Client Development
- Developer Libraries
-
BPM Integration in Clients
In order to provide the new features in client applications, the BPM process model
follow-up
has been updated. Process instances based on the previous version of thefollow-up
process model are not anymore supported. They are displayed without subject and attachments.Action: You can delete those process instances via the client application or via the corresponding Web-API Gateway endpoint.
Management of Configuration Files
-
In order to unify the management of standard configurations, the standard column and filter configurations are now managed via the Web-API Gateway and no longer via the USERSERVICE.
-
All client-specific configuration files like main, plug-in or language configuration are managed via the Web-API Gateway as well.
Action: If standard column or filter configurations are already stored in your system via the USERSERVICE, they need to be imported again via the corresponding Web-API Gateway endpoint.
-
10.9.11. 2021 Autumn
Core
- Access Management
-
Token Handling for Custom Services
The internal tokens (JWT) created by the
authentication
Service are now signed.Actions:
-
If you are working with Java custom services using the annotation
com.os.services.core.security.EnableServiceSecurity
from the libraryservices-security
, you need to update the library to version 5.7.0. -
If you are working with Java custom services using the library
com.nimbusds:nimbus-jose-jwt
for parsing of incoming JWTs, you have to use the classcom.nimbusds.jwt.SignedJWT
instead of the classcom.nimbusds.jwt.PlainJWT
.
Object Creation Permissions
In role sets, permissions can now be set for the creation of objects by introducing the action create. So far, the object creation was enabled together with the edit permission via the action write. Additionally, the role YUUVIS_CREATE_OBJECT had to be assigned to users in order to enable object creation via API Gateway. As of now, this role does not affect the functionality of the API Gateway and is not part of the global default role set anymore.
Actions:
-
In each of your existing role sets, add
<action>create</action>
to each permission including awrite
action that should allow for object creation further on. If the permission includes a condition, ensure that noCONTAINS
statement is involved. Use the endpoints for managing permissions. -
Remove the following lines from section
# API-endpoints
inauthorization.accesses
in the configuration fileauthentication-prod.yml
:- endpoints: /api/dms/objects method: POST access: hasAuthority('YUUVIS_CREATE_OBJECT')
-
Administration Tools
- Tenant Management API
-
Assignment of the System Integrator Role
In previous versions, the endpoint
POST /tenant-management/api/admin/users
that is accessible with the roleYUUVIS_TENANT_ADMIN
allowed for the assignment of the roleYUUVIS_SYSTEM_INTEGRATOR
to other users. This is not possible anymore. Only the endpointPOST /tenant-management/api/system/tenants/{tenant}/users
that is accessible with the roleYUUVIS_SYSTEM_INTEGRATOR
allows for the assignment of the roleYUUVIS_SYSTEM_INTEGRATOR
to other users.
Client Development
- Developer Libraries
-
No Printing via 'ContentPreviewComponent'
The
ContentPreviewComponent
provided by the framework library does not allow for printing anymore. Users have to download the binary content files and print them from their local drives.
10.9.12. 2021 Summer
Client Development
- Web API
-
URLs
The endpoint URLs have been changed to match the structure of other service-specific endpoint URLs. The new URLs are used by yuuvis® client as reference implementation and yuuvis® architect.
The endpoints are grouped consistent with the Web-API Gateway Swagger-UI. The changes are highlighted in bold letters in the new URL.
Action: If you are already referencing one of the following endpoints in your applications, please update the corresponding URLs.
HTTP Method Deprecated URL New URL admin-controller
GET
/api-web/admin/resources/text
/api-web/api/admin/resources/text
POST
/api-web/admin/resources/text/{locale}
/api-web/api/admin/resources/text/{locale}
GET
/api-web/admin/resources/icon/{path}
/api-web/api/admin/resources/icons/{path}
POST
/api-web/admin/icon/{path}
/api-web/api/ admin/resources/icons/{path}
GET
/api-web/admin/resources/config
/api-web/api/admin/resources/config
POST
/api-web/admin/resources/config
/api-web/api/admin/resources/config
GET
/api-web/admin/form/{objecttype}
/api-web/api/admin/dms/forms/{objecttype}
POST
/api-web/admin/form/{objecttype}
/api-web/api/admin/dms/forms/{objecttype}
GET
/api-web/admin/form/{objecttype}
/api-web/api/admin/dms/forms/{objecttype}
GET
/api-web/admin/catalogs/{name}
/api-web/api/admin/dms/catalogs/{qname}
POST
/api-web/admin/catalogs/{name}
/api-web/api/admin/dms/catalogs/{qname}
bpm-controller
GET
/api-web/bpm/process/instances
/api-web/api/bpm/process/instances
POST
/api-web/bpm/process/instances
/api-web/api/bpm/process/instances
DELETE
/api-web/bpm/process/instances/{processInstanceId}
/api-web/api/bpm/process/instances/{processInstanceId}
GET
/api-web/bpm/process/instances
/api-web/api/bpm/process/instances
GET
/api-web/bpm/tasks
/api-web/api/bpm/tasks
POST
/api-web/bpm/tasks/{taskId}
/api-web/api/bpm/tasks/{taskId}
dms-controller
POST
/api-web/dms/search
/api-web/api/dms/objects/search
GET
/api-web/dms/{id}
/api-web/api/dms/objects/{id}
GET
/api-web/dms/{id}/versions/{version}
/api-web/api/dms/objects/{id}/versions/{version}
GET
/api-web/dms/{id}/versions
/api-web/api/dms/objects/{id}/versions
GET
/api-web/dms/{id}/content
/api-web/api/dms/objects/{id}/contents/file
GET
/api-web/dms/{id}/content
/api-web/api/dms/objects/{id}/contents/file
POST
/api-web/dms/update/{id}/content
/api-web/api/dms/objects/{id}/contents/file
POST
/api-web/dms/create
/api-web/api/dms/objects
PATCH
/api-web/dms/update/{id}
/api-web/api/dms/objects/{id}
DELETE
/api-web/dms/delete/{id}
/api-web/api/dms/objects/{id}
GET
/api-web/dms/form/{objecttype}
/api-web/api/dms/forms/{objecttype}
GET
/api-web/dms/catalogs/{qname}
/api-web/api/dms/catalogs/{qname}
POST
/api-web/dms/catalogs/{qname}
/api-web/api/dms/catalogs/{qname}
PATCH
/api-web/dms/catalogs/{qname}
/api-web api/dms/catalogs/{qname}
GET
/api-web/dms/catalogs/{qname}/validate
/api-web/api/dms/catalogs/{qname}/validate
resource-controller
GET
/api-web/resources/text
/api-web/api/resources/text
GET
/api-web/resources/icon/{path}
/api-web/api/resources/icons/{path}
GET
/api-web/resources/config
/api-web/api/resources/config
system-controller
GET
`/api-web/system/resources/text
/api-web/api/system/resources/text
POST
/api-web/system/resources/text/{locale}
/api-web/api/system/resources/text/{locale}
GET
/api-web/system/resources/icon/{path}
/api-web/api/system/resources/icons/{path}
POST
/api-web/system/icon/{path}
/api-web/api/system/resources/icons/{path}
GET
/api-web/system/resources/config
/api-web/api/system/resources/config
POST
/api-web/system/resources/config
/api-web/api/system/resources/config
GET
/api-web/system/form/{objecttype}
/api-web/api/system/dms/forms/{objecttype}
POST
/api-web/system/form/{objecttype}
/api-web/api/system/dms/forms/{objecttype}
GET
/api-web/system/form/{objecttype}
/api-web/api/system/dms/forms/{objecttype}
GET
/api-web/system/catalogs/{name}
/api-web/api/system/dms/catalogs/{qname}
POST
/api-web/system/catalogs/{name}
/api-web/api/system/dms/catalogs/{qname}
user-controller
GET, POST
/api-web/users*
/api-web/api/users*
Appendix A: FAQ
Find here answers to frequently asked questions (FAQ) on yuuvis® Momentum.
A.1. DMS Schemata
- Is it possible to change the object type of an already existing object?
-
No, it is not. The object type has to be specified in the object creation request by the
system:objectTypeId
property and cannot be modified later on. However, the concept of secondary object types (SOTs) might satisfy your needs. Those object types cannot be used to instantiate any object, but to assign or remove additional properties at runtime. Thus, it is possible to specify a generic object type with only few properties during the object creation and assign a characterizing SOT by a metadata update at any time. In case you want to build a client application based on our developer libraries, such characterizing SOTs have to be defined as primary SOTs.
A.2. Search
- Why are some objects displayed on the first and second result page?
-
The request for the second result page in yuuvis® Momentum internally requests a new search with the same query condition. From the new result list, the second page is calculated and provided to you. If, e.g., some objects matching the query condition are created after you retrieved the first and before you retrieved the second page, some objects from the first page might now appear later in the total result list. Thus, they reappear on the second result page.
A.3. Troubleshooting
- Why is the database locked sometimes after a service startup?
-
During the startup of services with database access, Liquibase locks the data tables by writing a specific entry in the
DATABASECHANGELOGLOCK
table. If the startup is cancelled for any reason, this entry might remain. In this case the services with a database connection (e.g.audit
,registry
andrendition-repository
services) fail to start and will repeatedly log warnings containing waiting for changelog lock.Example log:
INFO [audit,,] 8 --- [ main] liquibase.lockservice : Waiting for changelog lock....
The database has to be unlocked as described in the Liquibase documentation.
- What can I do if updating/deleting an object takes longer than its locking time?
-
The
api
gateway,registry
service orrepository
lock the affected DMS objects during the processing time of the following requests:-
update of metadata or content
-
moving content
-
object creation with reference to a binary content file that is already stored in yuuvis® Momentum
-
object deletion
-
creation, update or deletion of tags.
Thus, multiple parallel manipulations on the same object or content are prevented. However, the locking time for each process is limited to 600 s in the default configuration. If some update or deletion processes exceed this time, you have the possibility to configure a higher value by specifying the
lock.leasetime
parameter for the above mentioned services.We strongly recommend to look for the origin of the slow processing instead of increasing the locking time. In most cases, your issues indicate a problem with your search index, your database or a binary storage (e.g., one of them might be almost full). Especially for productive systems, it is important to fix the actual problem. -
- Why is the header size of my cluster-internal requests too large?
-
The calls within the yuuvis® Momentum cluster can have multiple headers assigned to themselves. The sum of them is limited to a maximum total header size of 8 KB. If your header size exceeds this limit, try the following steps:
-
Find the origin of the large amount of data in your headers and reduce it as much as you can. In most cases, the internal json web token (JWT) is unnecessarily large and can be reduced.
-
Optimize your role set such that users only need a few roles to get all their required permissions.
-
Use short role names.
-
If you use the
abac
section in your JWT, keep the content as small as possible as well.
-
-
If you cannot further reduce your header size and still exceed the limit, cache the user attributes. The most critical JWT sections are outsourced and thus the header size is reduced.
-
Only as a last resort, increase the maximum header size. Set
server.max-http-request-header-size
for all services within your cluster to your desired value.The larger your headers, the slower is the processing of all requests within your cluster. Make a serious attempt to reduce the header size below the default limit of 8 KB using the means described above before increasing the maximum header size.
-
Appendix B: Glossary
- AMQP Hook
-
Special system hooks used to generate messages for messaging systems using Advanced Message Queuing Protocol 1.0 (AMQP) as encoding scheme. The generation of messages is triggered by specific operations under configured conditions.
- Audit configuration
-
The configuration possibilities for the
audit
service. - Audit service
-
The service of yuuvis® Momentum core that is responsible for audit trail and metrics management.
- Audit trail
-
A documentation of the actions that have been applied to a specific DMS object. The values are stored in a separate database table.
- Compound document
-
DMS objects with binary content consisting of concatenated byte arrays. Sub-documents can be created that reference a specified range within the compound document’s content instead of importing the actual data again.
- Content digest
-
A property of each binary content stored in the content stream properties section of the DMS object(s) to which the content is assigned. The hex-encoded value is calculated by the
repository
service during the import or update of binary content files via Secure Hash Algorithm (SHA256). Thus, it can be used, e.g., to compare content files of different DMS objects or versions. - Document
-
A DMS object instantiated of a document object type. It consists of metadata and, if configured in the object type definition, it can contain a binary content file.
- Document object type
-
Defined object type with base type
system:document
. - Endpoint
-
An URL to request a specific operation via yuuvis® Momentum REST API.
- Folder
-
A DMS object instantiated of a folder object type. It consists of metadata and CANNOT have a binary content file assigned to itself.
- Folder object type
-
Defined object type with base type
system:folder
. - History
-
-
In the context of DMS objects: see audit trail.
-
In the context of workflow / business process management: The process instance history gives an overview of all comments and tasks contained in the process instance and their current processing state.
-
- Interceptor
-
The interceptors allow for project-specific extensions of the yuuvis® Momentum standard process flows by redirection to an alternative processing flow. The alternative process can entirely replace the standard one from this position on or resume the standard process at a specified position.
- Metadata
-
Information stored in a JSON structure as defined in a schema that identifies and characterizes a DMS object in yuuvis® Momentum and makes it queryable. A fixed set of pre-defined system properties is assigned to all DMS objects. Further properties can be assigned if valid with respect to the applied tenant schema.
- Multipart body
-
For transferring data of several types (e.g. a binary file along with a JSON object) in a single request you typically use multipart body. This type of request combines one or more sets of data, separated by boundaries, into a single body.
- Object
-
-
DMS object: An instance of a defined document or folder object type.
-
In the context of workflow / business process management via BPM Engine API or Web API:
-
A task or process definition containing pre-defined Flowable parameters.
-
A task or process instantiated from a task or process definition containing values for the configured properties.
-
-
- Object type
-
The identification of a specific XML (or JSON) structure that defines which properties are available/required for DMS object instances in a specific business use case.
- Rendition
-
An alternative representation (plain text, PDF or thumbnail) of a binary content file to be used, e.g., for full-text search or content preview.
- Retention
-
A protection of the binary content file from being modified or deleted before a specified expiration date is reached.
- Schema
-
The schema is the data model defining the object types and property types. Any DMS object’s metadata validation is based on the schema.
- Secondary object type
-
An abstract object type that cannot be directly instantiated during the creation of DMS objects. It is used as reusable group of properties defined in a schema that belong together in business situations. For example, properties related to e-mail management could be sender and receiver. Those property groups can be referenced in multiple object type definitions.
- System hook
-
A custom extension of the yuuvis® Momentum core functionality. At specific entry points of some processing flows, messages can be generated (AMQP hooks) or the current data can be sent to a custom service (webhooks). After the custom extension, the standard process flow is resumed.
- Tag
-
A tag describes the status of an object within a process chain independently of the object’s metadata. Thus, the usage of tags needs no definition in the schema and does not trigger the creation of new DMS object versions.
- Tenant
-
An isolated part within the yuuvis® Momentum system with the possibility to configure an own schema, role set and further configurations. Each yuuvis® Momentum user belongs to exactly one tenant. Each DMS object is stored for exactly one tenant as well. Users have access only to the DMS objects within their own tenant.
- Webhook
-
System hooks that extend the standard processing flow by an HTTP call if a configured condition is matched.
Feedback Contact and Impressum
We hope this growing portal serves you well and invite you to submit requests or suggestions to us.