What this is about
Two persons send the same search and get different matches. This is not a bug: CDMS adds filters to every search that the client does not see and cannot switch off.
The tree behind every search
flowchart TB
W["AND – root from CDMS"] --> C["your query"]
W --> O["own data<br/>_userId = logged-in person"]
W --> A["attribute filter<br/>e.g. companyId IN (companies from the profile)"]
W --> P["custom mandatory filters<br/>of the project"]
DB[("Database of the tenant")] -.->|"with MULTI: the tenant takes effect through the choice of database"| W
| Filter | When it runs along | Effect |
|---|---|---|
| Own data (owner filter) | for models whose objects belong to a person | only objects whose _userId is the logged-in person |
| Attribute filter | when the model has an attribute filter | only objects whose field matches an attribute in the profile |
| Custom mandatory filters | when the project registers a filter for the model | whatever the project’s filter specifies |
| Tenant | when every tenant has its own database (operating mode MULTI) | no filter in the query: CDMS reads directly from the tenant’s database, see SINGLE and MULTI |
Details: Only your own data (owner filter), Attribute filter, Custom data filters.
The attribute filter in detail
An attribute filter connects an attribute in the profile of the person with a field in the model. Example: the profile has company: ["123456", "654321"], the model order has the field companyId.
| Attribute company in the profile | Filter on companyId |
|---|---|
| "123456" | companyId = 123456 |
| "123456", "654321" or "123456,654321" | companyId IN (123456, 654321) |
| contains "*" | no filter, all orders |
| missing | 422 missing-attribute-on-profile|company |
| present, but empty | 422 empty-attribute-on-profile|company |
A missing or empty attribute never means “see everything”. The request fails instead of returning all data.
The same filters everywhere
The security filters do not only apply to POST /query:
When: POST /query
The matches and totalCount contain only what the filters let through.
Result: Two persons, two different lists.
When: POST /read/{id}
An object that the filters exclude does not exist for the person.
Result: 404, see Why invisible objects return 404.
When: expanded list, e.g. { "field": "orders" }
The entries of a list also go through the filters of their model.
Result: Only the visible entries.
When: PUT, PATCH, DELETE
CDMS first checks with the same filters whether the object is visible.
Result: What you are not allowed to read, you cannot change either: 404.
When a mandatory filter is not applicable
No filter is silently dropped: without it the search would return more rows than intended, for a security filter even all of them. A filter from the client that does not fit is therefore rejected (see When a filter does not fit). Security filters are mandatory filters, and with them the error is never the client’s:
- field unknown or operator does not fit → request rejected
- 400
unknown-search-key|…,unsupported-operator|… - the client corrects its request
- field unknown or operator does not fit → search fails
- 500
unresolvable-mandatory-filter|<feld>|… - better no result than too much
Such an error is a configuration error in the project, for example an attribute filter on a field that does not exist in the model.