Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 42 Next »

Released: Q3 2024

Reisalpe von S.jpg

Highlights Portrait - 7.0.0

Security Improvements Notice

At Portrait, we take application security extremely seriously, which is why we continuously enhance the security features of our platform. We strive to strike a balance between automated configuration options and strict input validation, ensuring that our users can build flexible and dynamic web applications with confidence.

Please note that Portrait is designed to empower admins to create custom web applications. While we prioritize robust security, we also recognize the importance of flexibility and ease of use in our platform. As such, you may need to perform manual configuration or make informed decisions about trade-offs between security and functionality.

As an admin using Portrait to build your application, it's essential that you consider your own application's security needs and take responsibility for ensuring its security. With our latest update, we're introducing new configuration options that enable admins like you to further strengthen their application's security by adding custom input validation, permissions, conditions, and limiting form submissions to specific entries. These enhancements empower you to build applications that meet your unique needs while maintaining a high level of security.

Permissions

Sections can now be configured to be only accessible for admins.

- name: src-inventory
  role: ADMIN
  caption: Inventory

role String

ADMIN = only admins can see this section

USER = every user can see this data

If you don’t define it, role USER will be applied

Admin only sections will be displayed in the administration view.

Screenshot 2024-08-26 at 10.58.33.png

Actions 2.0

The Action inside a Section has been reworked and now support

Screenshot 2024-08-26 at 11.08.16.png

Example:

- name: vacations
  group: Demo
  caption: Vacations
  type: list
  description: |
    Übersicht der Urlaube
  formId: create_vacation
  icon: 'edit'
  actions:
    - label: 'Edit vacation' # Handlebar
      key: 'edit_vacation'
      type: 'FORM' # [LINK, FORM ]
      condition:
        - expression: "{{eq VACATION_EMAIL PORTRAIT_USER_EMAIL}}"
      forwardFields:
        - key
        - VACATION_EMAIL
        - VACATION_DATE
        - VACATION_STATUS

So all Entries of src-inventory have the same configured actions available. However not all actions are displayed equally. For example inventory items that are not in stock (amount <= 0) the link is not displayed. In addition, the value of the link is also different for each inventory item

Actions for triggering Forms

Screenshot 2024-08-26 at 11.12.36.png

I am logged in as user linda.jackson and therfore are only allowed to open the edit vacation form assigned to this user.

Example

actions:
  - label: 'Edit vacation' # Handlebar
    key: 'action1'
    value: 'create_vacation'
    type: 'FORM' # [LINK, FORM ]
    condition:
      - expression: "{{eq VACATION_EMAIL PORTRAIT_USER_EMAIL}}"
    forwardFields:
      - key
      - VACATION_EMAIL
      - VACATION_DATE
      - VACATION_STATUS

Details, see: Actions

Forms

Permissions

Forms can now be configured to be only accessible for admins.

- id: createInventoryItem
  role: ADMIN
  onSubmit:
    type: ELO
    ...
  dialog: config/forms/createInventoryItem.json

role String

ADMIN = only admins can see this section

USER = every user can see this data

If you don’t define it, role USER will be applied

Field Processor

Field Processors support has been extended and is now available for

  • ELO

  • Python

  • SQL

They work similar to the Field Processors in ELO.

Python

The evaluated Field processors are passed alongside the form fields to the python script via the --args flag.

SQL

The evaluated Field processors are available as variables for the SQL query.

Forms based on existing Entries - Mode and Scope

It is now possible to link Forms to existing Entries. This allows Portrait Administrators to further increase their application security and data consistency. To achieve this goal we introduced multiple configuration options:

Mode Update (new for SQL and Python)

SubmitType

ELO

SQL

Python

BLP 5.1

Supported

(tick)

(tick)

(tick)

(error)

With the Mode Update you can get the ‘previous’ attributes from an entry available as variables to be used for Field Processors, SQL Query or further processing in your Python script.

The attributes are prefixed with ORIGIN_ (STATUS → ORIGIN_STATUS)

In addition a security check is applied:

  • If no entry is found for the configured section and key

Python/SQL

Two configs are required:

- id: edit_entry
  onSubmit:
    mode: UPDATE
    source: sectionID

ELO

Three configs are required:

- id: edit_entry
  onSubmit:
    mode: UPDATE
    source: sectionID
    scope: STRICT

Scope (Strict / Loose)

SubmitType

ELO

SQL

Python

BLP 5.1

Supported

(tick)

(error)

(error)

(error)

A Parameter scope has been added to the onSubmitconfiguration element.
This can either be STRICT or LOOSE

- id: create_vacation
  onSubmit:
    type: ELO
    ...
    source: vacations
    scope: STRICT

STRICT:

The STRICT Scope is meant to protect your ELO Instance from being manipulated in ways that you did not configured in the first place: Like editing unrelated Sords which are not indexed. Therefore it is highly recommended to apply this configuration.

Please set all ELO Mask Attributes explicitly via FieldProcessors see https://portrait.atlassian.net/wiki/spaces/PA7/pages/1029112687/ELO#Mask-Attributes

