Coder Social home page Coder Social logo

damienharper / auditor Goto Github PK

View Code? Open in Web Editor NEW
146.0 4.0 49.0 647 KB

auditor, the missing audit log library

License: MIT License

PHP 100.00%
audit-logs auditor auditing-services diffs audit-bundle doctrine audit-log audit-trail audits doctrine2

auditor's Introduction

auditor Tweet

Latest Stable Version Latest Unstable Version auditor 3.x CI Scrutinizer Code Quality codecov License Total Downloads Monthly Downloads Daily Downloads

The purpose of auditor is to provide an easy and standardized way to collect audit logs.

Architecture

This library is architected around two concepts:

  • Auditing services responsible for collecting audit events
  • Storage services responsible for persisting audit traces

Those two kind of services are offered by Providers.

Default provider

A default provider is included with this library: the DoctrineProvider

DoctrineProvider offers both auditing services and sorage services. It creates audit logs for all Doctrine ORM database related changes:

  • inserts and updates including their diffs and relation field diffs.
  • many to many relation changes, association and dissociation actions.
  • if available, the user responsible for these changes and his IP address are recorded.
  • audit entries are inserted within the same transaction during flush event so that even if something fails the global state remains clean.

DoctrineProvider supports following RDBMS

  • MySQL
  • MariaDB
  • PostgreSQL
  • SQLite

DoctrineProvider should work with any other database supported by Doctrine. Though, we can only really support the ones we can test with GitHub Actions.

Basically you can track any change of any entity from audit logs.

NOTE: DoctrineProvider cannot track DQL or direct SQL statements executions.

Official Documentation

auditor official documentation can be found here.

Version Information

Version Status Requirements Badges
3.x Active development ๐Ÿš€ (Not yet released) PHP >= 8.2, Symfony >= 5.4 auditor 3.x CI
Scrutinizer Code Quality
codecov
2.x Active support PHP >= 7.4, Symfony >= 4.4 auditor 2.x CI
Scrutinizer Code Quality
codecov
1.x EOL PHP >= 7.2, Symfony >= 3.4 auditor 1.x CI
Scrutinizer Code Quality
codecov

Changelog is available here

Contributing

auditor is an open source project. Contributions made by the community are welcome. Send us your ideas, code reviews, pull requests and feature requests to help us improve this project.

Do not forget to provide unit tests when contributing to this project. To do so, follow instructions in this dedicated README

Credits

License

auditor is free to use and is licensed under the MIT license

auditor's People

Contributors

andrew-demb avatar damienharper avatar dbannik avatar djpremier avatar dmitryuk avatar janklan avatar joerndyherrn avatar knallcharge avatar maksclub avatar marmelatze avatar martijnboers avatar metabor avatar robier avatar samuel4x4 avatar sanderverkuil avatar vindert avatar yivi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

auditor's Issues

exception while creating audit table schema when using single table inheritance

Q A
auditor version 2.3.0
PHP version 8.1.8
Database MySQL / SQLite

Summary

I have an abstract parent entity which is not audited, but uses doctrine/orm inheritance type "SINGLE_TABLE" and defines the database table for its child entities. Some child entities are configured to be audited.

With auditor 2.3.0, creating the audit database schema throws an exception.

Current behavior

When the database schema is created for this abstract parent entity, the CreateSchemaListener wants to create the corresponding audit table. This throws an exception while trying to determine the table name from the configuration with the new logic introduced in auditor 2.3.0, as the parent entity does not have any configuration: Undefined array key "App\AbstractParentEntity"

$auditTablename = $this->resolveAuditTableName($entities[$entity], $configuration, $connection->getDatabasePlatform());

In versions before 2.3.0, the table name from the event was being used, which is independent of the configuration.

How to reproduce

Define an abstract parent entity and an audited child entity:

namespace App;

/**
 * @ORM\Table(name="entities")
 * @ORM\Entity()
 * @ORM\InheritanceType("SINGLE_TABLE")
 */
abstract class AbstractParentEntity {}

/**
 * @ORM\Entity
 */
class Entity {}

Configure auditing for the child entity:

dh_auditor:
    enabled: true
    providers:
        doctrine:
            table_prefix: ~
            table_suffix: '_audit'
            entities:
                App\Entity: ~

Create the database schema using Doctrine\ORM\Tools\SchemaTool::createSchema for the parent entity to create an Doctrine\ORM\Tools\ToolEvents::postGenerateSchemaTable event.

Expected behavior

Creating the database schema for the abstract parent entity and its child entities does not throw an exception and creates the corresponding audit table schema.

Incorrect primary key name on render

vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/AuditTrait::summarize
the method uses the actual name of the primary key (in my case the "code" field - $pkName variable)

vendor/damienharper/auditor-bundle/src/Resources/views/Audit/helpers/helper.html.twig:58-59
{% set subject = target.class~'#'~target.id %} {{ direction }} <code><a href="{{ path('dh_auditor_show_entity_history', { 'entity': helper.namespaceToParam(target.class), 'id': target.id }) }}">{{ subject }}</a></code>
but when rendering, we use the "id" field, but in my case it is not there, there is a "code" field

global enable disable moved, maybe thats okay

As always, thanks for your work on this bundle. I wrote a PR on the old version, a "global" runtime enable/disable.

I am just updating to v4, and DH\Auditor\Provider\Doctrine\Configuration::disable() no longer exists. I did a bit of digging around, and my code is still there, I just have to do DH\Auditor\Configuration::disable()

This is not a huge deal, and maybe that makes more sense with the new split setup. But, should there maybe be a "shortcut" in DH\Auditor\Provider\Doctrine\Configuration to the DH\Auditor\Configuration enable and disable?

What are your thoughts?

Is auditor using the database during a cache:clear?

