diff --git a/.env b/.env index 1eb7f8da..6e7c8362 100644 --- a/.env +++ b/.env @@ -59,3 +59,17 @@ EMAIL_SENDER_EMAIL=noreply@partdb.changeme # Set this to 1 to allow reset of a password per email ALLOW_EMAIL_PW_RESET=0 + +###################################################################################### +# History/Eventlog related settings +###################################################################################### + +# If you want to use full timetrave functionality + +# Save which fields were changed in a ElementEdited log entry +HISTORY_SAVE_CHANGED_FIELDS=1 +# Save the old data in the ElementEdited log entry (warning this could increase the database size in short time) +HISTORY_SAVE_CHANGED_DATA=0 +# Save the data of an element that gets removed into log entry. This allows to undelete an element +HISTORY_SAVE_REMOVED_DATA=0 + diff --git a/config/services.yaml b/config/services.yaml index df74c644..2b97c116 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -74,6 +74,10 @@ services: - { name: "doctrine.orm.entity_listener" } App\EventSubscriber\EventLoggerSubscriber: + arguments: + $save_changed_fields: '%env(bool:HISTORY_SAVE_CHANGED_FIELDS)%' + $save_changed_data: '%env(bool:HISTORY_SAVE_CHANGED_DATA)%' + $save_removed_data: '%env(bool:HISTORY_SAVE_REMOVED_DATA)%' tags: - { name: 'doctrine.event_subscriber' } diff --git a/src/Entity/LogSystem/ElementEditedLogEntry.php b/src/Entity/LogSystem/ElementEditedLogEntry.php index 9c84d7a4..59be889c 100644 --- a/src/Entity/LogSystem/ElementEditedLogEntry.php +++ b/src/Entity/LogSystem/ElementEditedLogEntry.php @@ -68,7 +68,7 @@ class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterf */ public function hasChangedFieldsInfo(): bool { - return $this->hasOldDataInformations(); + return isset($this->extra['f']) || $this->hasOldDataInformations(); } /** @@ -77,7 +77,26 @@ class ElementEditedLogEntry extends AbstractLogEntry implements TimeTravelInterf */ public function getChangedFields(): array { - return array_keys($this->getOldData()); + if ($this->hasOldDataInformations()) { + return array_keys($this->getOldData()); + } + + if (isset($this->extra['f'])) { + return $this->extra['f']; + } + + return []; + } + + /** + * Set the fields that were changed during this element change. + * @param string[] $changed_fields The names of the fields that were changed during the elements + * @return $this + */ + public function setChangedFields(array $changed_fields): self + { + $this->extra['f'] = $changed_fields; + return $this; } /** diff --git a/src/EventSubscriber/EventLoggerSubscriber.php b/src/EventSubscriber/EventLoggerSubscriber.php index bc60f36e..3e0b9d36 100644 --- a/src/EventSubscriber/EventLoggerSubscriber.php +++ b/src/EventSubscriber/EventLoggerSubscriber.php @@ -25,6 +25,7 @@ use App\Entity\LogSystem\AbstractLogEntry; use App\Entity\LogSystem\ElementCreatedLogEntry; use App\Entity\LogSystem\ElementDeletedLogEntry; use App\Entity\LogSystem\ElementEditedLogEntry; +use App\Entity\UserSystem\User; use App\Services\LogSystem\EventCommentHelper; use App\Services\LogSystem\EventLogger; use Doctrine\Common\EventSubscriber; @@ -37,15 +38,26 @@ use Symfony\Component\Serializer\SerializerInterface; class EventLoggerSubscriber implements EventSubscriber { + + protected const MAX_STRING_LENGTH = 2000; + protected $logger; protected $serializer; protected $eventCommentHelper; + protected $save_changed_fields; + protected $save_changed_data; + protected $save_removed_data; - public function __construct(EventLogger $logger, SerializerInterface $serializer, EventCommentHelper $commentHelper) + public function __construct(EventLogger $logger, SerializerInterface $serializer, EventCommentHelper $commentHelper, + bool $save_changed_fields, bool $save_changed_data, bool $save_removed_data) { $this->logger = $logger; $this->serializer = $serializer; $this->eventCommentHelper = $commentHelper; + + $this->save_changed_fields = $save_changed_fields; + $this->save_changed_data = $save_changed_data; + $this->save_removed_data = $save_removed_data; } public function onFlush(OnFlushEventArgs $eventArgs) @@ -61,7 +73,12 @@ class EventLoggerSubscriber implements EventSubscriber foreach ($uow->getScheduledEntityUpdates() as $entity) { if ($this->validEntity($entity)) { $log = new ElementEditedLogEntry($entity); - $this->saveChangeSet($entity, $log, $uow); + if ($this->save_changed_data) { + $this->saveChangeSet($entity, $log, $uow); + } elseif ($this->save_changed_fields) { + $changed_fields = array_keys($uow->getEntityChangeSet($entity)); + $log->setChangedFields($changed_fields); + } //Add user comment to log entry if ($this->eventCommentHelper->isMessageSet()) { $log->setComment($this->eventCommentHelper->getMessage()); @@ -77,7 +94,9 @@ class EventLoggerSubscriber implements EventSubscriber if ($this->eventCommentHelper->isMessageSet()) { $log->setComment($this->eventCommentHelper->getMessage()); } - $this->saveChangeSet($entity, $log, $uow); + if ($this->save_removed_data) { + $this->saveChangeSet($entity, $log, $uow); + } $this->logger->log($log); } } @@ -94,6 +113,21 @@ class EventLoggerSubscriber implements EventSubscriber $changeSet = $uow->getEntityChangeSet($entity); $old_data = array_diff(array_combine(array_keys($changeSet), array_column($changeSet, 0)), [null]); + //Restrict length of string fields, to save memory... + $old_data = array_map(function ($value) { + if (is_string($value)) { + return mb_strimwidth($value, 0, self::MAX_STRING_LENGTH, '...'); + } + + return $value; + }, $old_data); + + //Dont save sensitive fields to log + if ($entity instanceof User) { + unset($old_data['password'], $old_data['pw_reset_token'], $old_data['backupCodes']); + } + + $logEntry->setOldData($old_data); }