Auditing of entities is done by:
_a
suffix according to a specific entity. Auditing is linked to all the basic entities, except for entities which cannot be audited. (IdmAudit, IdmPassword, etc.).There is a simple way of "enabling" versing for an entity in Hibernate envers. It is done simply by writing the annotation @Audited before the entity's definition. We DO NOT USE this way in the CzechIdMng system. Instead, we write this annotation to the individual entity attributes which we want to audit. For example:
@Audited @NotNull @Column(name = "disabled", nullable = false) private boolean disabled = false;
IdmAuditService serves as a mediator between Hibernate envers and IdmAudit. The service provides an access to the audit metadata (IdmAudit) and the versions themselves. The basic methods of this service are divided into findRevision
and findVersion
. The description of their differences can be found below.
Revisions in the CzechIdMng system are basic metadata about the individual revisions. The metadata is propagated to the front-end to the agenda itself. Using revisions, we are able to ascertain the following metadata:
The findRevision
methods are able to return exactly one revision for the given class, entity ID and revision ID, and also all the revisions for the class and entity ID. Using the getPreviousRevision
method, it is possible to get the previous revision according to the ID of the revision.
A version in the CzechIdMng system is a snapshot of the entity at a given time. Methods handling versions do not allow getting all the versions for the entity. Instead, they support getting one version getVersion
, the previous version getPreviousVersion
, and the difference (diff) between the versions getDiffBetweenVersion
. If we need to ascertain the last entity version, we can use the getLastVersionNumber
method.
If we do not know the exact entity type (class), an object will be returned as the version. If we want to get the individual values from this unidentifiable type, we can use the getValuesFromVersion
method. If we need a list of the changed attributes between the versions, we can use the getDiffBetweenVersion
method.
A complete list of the audited entities can be acquired by using the getAllAuditedEntitiesNames
method.
The current version of these methods can be found in the IdmAuditService interface. The most important methods have been chosen.
The method returns one revision, if it exists, or it returns an exception RevisionDoesNotExistException
The method returns all revisions for the entity. If no revision is found, an empty list is returned.
It returns the exact type of version, to the previous revision. The previous version is established using the revision ID.
It returns the previous entity version for the id revision. The version type cannot be determined easily at this moment.
The method returns the exact version type which is determined by revision ID and entity ID.
The method returns the last available revision number.
It returns a list of changed entity attributes. Note that only attributes with the @Audited annotation are accepted.
A list of all entities containing at least one @Audited annotation is returned.
A map is returned, where the key is the name of the attribute which has been changed in the second revision. The value is then the changed value from the second version.
If we do not know the exact version type, we can get it using PropertyUtils.getPropertyDescriptor
(getPropertyDescriptor)
The information about audit is located on the /audits
endpoint. The right for endpoints AUDITWRITE
. If a user owns a role with this permission, he is able, for example, to display data about users, to which he does not have to have any rights at all. This situation is desired.
does not exist for audit. All the other information about audit are secured using
AUDITREAD
Apart from the basic endpoints, the REST controller is extended by these endpoints.
The previous revisions is returned to the revision ID. If it does not exist, http status 404 is returned.
The endpoint compares the difference between two versions of revisions.
The same detail has been created for all entities to display audit detail. This detail enables displaying and comparison of two revisions including the difference of their version values.
The listener IdmAuditListener handles filling in of revision metadata.
At the moment, it performs these operations:
If it is the MOD (modification) type modification, comparison with the previous revision is done and the attribute changedColumns
is given the names of the changed attributes.
During synchronization (and not only there), a problem has been found with multiple saving of one entity in one transaction. For Envers, one transaction means one revision (the revision can then contain multiple versions/snapshots of various entities. If a creation of an entity is done in a transaction and then, after saving it, it is updated, the revision will contain two versions/snapshots of the entity. The problem comes when we want to fill in the list of changed attributes in the version because the previous version has not been committed yet.
Temporary solution: The functionality of changed attributes is temporarily disabled, the list of changed attributes can only be seen in the detail.
For better search audit for identities (for example by username) was create FE agenda for search identities with their relationship. For entity IdmAudit was added 6 new columns that is filled in a IdmAuditListener. This column is filled only when audited entity implements interface AuditSearchable (for example IdmIdentityRole).
Use Sub owner columns is recommended only for intersection tables. Example fill attributes (IdmIdentityRole):
@Override public String getOwnerId() { return this.getIdentityContract().getIdentity().getId().toString(); } @Override public String getOwnerCode() { return this.getIdentityContract().getIdentity().getCode(); } @Override public String getOwnerType() { return IdmIdentity.class.getName(); } @Override public String getSubOwnerId() { return this.getRole().getId().toString(); } @Override public String getSubOwnerCode() { return this.getRole().getCode(); } @Override public String getSubOwnerType() { return IdmRole.class.getName(); }
Endpoint for getting some entity with their relation is /audit/search/entity (IdmAuditController). As parameter is required entity that is name class. For this class is found implementation of AbstractAuditEntityService (service method DefaultAuditService (findEntityWithRelation))