I upgraded yesterday to 4.0.1. I use a docker environment, but also have a console binary on my host system. Now since yesterday I experience that a bin/console cache:clear is ending in a PDO exception (which is correct since the host environment doesn't have one), but that wasn't the case before.

I think Auditor is doing something with the database connection during cache warmup? Is this correct and expected behaviour or did I do something wrong?

Exception trace:
  at /home/paul/www/BO3/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:37
 PDO->__construct() at /home/paul/www/BO3/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:37
 Doctrine\DBAL\Driver\PDOConnection->__construct() at /home/paul/www/BO3/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php:24
 Doctrine\DBAL\Driver\PDOMySql\Driver->connect() at /home/paul/www/BO3/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:360
 Doctrine\DBAL\Connection->connect() at /home/paul/www/BO3/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:425
 Doctrine\DBAL\Connection->getDatabasePlatformVersion() at /home/paul/www/BO3/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:385
 Doctrine\DBAL\Connection->detectDatabasePlatform() at /home/paul/www/BO3/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:328
 Doctrine\DBAL\Connection->getDatabasePlatform() at /home/paul/www/BO3/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php:801
 Doctrine\ORM\Mapping\ClassMetadataFactory->getTargetPlatform() at /home/paul/www/BO3/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php:644
 Doctrine\ORM\Mapping\ClassMetadataFactory->completeIdGeneratorMapping() at /home/paul/www/BO3/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php:166
 Doctrine\ORM\Mapping\ClassMetadataFactory->doLoadMetadata() at /home/paul/www/BO3/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php:306
 Doctrine\Persistence\Mapping\AbstractClassMetadataFactory->loadMetadata() at /home/paul/www/BO3/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php:82
 Doctrine\ORM\Mapping\ClassMetadataFactory->loadMetadata() at /home/paul/www/BO3/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php:184
 Doctrine\Persistence\Mapping\AbstractClassMetadataFactory->getMetadataFor() at /home/paul/www/BO3/vendor/doctrine/persistence/lib/Doctrine/Persistence/Mapping/AbstractClassMetadataFactory.php:90
 Doctrine\Persistence\Mapping\AbstractClassMetadataFactory->getAllMetadata() at /home/paul/www/BO3/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Annotation/AnnotationLoader.php:32
 DH\Auditor\Provider\Doctrine\Auditing\Annotation\AnnotationLoader->load() at /home/paul/www/BO3/vendor/damienharper/auditor/src/Provider/Doctrine/DoctrineProvider.php:236
 DH\Auditor\Provider\Doctrine\DoctrineProvider->loadAnnotations() at /home/paul/www/BO3/vendor/damienharper/auditor/src/Provider/Doctrine/DoctrineProvider.php:45
 DH\Auditor\Provider\Doctrine\DoctrineProvider->registerAuditingService() at /home/paul/www/BO3/var/cache/de_/ContainerJBNVfRG/App_KernelDevDebugContainer.php:1518
 ContainerJBNVfRG\App_KernelDevDebugContainer->getDoctrineProviderService() at /home/paul/www/BO3/var/cache/de_/ContainerJBNVfRG/App_KernelDevDebugContainer.php:920
 ContainerJBNVfRG\App_KernelDevDebugContainer->getDoctrine_Dbal_DefaultConnectionService() at /home/paul/www/BO3/var/cache/de_/ContainerJBNVfRG/App_KernelDevDebugContainer.php:933
 ContainerJBNVfRG\App_KernelDevDebugContainer->getDoctrine_Orm_DefaultEntityManagerService() at /home/paul/www/BO3/var/cache/de_/ContainerJBNVfRG/App_KernelDevDebugContainer.php:2310
 ContainerJBNVfRG\App_KernelDevDebugContainer->getValidator_BuilderService() at /home/paul/www/BO3/var/cache/de_/ContainerJBNVfRG/getValidator_Mapping_CacheWarmerService.php:24
 ContainerJBNVfRG\getValidator_Mapping_CacheWarmerService::do() at /home/paul/www/BO3/var/cache/de_/ContainerJBNVfRG/App_KernelDevDebugContainer.php:597
 ContainerJBNVfRG\App_KernelDevDebugContainer->load() at /home/paul/www/BO3/var/cache/de_/ContainerJBNVfRG/getCacheWarmerService.php:25
 ContainerJBNVfRG\getCacheWarmerService::ContainerJBNVfRG\{closure}() at /home/paul/www/BO3/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php:90
 Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate->warmUp() at /home/paul/www/BO3/vendor/symfony/http-kernel/Kernel.php:580
 Symfony\Component\HttpKernel\Kernel->initializeContainer() at /home/paul/www/BO3/vendor/symfony/http-kernel/Kernel.php:780
 Symfony\Component\HttpKernel\Kernel->preBoot() at /home/paul/www/BO3/vendor/symfony/http-kernel/Kernel.php:121
 Symfony\Component\HttpKernel\Kernel->boot() at /home/paul/www/BO3/vendor/symfony/http-kernel/Kernel.php:139
 Symfony\Component\HttpKernel\Kernel->reboot() at /home/paul/www/BO3/vendor/symfony/framework-bundle/Command/CacheClearCommand.php:224
 Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand->warmup() at /home/paul/www/BO3/vendor/symfony/framework-bundle/Command/CacheClearCommand.php:148
 Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand->execute() at /home/paul/www/BO3/vendor/symfony/console/Command/Command.php:255
 Symfony\Component\Console\Command\Command->run() at /home/paul/www/BO3/vendor/symfony/console/Application.php:989
 Symfony\Component\Console\Application->doRunCommand() at /home/paul/www/BO3/vendor/symfony/framework-bundle/Console/Application.php:96
 Symfony\Bundle\FrameworkBundle\Console\Application->doRunCommand() at /home/paul/www/BO3/vendor/symfony/console/Application.php:290
 Symfony\Component\Console\Application->doRun() at /home/paul/www/BO3/vendor/symfony/framework-bundle/Console/Application.php:82
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /home/paul/www/BO3/vendor/symfony/console/Application.php:166
 Symfony\Component\Console\Application->run() at /home/paul/www/BO3/bin/console:42

Add whitelist option to audit columns

Add option include_columns to specify the columns to be used for auditing an entity. (only those columns should be audited then, changes in all the rest should be ignored)
Right now one has to ignore a lot of columns per entity to achieve the same thing.

In my opinion, most entities only have a few columns that are relevant for auditing, so it makes sense to just specify those and ignore the rest.

Laravel support

I see that the package's goal is to make it universal and possible to write own implementations based on it.

I think we can increase community twice if we will create a package like https://github.com/DamienHarper/auditor-bundle for Laravel.
What do you think? I have some experience on this framework

Support for Binary formats. (Ramsey: uuid_binary/uuid_binary_ordered_time)

Context

  • Using Symfony 5.x
  • Using PHP 7.4
  • Using Ramsey UuidBundle
  • Added following Types and Mapping Types:
        types:
          uuid_binary: Ramsey\Uuid\Doctrine\UuidBinaryType
          uuid_binary_ordered_time: Ramsey\Uuid\Doctrine\UuidBinaryOrderedTimeType
        mapping_types:
          uuid_binary: binary
          uuid_binary_ordered_time: binary
  • I have following entity:
/**
 * @ORM\Entity
 * @ORM\Table(...)
 * @Auditable()
 */
class Xxx implements Yyy
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class="Ramsey\Uuid\Doctrine\UuidOrderedTimeGenerator")
     * @ORM\Column(type="uuid_binary_ordered_time", unique=true)
     * @Ignore()
     */
    private Uuid $id;

    /**
     * @ORM\Column(...)
     */
    public string $yyy;
}