For Mode Update/Delete there are additional requirements and checks:

Required Config for Mode UPDATE/DELETE:

  • The source: <sectionID> parameter needs to be set → this is the sectionID of the referenced section

For more details on the purpose and effect of the STRICT mode see:

https://portrait.atlassian.net/wiki/spaces/PA7/pages/1029112687/ELO#Improved-Security%3A-Scope-(Strict-%2F-Loose)

Conditions

With Portrait 7.0 we introduce the concept of conditions, which allows for extensive input validation to keep your data consistent at all times.

Furthermore, you can define which user can use which operation. Like this you can enforce “ACL” / permissions and define, which user is allowed to edit or delete an entry. I´

A condition is a boolean expression when evaluated either allow or prevent:

Example

condition:
  - expression: "{{in SELECTED_STATUS 'STATUS1' 'STATUS2'}}"
    errorMessage: 'only STATUS1 or STATUS2 are allowed'
  - expression: "{{in SELECTED_EMAIL PORTRAIT_USER_EMAIL}}"
    errorMessage: 'you can only edit your own entries'

Multiple Conditions can be set. All conditions need to match. (Logical AND between all conditions). You can build more complex rules with nested handlebars.

- expression: "{{or (in SELECTED_STATUS 'STATUS1' 'STATUS2') (eq PORTRAIT_USER_ROLE 'ADMIN')}}"
  errorMessage: 'only STATUS1 or STATUS2 are allowed, Admin can do anything.'

If needed, variables can also be preprocessed with Field Processors, this allows a better readability.

 - id: edit_entry
      onSubmit:
        type: ELO
        connection: eloconn
        mask: ELOMASK
        mode: UPDATE
        source: eloSource
        scope: STRICT
        condition:
          - expression: "{{or IS_VALID_STATUS IS_ADMIN_USER}}"
            errorMessage: 'only STATUS1 or STATUS2 are allowed, Admin can do anything'
        fieldProcessor:
          - field: STATUS
            value: "{{SELECTED_STATUS}}"
          - field: IS_VALID_STATUS
            value: "{{in SELECTED_STATUS 'STATUS1' 'STATUS2'}}"
            type: BOOLEAN
          - field: IS_ADMIN_USER
            value: "{{eq PORTRAIT_USER_ROLE 'ADMIN'}}"
            type: BOOLEAN

Conditional Support Currently on Forms https://portrait.atlassian.net/wiki/x/SQNXPQ currently works for

  • ELO

  • Python

  • SQL

For more details see: https://portrait.atlassian.net/wiki/x/AYDHPg

Section Actions

The Action inside a Section has been reworked and now support:

  • Conditional expressions. These allow to write custom boolean expression to either display or hide a action based on the metadata.

  • Handlebar Support for Labels and Links.

  • Support to link multiple Forms within a single section entry

Details, see: Actions

Field Processor

Type Boolean

A new type boolean has been added.

Example:

 fieldProcessor:
        - field: BudgetLeft
          value: '{{gt Amount 0}}'
          type: BOOLEAN

Details, see: Field Processors

In Helper

A new type helper has been added.

Check if a given value is contained in a given list of other values

{{in SELECT_VACATION_STATUS 'GENEHMIGT' 'ABGELEHNT'}}

Also a combination with various split methods is possible

{{in PORTRAIT_USER_EMAIL (splitBySemicolon EVENT_PARTICIPANTS) 'admin@portrait.com'}}

Details, see: https://portrait.atlassian.net/wiki/spaces/PA7/pages/1029114243/Field+Processors#In

File Download

It is now possible to download files linked to an indexed ELO Entry directly from the Table or Detail View.

Example:

sourceSpecific:
  mask: Application Entry
  files:
    nesting: 1
    mask: Application Attachment

Will be displayed like this:

Screenshot 2024-08-26 at 11.54.49.png

Depending on the file type, a preview is available. All files are available to download.

Search Index Space Optimization

We optimized the required disk space for the search recommendations. To take full advantage of this, we recommend that you delete your index and rebuild them from scratch.

To do this:

  1. Delete your sources that you want to optimize in the admin dashboard.

    Screenshot 2024-08-07 at 11.50.35.png

  2. Restart Portrait

  3. If mandatory, trigger a manual reindex if not configured periodic reindexing.

Breaking Changes

Breaking changes led to a major release. In this chapter, we summarize the breaking changes - which might affect your installation and need to be considered, whilst upgrading.

SQL Form Submit Parameter

We increased the security measurements whilst dealing with SQL write operations. This means, the SQL query will be parsed as prepared statement. For safety reasons, we enforce this style now for every SQL query. These changed are valid for all DML Statements. DDL Statements are not supported anymore.

Given this example for the createCompany form.

Example:

- id: createNewCompany
  onSubmit:
    type: SQL
    connection: internal
    query: |
      INSERT INTO DemoOrganigram (Name, PARENT_IDS, PARENT_LABELS)
        VALUES ('{{Name}}', '{{PARENT_IDS}}', '{{PARENT_LABELS}}');

