CodamAIDocs
Topicdone

What is audited

Which models have a history, which operations create a revision, and which revision types exist.

Variants
auditing: trueADDMODDELnot audited model

What this is about

A model is either audited or not. Audited means: CDMS keeps the new state every time an object changes. Such a stored state is called a revision. All revisions of an object together are its history.

Whether a model is audited is decided by a single switch on the model: in the hub “Auditing: yes”, in a model file auditing: true. The switch applies to the whole model. You cannot leave out individual fields.

The timeline of an object

This is the history of an order that is created, changed twice, rolled back once and then deleted:

flowchart LR
    A["Revision 17 · ADD<br/>POST /create<br/>price 90.8"] --> B["Revision 42 · MOD<br/>PATCH<br/>price 120.5"]
    B --> C["Revision 51 · MOD<br/>PUT<br/>price 99.0"]
    C --> D["Revision 58 · MOD<br/>rollback to 17<br/>price 90.8"]
    D --> E["Revision 63 · DEL<br/>DELETE"]

Every revision has a type, in JSON revisionType:

TypeMeaningWhat the revision contains
ADDthe object was createdthe state right after creating
MODthe object was changedthe state right after the change
DELthe object was deletedonly the id, all other fields are empty

The numbers go up, but they have gaps. Revisions of other objects lie in between. More in What a revision records.

Which operation creates which revision

OperationRevision
POST /createADD
PUT /update/{id}, PATCH /update/{id}MOD, even if nothing changes in terms of content, because _updatedOn is set again
new file content for a file modelMOD, because fileVersion, size and type change
POST /{id}/rollback/{revision}MOD with the old content, see Rolling back to an old state
DELETE /delete/{id}DEL
a child is created, changed or deleted in the same requestan ADD, MOD or DEL revision of its own for the child, if its model is audited
only a list of the object changesMOD for the object that holds the list
read, search, read history, downloadno revision

The revisions are only created when the request ends successfully. If it fails, the revision is discarded together with everything else. See One request, one transaction.

One request, one revision number

If a request changes several objects, all changes get the same revision number. An order with three new items, created in one request, therefore results in one revision 17, and it contains the order and the three items, each as ADD.

This applies per database. If a request touches models in the system database and in the tenant database, each database gets a revision of its own with its own number. See No atomicity across two databases.

Audited or not

Is a revision created?
Model audited?Request writes?Request successful?Result
no––no revision, there is only the current state
yesno–no revision, reading is not recorded
yesyesnono revision, the change was discarded
yesyesyesnew revision ADD, MOD or DEL
What the switch does
auditing: true
audited
  • every change becomes a revision
  • history and rollback are possible if the endpoints are listed
  • for file models every old content stays as a version
  • the database gets an audit table for every table
  • hibernate-envers is added to the POM
auditing: false
not audited
  • only the current state
  • no history, no rollback, even if the endpoints are listed
  • new file content overwrites the old one
  • nothing remains after deleting

What happens in the background

You do not need to know this to use the API. It helps, though, when you look into the database:

From the switch to the revision
  1. 1
    Hub
    The model is set to "Auditing: yes".
  2. 2
    Build
    The generator writes @Audited on the entity class and adds hibernate-envers to the POM.
    Envers is the library that writes revisions. See The project scaffold.
  3. 3
    Database
    For every table of the model there is an audit table <table>_AUD, plus the table revinfo once per database.
  4. 4
    CDMS→Database
    On every successful write, Envers adds a row to revinfo and, for every changed object, a row to its _AUD table.
    Result: revinfo says who, when and from where. The _AUD row holds the state of the object.

The endpoints for reading the history and for rolling back are only created if the model is audited and they are in the endpoint list. See Which endpoints a model has.

Special cases

Auditing and time

When: A model with existing data is set to audited and generated again.

The history starts with the first change after that. For an existing object the first revision is then a MOD, there is no ADD. CDMS does not know older states, and you cannot roll back to them either.

When: An audited model is set to not audited.

New changes are no longer recorded, and the endpoints for history and rollback go away. What was recorded until then stays in the database, but can no longer be reached through the API.

When: An audited model has a relation to another model.

The target model must be audited as well. Envers rejects an audited model that points to a model that is not audited, and the application then does not start. That is why you audit models that are connected to each other together.

Pitfalls

What comes next

Sources in the code and the knowledge base
  • CDMS/cdms-generator – EntityProcessor (@Audited(withModifiedFlag = true, targetNotFoundAction = IGNORE) with auditing), CdmsYamlLoader (auditing, endpoints HISTORY_*/HISTORY_ROLLBACK), ApiProcessor/ApiSingletonProcessor (getHistoryMethod, getRollbackMethod: only isAudited() and endpoint)
  • CDMS/cdms-persistence-database – models/AbstractEntityModel (@Audited on the base class), auditing/AuditRevisionEntity, AuditHistoryReader.queryHistory (RevisionType), EntityClassFilterService (revinfo per persistence target)
  • CDMS/cdms-integrationtest – AbstractAuditTrailTest.createPatchDeleteAreEachRecorded (ADD, MOD, DEL; one revision per transaction)
  • documentation/50-auditierung/01-auditing-und-historie.md
Search