Error

Audit will fail to SQL error on insert. Example of error is following:

An exception occurred while executing 'INSERT INTO namespace_Xxx_audit (type, object_id, discriminator, transaction_hash, diffs, blame_id, blame_user, blame_user_fqdn, blame_user_firewall, ip, created_at) VALUES (:type, :object_id, :discriminator, :transaction_hash, :diffs, :blame_id, :blame_user, :blame_user_fqdn, :blame_user_firewall, :ip, :created_at)' with params ["insert", "\x11\xea\xb4\x47\xd5\x35\xc1\xd2\x99\x2f\x02\x42\xac\x1e\x00\x09", null, "16e29081336395cbe0f08971bb4f51b584dd94a0", "{\"firstName\":{\"old\":null,\"new\":\"F\"},\"lastName\":{\"old\":null,\"new\":\"L\"}}", null, null, null, "login", "172.30.0.1", "2020-06-22 06:18:40"]:

SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect string value: '\xEA\xB4G\xD55\xC1...' for column `database`.`namespace_Xxx_audit`.`object_id` at row 1

Problem

The problem is caused due value is expected to be string value when in the DB, but when code runs convertToDatabaseValue() here, it will convert it from string to binary which causes this error.

Solution

To solve this you need to be able specify which types are ran with $type->convertToPHPValue($value, $platform); instead of $type->convertToDatabaseValue($value, $platform);. Another solutions is to run (string) or __toString() cast on this value.

I am not honestly sure how this can be achived without hacky solutions, but I was thinking as you are refactoring everything for v4, this could be implemented in same rewrite.

Context to Problem/Solution

private function value(EntityManagerInterface $entityManager, Type $type, $value)
{
if (null === $value) {
return;
}
$platform = $entityManager->getConnection()->getDatabasePlatform();
switch ($type->getName()) {
case DoctrineHelper::getDoctrineType('BIGINT'):
$convertedValue = (string) $value;
break;
case DoctrineHelper::getDoctrineType('INTEGER'):
case DoctrineHelper::getDoctrineType('SMALLINT'):
$convertedValue = (int) $value;
break;
case DoctrineHelper::getDoctrineType('DECIMAL'):
case DoctrineHelper::getDoctrineType('FLOAT'):
case DoctrineHelper::getDoctrineType('BOOLEAN'):
$convertedValue = $type->convertToPHPValue($value, $platform);
break;
default:
$convertedValue = $type->convertToDatabaseValue($value, $platform);
}
return $convertedValue;
}

Extra

I dont want push you, but I am waiting v4 to finish stable state and this feature to be published before I add this library to my new project. Thank you for your awesome work. ๐Ÿฅ‡

Query all audited tables

Would it be possible to query all audited table for some criteria just like you can query a specific table ?

I know the query may be taking long time and consuming memory but this could be avoid with some kind of pagination maybe ?

Incorrect array destructuring when processing disassocitions

Q A
auditor version 2.0.0
PHP version 8.1.3
Database MySQL

Summary

Auditor fails to process entity disaccociation.

Current behavior

When attempting to deassociate inverse side of uni-directional ManyToMany relation (Report m..m Tags), I get a following error:

DH\Auditor\Provider\Doctrine\Auditing\Transaction\TransactionProcessor::dissociate(): Argument #4 ($mapping) must be of type array, int given, called in /srv/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php on line 164

I tracked the cause to be incorrect array destructuring: https://github.com/DamienHarper/auditor/blob/master/src/Model/Transaction.php#L24 even says the return value is [$source, $target, $id, $mapping], but https://github.com/DamienHarper/auditor/blob/master/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php#L162 is workin with it as if the $id was not expected: foreach ($transaction->getDissociated() as [$source, $target, $mapping]) {

Changing line 162 to foreach ($transaction->getDissociated() as [$source, $target, $id, $mapping]) { fixes the problem.

How to reproduce

I'll create a PoC if necessary - the cause seems to be obvious, fix as well - PoC might be just a wasted time.

Expected behavior

It should work :)

Entries in reverse order on audit table when using transactions

Q A
auditor version 1.3.1
PHP 7.4
MySQL 5.7
Symfony 5.3

Summary

Given these insert and update operations:

$this->orm->beginTransaction();

$e1 = new Entity();
$e1->setProperty($value);
$this->orm->persist($e1);
$this->orm->flush();
$e1->setProperty($value);
$this->orm->flush();
$e1->setProperty($value);
$this->orm->flush();

$e2 = new Entity();
$e2->setProperty($value);
$this->orm->persist($e2);
$this->orm->flush();
$e2->setProperty($value);
$this->orm->flush();
$e2->setProperty($value);
$this->orm->flush();

$this->orm->commit();

On the audit table you'll have them in the reverse order:

$e2 update
$e2 update
$e2 insert
$e1 update
$e1 update
$e1 insert

If you don't use beginTransaction() and commit(), they are in the correct order:

$e1 insert
$e1 update
$e1 update
$e2 insert
$e2 update
$e2 update

Do you have any idea why is this and how should it be fixed?

