critical
#29080
Unwanted row objects in tables with changes from other sessions
Due to the current implementation of receiveModelChangedEvent and receiveModelCreatedEvent in the TableComponent, it can happen that unwanted row objects appear in a table after these row objects have previously been changed or created in another session.
This ensures that users see elements that they are not allowed to see (for authorization reasons).
**Example situation:**
- You have a tree that displays project elements.
- The selection of the tree serves as a model for a table that displays, for example, the components of the selected project element.
- The table has an editor / dialog in which the component selected in the table is displayed.
**Procedure:**
- User 1 selects a project element and sees (only) the components for the selected project element in the table.
- User 2 selects another project element, selects a component there and changes it in the editor / dialog.
- User 1 updates the GUI (e.g. by pressing F5 or moving columns in the table or by clicking within the table without changing the model in the tree).
- Error: The component changed by user 2 suddenly appears in the table of user 1, although it does not belong to the currently selected project element.
- A reselection in the project tree "repairs" the table again until a component is changed (or created) again in another session.
**Cause:**
The problem is due to the implementation / configuration and different interpretation of the supportsListElement method in the ListModelBuilder.
- If an element is changed or created, supportsListElement is called on the table for this element. If the element is "supported", the table adds this element directly to the list of row objects without further checks instead of calling the ModelBuilder again.
- In practice, the methods are usually implemented in the form element instanceof MyType, whereby every object of this type is added to the list, regardless of whether it matches the selection of the master or other (functional) filters implemented in ModelBuilder.
- If a component is set as a model in the editor / dialog via a goto or bookmark link, the table attempts to set this component as a selection and to set a matching model. Here supportsListElement is also checked, but this time with a different semantics, which expects exactly this usual implementation of element instanceof MyType.
**Solution:**
In the corresponding receive methods of the TableComponent, an invalidate() must be called instead of addRow(), so that the ModelBuilder calculates in the normal way which components should now be displayed after the change and which should not.
The whole thing must also be checked for other classes implementing receive methods, e.g. TreeTableComponent, GridComponent, ...
Implementation
- If object types are specified in the table, an instanceOf check is automatically performed. Only elements that pass the instanceOf check are transferred to the ListModelBuilder#supportsListElement API.
- A new ElementUpdate constant com.top_logic.mig.html.ElementUpdate.UNKNOWN has been introduced. If this is returned in ListModelBuilder#supportsListElement, the table is invalidated and the list is recreated.
- ListModelByExpression has been adapted so that if no supportsElement script is set, ElementUpdate.UNKNOWN is always returned. New tables/grids are created without supportsElement to prevent the developer from customizing "elements" but forgetting "suportsElement".
Code migration
- If it is unclear whether an object should be added to the list or removed from the list, the ListModelBuilder must return ElementUpdate.UNKNOWN in ListModelBuilder#supportsListElement.
- InApp tables and grids must be checked. If the table/grid displays all objects of a type, "true" must be returned. If the table/grid is to rebuild the list when an element of the supported type is created, "supportsElement" must be left empty.