What this is about
Besides its business fields, every object in CDMS has a few system fields. The server sets them, not the client. You can almost always recognize them by the leading underscore.
The system fields
| Field | Meaning | Present on | JSON name |
|---|---|---|---|
id | unique identifier, a UUID | every model | id |
_createdOn | when the object was created | every model | _createdOn |
_updatedOn | time of the last change | every model | _updatedOn |
_userId | ID of the person the object belongs to | user models only | _userId |
_MODELTYPE | concrete type of the object | every model, important for abstract models | @type |
_version | version counter against concurrent overwrites | file models only | – |
On top of that there are internal helper fields such as _reference, which CDMS uses during processing, for example so that nested writing does not run in circles. Do not evaluate them in the client.
Who sets what, and when?
| Create (POST /create) | Replace / update (PUT, PATCH) | Roll back | |
|---|---|---|---|
| id | generated by the database on save; an id sent by the client is ignored | stays; it decides which object is changed | stays |
| _createdOn | set to now | unchanged | stays |
| _updatedOn | stays empty | set to now | unchanged |
| _userId | set to the signed-in person | unchanged | stays |
| _MODELTYPE / @type | follows from the concrete type; for abstract models the client picks it with @type | unchanged, an object never changes its type | stays |
| _version | created by the database | incremented on every change | as for a change |
What happens if the client sends them?
-
1Client→CDMSsends
{ "data": { "id": "abc", "_userId": "someone-else", "_createdOn": "2020-01-01 00:00:00", "name": "Muster" }, "response": ["+"] } -
2CDMSwalks through the fields of the model and skips
idand every field starting with_ -
3CDMSsets
_createdOnto now and_userIdto the signed-in person -
4Databaseassigns a new
id -
5CDMS→Clientresponds with the server's valuesResult:
nameis stored.id,_userIdand_createdOncome from the server, not from the request. There is no error.
PUT and PATCH behave the same way, with one exception: there the id must be in data, because it says which object is meant. It is never changed.
| Operation | id in data? | What happens |
|---|---|---|
| POST /create | any | ignored, the server assigns a new one |
| PUT /update/{id} | yes | decides the object that is replaced |
| PUT /update/{id} | no | 400 missing-id |
| PATCH /update/{id} | yes | decides the object that is changed |
| PATCH /update/{id} | no | 400 missing-id |
What you get when reading
CDMS reads four values on every access, even if they are not in response: id, _createdOn, _updatedOn and the type.
| Request | Result |
|---|---|
["name"] | id_createdOn_updatedOn@typenameemailaddress id, _createdOn, _updatedOn and the type always come along. email and address are null in the response. |
There is a practical reason for this: with id and type the client can always identify an object unambiguously, even if it requested only one business field.
Each field in brief
When: every object
A UUID, stored as 16 bytes in the database. It is created on the first save and never changes. You address an object by it in every path: /read/{id}, /update/{id}, /delete/{id}. Singletons have one too, but it does not appear in any path.
When: every object
The server sets the time on create, including child objects created in the same request. After that it never changes, not even on a rollback.
When: every object
The server sets the time to now on every PUT and PATCH. On create the field stays empty; on a rollback to an old revision it stays unchanged. So it tells you when the object was last changed, but not by whom or what. That is what the history is for.
When: only models with the scope “user”
The ID of the person the row belongs to, taken from the sub claim of the token. It is set on create and then used by the owner filter: each person only sees rows with their own _userId. See Model levels.
When: every object, essential for abstract models
In the database the column is called _MODELTYPE, in JSON @type. For an abstract model, e.g. customer with privatecustomer and businesscustomer, it says which concrete type an object is. When creating under an abstract model, the client has to name it. See Abstract models.
When: file models only
A counter that the database increments on every change of the object. If two requests write a new file into the same object at the same time, the second fails with 409 instead of silently overwriting the first. See Concurrent changes.
System fields and history are two different things
- one value per field, the current state
- present on every model
- says: created when, belongs to whom, which type
- every change with the old state
- with time, person, IP address, browser
- says: who changed what, and when