Dependency to doctrine/doctrine-bundle

Is there a specific reason to depend on doctrine/doctrine-bundle.

I am currently investigating the possibility to use it with a different framework, using components from symfony is completly fine, but doctrine-bundle pulls in the dependency-injection and with it more or less the complete framework.

From a code perspective at least none of the classes of Doctrine\Bundle is used, so it would be great, if this would not be runtime dependency (ok for dev-dependencies, if it is needed for tests).

Other opinions? I was very lucky to have found a component not beeing already a bundle itself. ;)

Manual entry in Audit tables

Sometimes when you encounter a bug you must change the data with an adhoc query in the database. Is there a way to insert a line of the diff in the Audit tables after making the update on the database through a query?

If not, I supposed the solution is to use the ORM to make the updates?

Thanks.

Support Doctrine DBAL 3

When using Doctrine DBAL 3.3.0 i got an error

"Error: Uncaught Error: Call to undefined method Doctrine\DBAL\Result::setFetchMode() in vendor/damienharper/auditor/src/Provider/Doctrine/Persistence/Reader/Query.php:72

Calling flush multiple times before committing causes additional audit-logs

I have an entity which should get audited and if I call flush more than once before calling commit, the audit-events will get logged with each subsequent commit again. In this example I end up with 11 identical insert audits:

        $this->orm->beginTransaction();
        $e = new Enity();
        $this->orm->persist($e);
        $this->orm->flush();
        $this->orm->flush();
        $this->orm->commit(); // Logs the insert once.

        // Logs an additional 10 inserts for the entity added above:
        for ($n=1;$n<=10;$n++) {
            $this->orm->beginTransaction();
            $this->orm->commit();
        }

I believe the issue is caused by DoctrineSubscriber::onFlush, which simply copies the current SQL-Logger to a class-variable and then tries to restore that value on commit, while not checking if the Audit-Logger is already installed.

Linking changes in child entities to their parent entity

I have a simple use case of logging an order with multiple order lines.

When changing the order line the order entity is not modified and no log is generated for it. Only the log for the order line entity is generated.

How can I query every change to an order + order lines using the order number only. So for every transaction i should get the changes for both order and orderline.

The diff for the order line entity doesn't have the order information to reference it.

The general question is how to link changes in child entities to their parent when the parent entity remains unchanged.

Include former data in the remove audit entry

In a lot of use cases it would be really helpful to include the former data of a removed entity into the audit log. Right now the log only stores that an entity with a specific id was removed. If you for example, use the audit log to audit any user specific data, you might not be able to track for what exactly was deleted.

I would suggest to include the old values in the diff/changeset like it is done in the case of an update.

Add another column for audit tables

I have been browsing the documentation trying to find a way to add a new field for each audit log, but I haven't found anything.

For our use case, the audit should be "tagged" with the project ID, and users within that project should be able to see the audit log. Users of course can be added and removed to the project.

At this time, audit logs seem to be owned by a user, but for our use case, it is owned by a project, and we still need to know who was the user who performed the action.

If it does not exist yet, then providing a way for devs to extend the audit log entity (like how FOSBundle does it with FOSUser) can do the job.

Thanks!

Deprecation of Doctrine\DBAL\Logging\SQLLogger Interface

Q A
auditor version 2.0.3
PHP version 8.1.8
Database SQLite

Summary

The Doctrine\DBAL\Logging\SQLLogger Interface is deprecated

Current behavior

Symfony 6.1 shows a deprecation notice.

2022-07-12T09:45:13+00:00 [info] User Deprecated: The "DH\Auditor\Provider\Doctrine\Auditing\Logger\Logger" class implements "Doctrine\DBAL\Logging\SQLLogger" that is deprecated Use {@see \Doctrine\DBAL\Logging\Middleware} or implement {@see \Doctrine\DBAL\Driver\Middleware} instead.
2022-07-12T09:45:13+00:00 [info] User Deprecated: The "DH\Auditor\Provider\Doctrine\Auditing\Logger\LoggerChain" class implements "Doctrine\DBAL\Logging\SQLLogger" that is deprecated Use {@see \Doctrine\DBAL\Logging\Middleware} or implement {@see \Doctrine\DBAL\Driver\Middleware} instead.

How to reproduce

  1. Install the auditor bundle in symfony 6.1
  2. configure SQLite database
  3. Look at deprecations.

Expected behavior

No deprecations are shown when using the library.

JsonException when using custom binary DoctrineType

Q A
auditor version 2.0.3
PHP version 8.1.2
Database SQLite

Summary

It fails to compute the diff when a custom Doctrine type mapped to binary database type is used. It checks for known types such as Ramsey or Symfony UUIDs, but doesn't provide for customization when it comes to custom types - it defaults to using convertToDatabaseValue for all the unknown types.

convertToDatabaseValue in this case is returning a binary value which breaks JSON encoding further down the line.

Current behavior

A custom doctrine type, e.g. a copy of AbstractUid would cause the following exception:

JsonException: Malformed UTF-8 characters, possibly incorrectly encoded

/opt/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php:221
/opt/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php:66
/opt/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php:139
/opt/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php:38
/opt/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionManager.php:32
/opt/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php:43
/opt/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Logger/Logger.php:28
/opt/app/vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Logger/LoggerChain.php:30
/opt/app/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1783
/opt/app/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:454
/opt/app/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:398
/opt/app/var/cache/test/ContainerPGPpJpP/EntityManager_9a5be93.php:136

How to reproduce

  1. Create a custom Doctrine type extending AbstractUid
  2. Persist and flush the entity
  3. See JsonException: Malformed UTF-8 characters, possibly incorrectly encoded

Expected behavior

  1. Create a custom Doctrine type extending AbstractUid
  2. Persist and flush the entity
  3. See audit entry created

We could maybe introduce an interface that could be used with custom types, and checked here?

Auditor fails to compute diff for new entities created in a transaction that depend on typed properties being used in the __toString()

Q A
auditor version 2.0.1
PHP version 7.4.28
Database MySQL

Summary

The auditor fails to create the audit trails for entities that are created within a transaction and have a custom __toString() method that depends on type hinted properties.

Current behavior