The new format would be:

- id: createNewCompany
  onSubmit:
    type: SQL
    connection: organigram
    source: demo-organigram
    fieldProcessor:
      - field: Name
        value: "{{Name}}"
      - field: PARENT_IDS
        value: "{{PARENT_IDS}}"
      - field: PARENT_LABELS
        value: "{{PARENT_LABELS}}"
    query: |
      INSERT INTO DemoOrganigram (Name, PARENT_IDS, PARENT_LABELS)
        VALUES (:Name, :PARENT_IDS, :PARENT_LABELS);
  dialog: config/forms/createNewCompany.json

In this given example, the form-data will be inserted into the table DemoOrganigram via the connection organigram.

The FieldProcessors can either be used to format fields or as a fallback in case of an optional field in the form. If not supplied the Query would fail as there would be no valid parameter :Name if not set previously. With the given FieldProcessor the fallback is an empty String.

Details, see: https://portrait.atlassian.net/wiki/x/pQNXPQ

ELO Sources Files Indexing

When indexing files to the public folder, it is now required to set publicCache: true.

This is relevant to you, if you use Portrait in public mode - without authentication.

See also: Set up Public Access

Example:

sourceSpecific:
  mask: Application Entry
  files:
    publicCache: true
    nesting: 1
    mask: Application Attachment

Details, see: https://portrait.atlassian.net/wiki/spaces/PA7/pages/1029114146/ELO+sources#Index-Documents%2FFiles

Indexed files are also displayed in the section view and are available as a download.
Optionally, this behaviour can be disabled by setting the following flag inside the section:

- name: sectionid
  disableFiles: true

Details, see: Settings

ELO Sources Adminbase and Chaosablage indexing

When indexing elements within the ELO Administration (aka. “Administration” folder) and “Chaosablage”, results are per default now ignored this can be changed with:

sourceSpecific:
        blacklistChaosablage: false #default, if not set: true
        blacklistAdministration: false #default, if not set: true

https://treskon.atlassian.net/browse/POR-871

Details, see: ELO sources

In addition you can also provide own folder GUIDs that will be excluded:

TODO - document here? instead of screenshot.

Screenshot 2024-04-25 at 10.33.02.png

ELO Sources IDs

With this version, we switch to a more classic approach, like how ELO uses GUID’s. In ELO the identifier for a SORD is either a Object-Id, or a GUID. We use the GUID of ELO, but previously we removed the surrounding brackets artificially. With Release 7.X we remove this artificially modification of the GUID:

ELO Unique Identifier

Old - 6.x

New - 7.x

GUID

FC4B5EB2-359A-2FAE-C3DE-AC908A1A6BD9

(FC4B5EB2-359A-2FAE-C3DE-AC908A1A6BD9)

To maintain a consistent database ,we recommend to clear the existing ELO indexes and reindex them!

There might be some changes required in your configuration, when you used Field Processors , that use or manipulate the ELO-GUID’s.

Examples

Field Processor Use-Case

Old - 6.x

New - 7.x

A link to another Portrait detail entry. With 6.x you needed a substring manipulation.

value: '{{#if PARENT_ELOGUID}}[Open](https://organigram.customer.com/complete/{{substring PARENT_ELOGUID 1 37 }}/hi){{/if}}'

value: '{{#if PARENT_ELOGUID}}[Open](https://organigram.customer.com/complete/{{PARENT_ELOGUID}}/hi){{/if}}'

A link to the ELO Rich Client (via ELO protocol handler). In 6.x you had to add ( ) to the link.

value: 'elodms://({{key}})'

value: 'elodms://{{key}}'

When building references for the organigram inside Portrait, you had to remove the ( ).

value: '{{substring SHARE_SUBSIDIARY_ELOGUID 1 37 }}'

value: '{{SHARE_SUBSIDIARY_ELOGUID}}'

This examples prove, that with the new, unaltered, approach, the configuration gets simplier.

API changes

We did our homework, and the API, especially the documentation for it, is now concise and this will increase the possibilites to better integrate Portrait in your automations. If you open the API docs you will find a clean and grouped doc.

We also changed the following API routes, for better clarity:

API Use-Case

Old - 6.x

New - 7.x

Get all entries for a specific section or the global search

/data/

/search/

Get all entries for specific section or the global search with filter term (search query)

/data/{term}

/search/{term}

Retrieve the key value pairs for a single entry - nonetheless, what section it is in.

/docDetails/{docId}
(where docID was similar to the entryID)

This would lead to an issue when there would be the same entryID in two different sections. To guarantee uniqueness, docDetails was removed

Use either /entries/{sectionID}/{entryID} to query an unique entry. Or/data/{term} to perform a global search.

Method to retrieve a certain entry - via the source.

sources/{index}/{entryID}

This is similar to/entries/{sectionID}/{entryID}

Use /entries/{sectionID}/{entryID}

Currently there is a strong 1:1 connection between source and section. In the following, we plan to loosen up this restriction to connection a single source to multiple sections. This API change is one of the first steps towards that goal

  • No labels