It currently throws an exception that a property must be initialized prior to accessing, or that null can't be used if the property has a default value.

Stack trace
Error {#220741
  #message: "Typed property Entity::$type must not be accessed before initialization"
  #code: 0
  #file: "./src/Entity.php"
  #line: 35
  trace: {
    ./src/Entity.php:35 {
      Entity->__toString()
      โ€บ {
      โ€บ     return $this->type;
      โ€บ }
    }
    ./var/cache/selenium/doctrine/orm/Proxies/__CG__Entity.php:203 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/AuditTrait.php:198 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/AuditTrait.php:164 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php:60 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php:139 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionProcessor.php:38 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Transaction/TransactionManager.php:32 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php:43 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Logger/Logger.php:28 { โ€ฆ}
    ./vendor/damienharper/auditor/src/Provider/Doctrine/Auditing/Logger/LoggerChain.php:30 { โ€ฆ}
    ./vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1783 { โ€ฆ}
    ./vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:242 { โ€ฆ}
    ./vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php:76 { โ€ฆ}
    ./vendor/doctrine/doctrine-fixtures-bundle/Command/LoadDataFixturesDoctrineCommand.php:158 { โ€ฆ}
    ./vendor/symfony/console/Command/Command.php:298 { โ€ฆ}
    ./vendor/symfony/console/Application.php:1033 { โ€ฆ}
    ./vendor/symfony/framework-bundle/Console/Application.php:96 { โ€ฆ}
    ./vendor/symfony/console/Application.php:299 { โ€ฆ}
    ./vendor/symfony/framework-bundle/Console/Application.php:82 { โ€ฆ}
    ./vendor/symfony/console/Application.php:171 { โ€ฆ}
    ./vendor/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php:54 { โ€ฆ}
    ./vendor/autoload_runtime.php:35 { โ€ฆ}
    ./bin/console:11 { โ€ฆ}
  }
}

How to reproduce

I think the snippet below is the general case what happens

/**
 * @Auditable()
 */
class TestEntity {
  private string $name;

  public function __construct(string $name) {
    $this->name = $name;
  }

  public function getName(): string
  {
    return $this->name;
  }

  public function __toString(): string
  {
    return $this->name;
  }
}

$em = $container->get(EntityManagerInterface::class);

$em->transactional(function($manager) {
  $test = new TestEntity('Hello');
  $manager->persist($test);
  $manager->flush();
};

I'll see whether I can create a PR that creates a test for this bug.

Expected behavior

I expected that it would not crash, and create an insert log item.

In master, PHP8 must use PHP8-style annotations instead of old-school /** ORM\Entity */ style

Q A
auditor version dev-master 19d5c11
PHP version 8.0.13
Database MariaDB

Summary

When #40 introduced PHP8 annotations, it still used $this->reader->getClassAnnotation if there weren't any Entity attributes.

        if (\PHP_VERSION_ID >= 80000 && $attributes = $reflection->getAttributes(Entity::class)) {
            $annotation = $attributes[0]->newInstance();
        } else {
            $annotation = $this->reader->getClassAnnotation($reflection, Entity::class);
        }

In #72, this changed so that on PHP8, it will always use the if block rather than the else block.

        if (\PHP_VERSION_ID >= 80000 && method_exists($reflection, 'getAttributes')) {
            $attributes = $reflection->getAttributes(Entity::class);
            $annotation = \count($attributes) > 0 ? $attributes[0]->newInstance() : null;
        } elseif (null !== $this->reader) {
            $annotation = $this->reader->getClassAnnotation($reflection, Entity::class);
        }

Same deal obviously with the other annotation checks for Auditable and Security

How to reproduce

/**
 * @ORM\Entity(repositoryClass="App\Repository\InventoryRepository")
 * @Audit\Auditable
 */
class Inventory
{
  // ...
}

doesn't recognize the class as Auditable

If I add the PHP8-style attributes then it does recognize it

#[
    ORM\Entity(repositoryClass: InventoryRepository::class),
    Audit\Auditable
]

Expected behavior

Even with PHP8, old-style annotations are still recognized

BackedEnum could not be converted to int

Q A
auditor version 2.0.5
PHP version 8.1.2
Database MySQL

Summary

ErrorException

Warning: Object of class App\Enum\ProductType could not be converted to int

Current behavior

vendor\damienharper\auditor\src\Provider\Doctrine\Auditing\Transaction\AuditTrait.php&line=89#line89)(line 89)

https://github.com/DamienHarper/auditor/blob/master/src/Provider/Doctrine/Auditing/Transaction/AuditTrait.php#L88

Current code

case DoctrineHelper::getDoctrineType('INTEGER'):
case DoctrineHelper::getDoctrineType('SMALLINT'):
$convertedValue = (int) $value; // @phpstan-ignore-line
break;

Bug fixed

case DoctrineHelper::getDoctrineType('INTEGER'):
case DoctrineHelper::getDoctrineType('SMALLINT'):
$convertedValue = (int) ($value instanceof \BackedEnum ? $value->value : $value) ; // @phpstan-ignore-line
break;

Error on upgrading symfony 6.2

When I upgrade to symfony 6.2 I get this error:

!! Error {#613
โ€ƒ!! #message: "Call to a member function addEventSubscriber() on null"
โ€ƒ!! #code: 0
โ€ƒ!! #file: "./vendor/damienharper/auditor/src/Provider/Doctrine/DoctrineProvider.php"
โ€ƒ!! #line: 51
โ€ƒ!! trace: {
โ€ƒ!! ./vendor/damienharper/auditor/src/Provider/Doctrine/DoctrineProvider.php:51 { โ€ฆ}

Support for Symfony 6 + DBAL3 (tests), and PHP 8.1 support

TLDR; Attempting to create a PR to add support for Symfony 6, but many issues crop.

Would it be worth attempting to fix these issues on branch 1.x, and have support from Sf 3 to Sf 6 on this branch... or would this efforts better directed at the v2? Branch? Do you consider v2 branch to be near enough to be released in the near future?

Now, the long version:

Q A
auditor version 1.3.1
PHP version >= 8

Right now the package is not installable/runnable on Symfony 6.

I've created a branch to see exactly what's blocking the upgrade.

First, getting the obvious out of the way, on composer.json we have:

    "symfony/event-dispatcher": "^3.4|^4.0|^5.0",
    "symfony/lock": "^3.4|^4.0|^5.0",
    "symfony/options-resolver": "^3.4|^4.0|^5.0"

and on require-dev:

    "symfony/var-dumper": "^4.0|^5.0"

Adding"|^6.0" everywhere would make it installable on Sf 6 at least (with --no-dev), but only for things to break elsewhere.

First, the less important issue (as I see it).

The use of "friendsofphp/php-cs-fixer": "^2.16. This version is only compatible with Symfony 3, 4, or 5. But not 6. And PHP-CS-Fixer ^3,it's not compatible with Symfony ^3. (First version with Sf 6 support is 3.4). So the same version of PHP-CS-Fixer cannot be installed for versions 3 to 6 of Symfony. And PHP-CS-Fixer config for v2 is not compatible with PHP-CS-Fixer v3...

This is bothersome because this is not even a "real" dependency, but simply an external tool, without any runtime impact. In real life, this shouldn't even be a compatibility issue. But it is because of installing dev tools via composer.

This hurdle could be sidestepped. A couple of options:

  • Install friendsofphp/php-cs-fixer as a PHAR e.g. using something like this, within composer; or like this, outisde
  • Install friendsofphp/php-cs-fixer using something like this, so it's installed on its separate vendor-bin directory.

Considering the nature of the tool, any option should be better than allowing it to trigger dependency hell.

But even with this out of the way:

The project requires "doctrine/doctrine-migrations-bundle": "^1.3|^2.0", but only doctrine-migrations-bundle >= 3 declare support for Sf 6. So we could change this to "^1.3|^2.0|^3.0" to allow --dev installation...

If that's the case, on Sf 6 doctrine-migrations-bundle v^3 would be installed, and at least this wouldn't block the installation.

But without adding a conflict rule for dbal >= 3, DBAL v 3 would be installed, and this would case several problems, with many, as far as I can see only on happening on --dev, since many tests break under DBAL 3 (the library itself works fine with DBAL 3, as far as I can see). So declaring the library to be incompatible with seems not great.

There is quite a bit to go to make this compatible with a Symfony ^3.4|^4.4|^5.4|^6.0...

Dropping v3 would alleviate this a fair bit... but could be an unacceptable compromise.

Before I keep digging and trying to see if a PR would make sense, what do you think of this? Is dropping v3 a no-go? Is adding v6 (and DBAL 3 for tests) support too much for this version of the library? Would you welcome efforts on this, or rather have contributions focus on the future v2?

Hopefully I can lend a hand in some capacity.

And happy new year! :)

Auditor use specific field of related Table instead of ID for log

Hi,
first thanks for this flexible bundle.

I developed an own "audit service" but this isn't flexible and professional then yours.
But I used a specific filed to log on related fields instead of the ID

Example:
Your approach: status old: App\Entity\Status#4 new: App\Entity\Status#1
My approach: status old: planing new: operation

The record #4 with the field name= planing
The record #1 with the field name = operation

The advantage is, it is traceable in the AuditLog to which exact value it was changed.

If somebody changed the field of the related table it isn't exact traceable which field was used with your approach.

Is this possible?

Thanks

release pls

@DamienHarper ๐Ÿ™ please can you make a release so we can use the attributes via a stable version? ๐Ÿ™

Auditing outside of Doctrine Entities

Is there a way for us to audit log a database operation that happened through SQL? Maybe writing our own provider? Are there any examples of this?

Thanks!

Help with reader

Hi, Something is not clear to us how to use the reader. We don't know what provider to use. If we just want to use the default provider, Doctrine-provider, how to use this?
Anyway, the goal is just to be able to show on the "show" page of the audited entity the list of X lasts changes, with a very simple view. (That field has been changed from this to that) and nothing else.

What's the best way? We thought we can just query from inside the controller of that entity, but we have an error with the lien $reader = new Reader($provider); What Provider do we put here?? We probably missed a little thing stupid, sorry!

migrate from damienharper/doctrine-audit-bundle

Hi,

I want to migrate to this package because the other package 'damienharper/doctrine-audit-bundle'is abandonded ( or replaced)

I already migrated my old yaml file to the new structure but i'm still stuck at the new subscriber.

In the old i ad a subscriber that needs to update some fields like ip because it's getting it from another place then the usual place.

In the old package i had the following:

        $storage = $this->manager->selectStorageSpace($this->manager->getConfiguration()->getEntityManager());

        /** @var Statement $statement */
        $statement = $storage->getConnection()->prepare($query);

        foreach ($payload as $key => $value) {
            $statement->bindValue($key, $value);
        }

        $statement->execute();

        // Prevent event from executing the original event
        $event->stopPropagation();

but how can i migrate this to this new package ?

Thanks,

EDIT:
Found it by watching src/EventSubscriber/AuditEventSubscriber.php

    /**
     * @param LifecycleEvent $event
     *
     * @return LifecycleEvent
     * @throws DBALException
     * @throws InvalidArgumentException
     */
    public function onLifecycleEvent(LifecycleEvent $event): LifecycleEvent
    {
        $payload = $event->getPayload();
        $payload['ip'] = 'Use this ip';

        $event->setPayload($payload);

        foreach ($this->auditor->getProviders() as $provider) {
            if ($provider->supportsStorage()) {
                try {
                    $provider->persist($event);
                } catch (Exception $e) {
                    // do nothing to ensure other providers are called
                }
            }
        }

        // Prevent event from executing the original event
        $event->stopPropagation();

        return $event;
    }

Does this support EasyAdmin3

Does this support EasyAdmin3 ?

When editing or creating items it doesn't seem to log it?

It use to work with the API Platform when it changes entities in the database however since upgrading to auditor-bundle 4.0 it doesn't seem to be working anymore

Auditor fails to compute diff when a column of type `blob` is modified.

Q A
auditor version 2.0.2
PHP version 7.4.28
Database MySQL

Summary

Computing the diff breaks when using a resource column.

Current behavior

When the line:

[
  'diffs' => json_encode($data['diff'], JSON_THROW_ON_ERROR),
]

is called when the diff contains a column of type resource, a JSON exception is thrown stating that the type is not supported.

JsonException
Type is not supported

How to reproduce

See my next PR which will introduce a failing test.

Expected behavior

I had hoped that this would, at least, not be failing.

Deprecation message with SF 5.3

[2021-06-16T19:17:11.041340+02:00] deprecation.INFO: User Deprecated: Passing name and value is deprecated, you should pass a FilterInterface object instead. {"exception":"[object] (ErrorException(code: 0): User Deprecated: Passing name and value is deprecated, you should pass a FilterInterface object instead. at /home/mysite/sites/myapp/vendor/damienharper/auditor/src/Provider/Doctrine/Persistence/Reader/Query.php:109)"} []

Ignore attribute is not recognized on child classes

Q A
auditor version 2.0.1 (auditor bundle 5.0.2)
PHP version 8.1.5
Database MariaDB

Summary

The Ignore attribute is not respected when it's on a private property in a parent class and a field was changed in a child class.

Current behavior

Here is my class hierarchy:

BaseOrder
  |- PizzaOrder

I have an updatedAt property defined as follows:

// Defined on BaseOrder
#[ORM\Column(name: "updatedAt", type: "datetime_immutable", nullable: true)]
#[Audit\Ignore]
private ?\DateTimeImmutable $updatedAt = null;

When making changes to a PizzaOrder the changes to updatedAt appear in the audit log.

How to reproduce

See above, please let me know if you'd like a working code sample.

Expected behavior

Ignore annotation can be defined in parent classes on private variables. Note that it does work as expected for protected variables.

Incorrect SQL statement using MSSQL

Q A
auditor-bundle version 4.1.0
PHP version 8.0.3
Database MSSQL

Summary

Running a migration always terun a ivalid SQL statement for MSSQL.

Current behavior

ALTER TABLE category_audit ALTER COLUMN id INT IDENTITY NOT NULL
SQL error is:
Incorrect syntax near the keyword 'IDENTITY
COLLATE, NOT, NULL, SPARSE or WITH expected, got 'IDENTITY'

How to reproduce

running
bin/console doctrine:schema:update
or
bin/console make:migration
when using MSSQL as db

Expected behavior

Nothing, when schema is up tot date.

New version

On the 19th of April, two bugs have been fixed (#99 and #97). Currently, our project uses the dev-master version of the project, because no new version has been released. When will the new version including these bug fixes be released?

And should a new version be released for the DamienHarper/auditor-bundle as well, with the updated dependency to 2.0.3?

Slow queries when finding the revisions of a single entity.

Q A
auditor version 1.2.0
PHP version 7.4.19
Database MySQL 5.7

Summary

When running queries like:

SELECT *
FROM audit_User
WHERE object_id = 1

Explained:

id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE audit_User <null> ALL object_id_875a3855f585b727b04ee34ace463a77_idx <null> <null> <null> 72046910 10 Using where; Using filesort

the queries take quite some time to run when a lot of data is present.

Current behavior

The queries are slow.

How to reproduce

  1. Have an audited entity
  2. Insert 500 entities in a table
  3. Modify each entity 500 times
  4. Observe that there are 500*500 revisions in the audit table (250000 records)
  5. Run the query SELECT * FROM audit_Entity WHERE object_id = 1
  6. See the execution plan and it should show that a FULL INDEX SCAN is done

Expected behavior

I expected that the Database would be smart and use the index to speed up this query.
For some reason though, the database thinks that the cardinality of the index is too high and a full index scan is actually faster.

Possible solution

The SimpleThings EntityAudit uses basically the same structure but has a different index setup.
Instead of creating just a UNIQUE index on the object_id it added a joined index on both the object_id and theid.
I tried to create a UNIQUE index on the id and the object_id as the id is a primary key I expected the id to be auto-incremented and unique, but I got an error that a duplicated key existed.
Perhaps this has something to do with #44?

Creating a non-unique index doesn't solve this issue, unfortunately.

The UI itself is fast because it limits the results to the 50 latest results. In the database, I'd like to see a complete overview of all the records (DataGrip limits the results to 1,500 by default) but that is quite slow.

What can be done to increase the database performance of the queries, as we really like this bundle but would also like to use this for investigative purposes.

Multifilters broken because of doctrine behavior

Q A
auditor version x.y.z
PHP version 7.1
Database MySQL / PostgreSQL / SQLite / Other

Summary

Hello! Critical error founded

The error is reproduced in this case:

$query->addFilter('object_id', 1);
$query->addFilter('object_id', 34);

This code will generate an error:
An exception occurred while executing 'SELECT * FROM contact_audit at WHERE object_id IN (?) ORDER BY created_at DESC, id DESC LIMIT 50' with params [[1,34]] Notice: Array to string conversion

Cause of error:
The parameter list support only works with Doctrine\DBAL\Connection::executeQuery() and Doctrine\DBAL\Connection::executeUpdate(), NOT with the binding methods of a prepared statement.

Source: https://www.doctrine-project.org/projects/doctrine-dbal/en/2.9/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion

Sorry for my rude and bad english

Php preload is broken by two classes in one file

Q A
auditor version 1.2.0
PHP version 8.0.9
Database PostgreSQL 12.06

Summary

Can't preload already declared class DH\Auditor\Event\AuditEvent in /var/www/wl-core/vendor/damienharper/auditor/src/Event/AuditEvent.php on line 44

How to reproduce

Enable preload in php.ini (bug 100% reproduces on symfony)

Expected behavior

You have no errors about preload. You're perfect.

Delete collection not log dissociate.

Q A
auditor version 2.0.2
PHP version 8.0
Database MySQL

Summary

Not properly log dissociation if collection is removed.

Current behavior

If i have 2 entities manyToMany and remove all items from one entity - no logs dissociation. If some item remains so it log correct with dissociation

It thinks function hydrateWithScheduledCollectionDeletions not work properly.

private function hydrateWithScheduledCollectionDeletions(Transaction $transaction, EntityManagerInterface $entityManager): void
    {
        $uow = $entityManager->getUnitOfWork();

        /** @var PersistentCollection $collection */
        foreach (array_reverse($uow->getScheduledCollectionDeletions()) as $collection) {
            $owner = $collection->getOwner();

            if (null !== $owner && $this->provider->isAudited($owner)) {
                $mapping = $collection->getMapping();

                if (null === $mapping) {
                    continue;
                }
                /** @var object $entity */
                foreach ($collection->toArray() as $entity) {
                    if ($this->provider->isAudited($entity)) {
                        $transaction->dissociate(
                            $owner,
                            $entity,
                            $mapping,
                        );
                    }
                }
            }
        }
    }

$mapping has data.
$collection->toArray() is always empty array so code in this foreach is never done.

How to reproduce

make 2 entity manyToMany (company , user)
add for example 3 users to company
remove 1 user
this will log correct with one dissociation
remove 2 remains users and it log nothing
(if no one user remains in collection so it not logging dissociation)

Expected behavior

removed all items from collection (example 3) -> get 3 logs with dissociation data

Dissociating while removing offers no target

I'm using auditor with the auditor-bundle for Symfony on the latest version (5.3).

I have an entity A that has a OneToMany relation to entity B with orphanRemoval=true, since B depends on A and cannot be transferred or stand on its own.
If I remove an entity B from A (e.g. via a form with a CollectionType), I get a transaction that looks somewhat like this:

App\Entity\A
App\Entity\A#132 (My Entity) has been dissociated by username , IP: 127.0.0.1

App\Entity\B
App\Entity\B#321 (Some Name) has been deleted by username , IP: 127.0.0.1

While it's easy enough to work out what has happened in this simple instance, it's a different question when it comes to larger transactions that might contain multiple different entities.
The reason is AuditTrait's summarize() method bailing early:

        // An added guard for proxies that fail to initialize.
        if (null === $pkValue) {
            return null;
        }

Without that guard, I'm getting this audit log entry:

App\Entity\A
App\Entity\A#132 (My Entity) has been dissociated from App\Entity\B# (Some Name) by username , IP: 127.0.0.1

App\Entity\B
App\Entity\B#321 (Some Name) has been deleted by username , IP: 127.0.0.1

Which is much better in my opinion. It lacks the ID because the EntityManager has already removed it at this stage in the Event, but it'll still have the label from __toString() and most importantly, it'll say what type of entity was dissociated from A.

Is there a better way to approach this?
I'm sure there's a reason to not summarize entities without primary keys and it probably can't simply be changed and create unexpected behavior legacy users. I haven't seen an obvious way to replace the TransactionProcessor with another class implementing TransactionProcessorInterface, have I missed it or is it currently impossible?

Json column is double encoded

Q A
auditor version 2.0.5
PHP version 8.1.0
Database MySQL / PostgreSQL / SQLite / Other

Summary

Json diffs are encoded twice. At the end it doesn't show correctly in viewer
image

Current behavior

Message in viewer encoded twice

"\u041f\u0420\u0418\u041c\u0415\u0420"

How to reproduce

  • Create entity with JSON column
  • Fill something in entity, that can be encoded with UTF-8, for example, ะŸะ ะ˜ะœะ•ะ 
  • Save entity

Expected behavior

I see ะŸะ ะ˜ะœะ•ะ  in viewer

Argument 1 passed to DH\\Auditor\\Model\\Entry::sort() must be of the type array, null given

Q A
auditor version 4.0.3
PHP version 7.3
Database MariaDB

Summary

Argument 1 passed to DH\Auditor\Model\Entry::sort() must be of the type array, null given, called in /var/www/app/vendor/damienharper/auditor/src/Model/Entry.php on line 160

When viewing audit log for an entity that have done a insert and does not have any diff.

How to reproduce

Use the viewer and press "view audit" on a entity with entries that do not have a diff.

Expected behavior

Not an error

Audit tables column `diffs` type unexpectedly changed from JSON to TEXT

Hi @DamienHarper,

After update doctrine wants to change type of all diffs columns in audit tables from json to text. [db: postgres, json support: yes]
I'm not sure that was intended.

Fragment below forces TEXT as the type of all JSON columns when database actually supports json columns .

if (DoctrineHelper::getDoctrineType('JSON') === $struct['type'] && $isJsonSupported) {

if (DoctrineHelper::getDoctrineType('JSON') === $struct['type'] && $isJsonSupported) {
    $type = DoctrineHelper::getDoctrineType('TEXT');
} else {
    $type = $struct['type'];
}

It looks like a bug. As commit message for these lines says the intent was to add compatibility for older versions of mariadb that don't support json.

DH\Auditor\Event\LifecycleEvent not called on sf5.2

Q A
auditor version 1.2.0
PHP version 8.05
Database MS-SQL

Summary

After upgrading to symfony 5.2 the auditor doesn't work anymore.
symfony 4.4 had no problems.
I've looked into the debug-toolbar and the DH\Auditor\Event\LifecycleEvent is on the " Not Called Listeners" tab:

DH\Auditor\Event\LifecycleEvent
--
-1000000 | "DH\Auditor\EventSubscriber\AuditEventSubscriber::onAuditEvent(LifecycleEvent $event): LifecycleEvent"

Current behaviour

Not creating audits

How to reproduce

Update to sf5.2

Expected behaviour

Create audits, just as on sf4.4

Changes on flush not handled by auditor

Q A
auditor version 1.3.0
PHP version 8.0.10
Database MariaDB

Summary

Due to GDPR i've marked some fields with personal data to be encrypted.
The fields are encrypted with an subscriber 'onFlush' these changes are not picked up by the auditor so it always sees an diff because the auditor sees an plain text instead of the encrypted value.

Current behavior

It now sees every encrypted field als an change which isn't and is creating a lot of inserts in the _audit tables.

How to reproduce

Perform an value change on a field with onFlush (Doctrine\ORM\Events::onFlush)

Expected behavior

That it will perform an diff check on postFlush or add a priority number for the auditor onFlush so i can set mine flush with more priority

Log the field for relations

I have an entity User and another entity Post which might have an author and an editor. Both of these reference User.
If I associate and dissociate an author, there's no way to tell whether the User was assigned as the author or editor.

Is there a use-case where adding the affected field might lead to problems?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.