From d0173619404bac3cfa64e28886458bc079d7db7f Mon Sep 17 00:00:00 2001 From: Andrew Cornforth Date: Thu, 3 Mar 2022 10:18:29 +0000 Subject: [PATCH 1/8] Add Ip address to AuditLog Entity, and log it in audit() method of AuditSubscriber --- src/DataDog/AuditBundle/Entity/AuditLog.php | 111 ++++++++++++++++++ .../config/doctrine/AuditLog.orm.xml | 26 ++++ .../config/doctrine/AuditLog.orm.yml | 31 +++++ src/EventSubscriber/AuditSubscriber.php | 9 ++ 4 files changed, 177 insertions(+) create mode 100644 src/DataDog/AuditBundle/Entity/AuditLog.php create mode 100644 src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.xml create mode 100644 src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.yml diff --git a/src/DataDog/AuditBundle/Entity/AuditLog.php b/src/DataDog/AuditBundle/Entity/AuditLog.php new file mode 100644 index 0000000..fabc57d --- /dev/null +++ b/src/DataDog/AuditBundle/Entity/AuditLog.php @@ -0,0 +1,111 @@ +id; + } + + public function getAction() + { + return $this->action; + } + + public function getTbl() + { + return $this->tbl; + } + + public function getSource() + { + return $this->source; + } + + public function getTarget() + { + return $this->target; + } + + public function getBlame() + { + return $this->blame; + } + + public function getDiff() + { + return $this->diff; + } + + public function getLoggedAt() + { + return $this->loggedAt; + } + + public function getIp(): ?string + { + return $this->ip; + } + + public function setIp(?string $ip): void + { + $this->ip = $ip; + } +} diff --git a/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.xml b/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.xml new file mode 100644 index 0000000..f453177 --- /dev/null +++ b/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.yml b/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.yml new file mode 100644 index 0000000..6bc75cb --- /dev/null +++ b/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.yml @@ -0,0 +1,31 @@ +DataDog\AuditBundle\Entity\AuditLog: + type: entity + table: audit_logs + id: + id: + type: bigint + generator: + strategy: IDENTITY + + oneToOne: + source: + targetEntity: Association + joinColumn: + nullable: false + target: + targetEntity: Association + blame: + targetEntity: Association + + fields: + ip: + nullable: true + action: + length: 12 + tbl: + length: 128 + diff: + type: json + nullable: true + loggedAt: + type: datetime diff --git a/src/EventSubscriber/AuditSubscriber.php b/src/EventSubscriber/AuditSubscriber.php index c8228d4..01c25d9 100644 --- a/src/EventSubscriber/AuditSubscriber.php +++ b/src/EventSubscriber/AuditSubscriber.php @@ -345,6 +345,15 @@ protected function audit(EntityManager $em, array $data) // audit association explicitly sets that. $data[$field] = $meta->idGenerator->generate($em, null); } + // Log the ip address. + $masterRequest = $this->requestStack->getMasterRequest(); + // use this instead when support for symfony <5.3 dropped + // $masterRequest = $this->requestStack->getMainRequest(); + if ($masterRequest !== null) { + $data['ip'] = $masterRequest->getClientIp(); + } else { + $data['ip'] = null; + } $meta = $em->getClassMetadata(AuditLog::class); $data['loggedAt'] = new \DateTime(); From 706f59491ababd3a8ecc5f3722342c692621eeac Mon Sep 17 00:00:00 2001 From: Andrew Cornforth Date: Thu, 3 Mar 2022 10:24:23 +0000 Subject: [PATCH 2/8] fix indents --- src/DataDog/AuditBundle/Entity/AuditLog.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/DataDog/AuditBundle/Entity/AuditLog.php b/src/DataDog/AuditBundle/Entity/AuditLog.php index fabc57d..17fc176 100644 --- a/src/DataDog/AuditBundle/Entity/AuditLog.php +++ b/src/DataDog/AuditBundle/Entity/AuditLog.php @@ -97,15 +97,15 @@ public function getDiff() public function getLoggedAt() { return $this->loggedAt; - } + } - public function getIp(): ?string - { - return $this->ip; - } + public function getIp(): ?string + { + return $this->ip; + } - public function setIp(?string $ip): void - { - $this->ip = $ip; + public function setIp(?string $ip): void + { + $this->ip = $ip; } } From 413f83c7eac51c27d3454b31648675eab3da8616 Mon Sep 17 00:00:00 2001 From: Andrew Cornforth Date: Wed, 9 Mar 2022 15:22:08 +0000 Subject: [PATCH 3/8] Rebase on 1.0-dev --- src/DataDog/AuditBundle/Entity/AuditLog.php | 111 ------------------ .../config/doctrine/AuditLog.orm.xml | 26 ---- .../config/doctrine/AuditLog.orm.yml | 31 ----- src/DependencyInjection/Configuration.php | 12 +- .../DataDogAuditExtension.php | 7 ++ src/Entity/AuditLog.php | 14 +++ src/EventSubscriber/AuditSubscriber.php | 35 ++++-- .../config/doctrine/AuditLog.orm.xml | 2 + src/Resources/config/services.php | 2 + 9 files changed, 63 insertions(+), 177 deletions(-) delete mode 100644 src/DataDog/AuditBundle/Entity/AuditLog.php delete mode 100644 src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.xml delete mode 100644 src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.yml diff --git a/src/DataDog/AuditBundle/Entity/AuditLog.php b/src/DataDog/AuditBundle/Entity/AuditLog.php deleted file mode 100644 index 17fc176..0000000 --- a/src/DataDog/AuditBundle/Entity/AuditLog.php +++ /dev/null @@ -1,111 +0,0 @@ -id; - } - - public function getAction() - { - return $this->action; - } - - public function getTbl() - { - return $this->tbl; - } - - public function getSource() - { - return $this->source; - } - - public function getTarget() - { - return $this->target; - } - - public function getBlame() - { - return $this->blame; - } - - public function getDiff() - { - return $this->diff; - } - - public function getLoggedAt() - { - return $this->loggedAt; - } - - public function getIp(): ?string - { - return $this->ip; - } - - public function setIp(?string $ip): void - { - $this->ip = $ip; - } -} diff --git a/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.xml b/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.xml deleted file mode 100644 index f453177..0000000 --- a/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.yml b/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.yml deleted file mode 100644 index 6bc75cb..0000000 --- a/src/DataDog/AuditBundle/Resources/config/doctrine/AuditLog.orm.yml +++ /dev/null @@ -1,31 +0,0 @@ -DataDog\AuditBundle\Entity\AuditLog: - type: entity - table: audit_logs - id: - id: - type: bigint - generator: - strategy: IDENTITY - - oneToOne: - source: - targetEntity: Association - joinColumn: - nullable: false - target: - targetEntity: Association - blame: - targetEntity: Association - - fields: - ip: - nullable: true - action: - length: 12 - tbl: - length: 128 - diff: - type: json - nullable: true - loggedAt: - type: datetime diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index e49255d..05bbce5 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -28,8 +28,18 @@ public function getConfigTreeBuilder(): TreeBuilder ->end() ->children() ->booleanNode('blame_impersonator') - ->defaultFalse() + ->defaultFalse() + ->end() + ->end() + ->children() + ->booleanNode('log_user_ip') + ->defaultFalse() + ->end() + ->booleanNode('log_user_agent') + ->defaultFalse() + ->end() ->end() + ; // @formatter:on diff --git a/src/DependencyInjection/DataDogAuditExtension.php b/src/DependencyInjection/DataDogAuditExtension.php index 134de9f..04ef854 100644 --- a/src/DependencyInjection/DataDogAuditExtension.php +++ b/src/DependencyInjection/DataDogAuditExtension.php @@ -28,5 +28,12 @@ public function load(array $configs, ContainerBuilder $container): void if (isset($config['blame_impersonator'])) { $auditSubscriber->addMethodCall('setBlameImpersonator', array($config['blame_impersonator'])); } + + if (isset($config['log_user_ip'])) { + $auditSubscriber->addMethodCall('setLogIp', array($config['log_user_ip'])); + } + if (isset($config['log_user_agent'])) { + $auditSubscriber->addMethodCall('setLogUserAgent', array($config['log_user_agent'])); + } } } diff --git a/src/Entity/AuditLog.php b/src/Entity/AuditLog.php index e019cd3..fe78a2e 100644 --- a/src/Entity/AuditLog.php +++ b/src/Entity/AuditLog.php @@ -8,6 +8,10 @@ class AuditLog private string $action; + private ?string $ip; + + private ?string $userAgent; + private string $tbl; private Association $source; @@ -59,4 +63,14 @@ public function getLoggedAt(): \DateTimeInterface { return $this->loggedAt; } + + public function getIp(): ?string + { + return $this->ip; + } + + public function getUserAgent(): ?string + { + return $this->userAgent; + } } diff --git a/src/EventSubscriber/AuditSubscriber.php b/src/EventSubscriber/AuditSubscriber.php index 01c25d9..160bf43 100644 --- a/src/EventSubscriber/AuditSubscriber.php +++ b/src/EventSubscriber/AuditSubscriber.php @@ -14,6 +14,7 @@ use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Events; use Doctrine\ORM\Mapping\ClassMetadataInfo; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Role\SwitchUserRole; @@ -52,9 +53,19 @@ class AuditSubscriber implements EventSubscriber protected TokenStorageInterface $securityTokenStorage; - public function __construct(TokenStorageInterface $securityTokenStorage) + private RequestStack $requestStack; + + private bool $logIp = false; + + private bool $logUserAgent = false; + + public function __construct( + TokenStorageInterface $securityTokenStorage, + RequestStack $requestStack + ) { $this->securityTokenStorage = $securityTokenStorage; + $this->requestStack = $requestStack; } public function setLabeler(?callable $labeler = null): self @@ -346,14 +357,12 @@ protected function audit(EntityManager $em, array $data) $data[$field] = $meta->idGenerator->generate($em, null); } // Log the ip address. - $masterRequest = $this->requestStack->getMasterRequest(); + $mainRequest = $this->requestStack->getMasterRequest(); // use this instead when support for symfony <5.3 dropped - // $masterRequest = $this->requestStack->getMainRequest(); - if ($masterRequest !== null) { - $data['ip'] = $masterRequest->getClientIp(); - } else { - $data['ip'] = null; - } + // $mainRequest = $this->requestStack->getMainRequest(); + + $data['ip'] = $this->logIp && $mainRequest ? $mainRequest->getClientIp() : null; + $data['userAgent'] = $this->logUserAgent && $mainRequest ? substr($mainRequest->headers->get('User-Agent'), 0, 255) : null; $meta = $em->getClassMetadata(AuditLog::class); $data['loggedAt'] = new \DateTime(); @@ -543,4 +552,14 @@ public function setBlameUser(UserInterface $user) { $this->blameUser = $user; } + + public function setLogIp(bool $logIp): void + { + $this->logIp = $logIp; + } + + public function setLogUserAgent(bool $logUserAgent): void + { + $this->logUserAgent = $logUserAgent; + } } diff --git a/src/Resources/config/doctrine/AuditLog.orm.xml b/src/Resources/config/doctrine/AuditLog.orm.xml index d2c2df7..a2db359 100644 --- a/src/Resources/config/doctrine/AuditLog.orm.xml +++ b/src/Resources/config/doctrine/AuditLog.orm.xml @@ -7,6 +7,8 @@ + + diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php index d2a6a44..6503655 100644 --- a/src/Resources/config/services.php +++ b/src/Resources/config/services.php @@ -4,6 +4,7 @@ use DataDog\AuditBundle\EventSubscriber\AuditSubscriber; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; return static function (ContainerConfigurator $container) { @@ -12,6 +13,7 @@ $services ->set('datadog.event_subscriber.audit', AuditSubscriber::class)->private() ->arg(0, new Reference(TokenStorageInterface::class)) + ->arg(1, new Reference(RequestStack::class)) ->tag('doctrine.event_subscriber') ; // @formatter:on From b5ad782b2758061c17afdf68c7c09c486b35b2db Mon Sep 17 00:00:00 2001 From: Andrew Cornforth Date: Wed, 9 Mar 2022 15:22:08 +0000 Subject: [PATCH 4/8] Code review changes --- src/DependencyInjection/Configuration.php | 3 +++ src/DependencyInjection/DataDogAuditExtension.php | 3 +++ src/EventSubscriber/AuditSubscriber.php | 15 ++++++++++----- src/Resources/config/doctrine/AuditLog.orm.xml | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 05bbce5..ca3f390 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -38,6 +38,9 @@ public function getConfigTreeBuilder(): TreeBuilder ->booleanNode('log_user_agent') ->defaultFalse() ->end() + ->integerNode('truncate_user_agent') + ->defaultValue(1024) + ->end() ->end() ; diff --git a/src/DependencyInjection/DataDogAuditExtension.php b/src/DependencyInjection/DataDogAuditExtension.php index 04ef854..2137967 100644 --- a/src/DependencyInjection/DataDogAuditExtension.php +++ b/src/DependencyInjection/DataDogAuditExtension.php @@ -35,5 +35,8 @@ public function load(array $configs, ContainerBuilder $container): void if (isset($config['log_user_agent'])) { $auditSubscriber->addMethodCall('setLogUserAgent', array($config['log_user_agent'])); } + if (isset($config['truncate_user_agent'])) { + $auditSubscriber->addMethodCall('setTruncateUserAgent', array($config['truncate_user_agent'])); + } } } diff --git a/src/EventSubscriber/AuditSubscriber.php b/src/EventSubscriber/AuditSubscriber.php index 160bf43..32e0658 100644 --- a/src/EventSubscriber/AuditSubscriber.php +++ b/src/EventSubscriber/AuditSubscriber.php @@ -59,6 +59,8 @@ class AuditSubscriber implements EventSubscriber private bool $logUserAgent = false; + private int $truncateUserAgent = 1024; + public function __construct( TokenStorageInterface $securityTokenStorage, RequestStack $requestStack @@ -356,13 +358,11 @@ protected function audit(EntityManager $em, array $data) // audit association explicitly sets that. $data[$field] = $meta->idGenerator->generate($em, null); } - // Log the ip address. - $mainRequest = $this->requestStack->getMasterRequest(); - // use this instead when support for symfony <5.3 dropped - // $mainRequest = $this->requestStack->getMainRequest(); + // Log the ip address and User Agent String. + $mainRequest = $this->requestStack->getMainRequest(); $data['ip'] = $this->logIp && $mainRequest ? $mainRequest->getClientIp() : null; - $data['userAgent'] = $this->logUserAgent && $mainRequest ? substr($mainRequest->headers->get('User-Agent'), 0, 255) : null; + $data['userAgent'] = $this->logUserAgent && $mainRequest ? substr($mainRequest->headers->get('User-Agent'), 0, $this->truncateUserAgent) : null; $meta = $em->getClassMetadata(AuditLog::class); $data['loggedAt'] = new \DateTime(); @@ -562,4 +562,9 @@ public function setLogUserAgent(bool $logUserAgent): void { $this->logUserAgent = $logUserAgent; } + + public function setTruncateUserAgent(int $truncateUserAgent): void + { + $this->truncateUserAgent = $truncateUserAgent; + } } diff --git a/src/Resources/config/doctrine/AuditLog.orm.xml b/src/Resources/config/doctrine/AuditLog.orm.xml index a2db359..1d8450b 100644 --- a/src/Resources/config/doctrine/AuditLog.orm.xml +++ b/src/Resources/config/doctrine/AuditLog.orm.xml @@ -8,7 +8,7 @@ - + From f57087541e93391c81d1ad83171b152a323250eb Mon Sep 17 00:00:00 2001 From: Andrew Cornforth Date: Thu, 10 Mar 2022 11:45:39 +0000 Subject: [PATCH 5/8] protected instead of private visibility in audit subscriber --- src/EventSubscriber/AuditSubscriber.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/EventSubscriber/AuditSubscriber.php b/src/EventSubscriber/AuditSubscriber.php index 32e0658..1864cce 100644 --- a/src/EventSubscriber/AuditSubscriber.php +++ b/src/EventSubscriber/AuditSubscriber.php @@ -53,13 +53,13 @@ class AuditSubscriber implements EventSubscriber protected TokenStorageInterface $securityTokenStorage; - private RequestStack $requestStack; + protected RequestStack $requestStack; - private bool $logIp = false; + protected bool $logIp = false; - private bool $logUserAgent = false; + protected bool $logUserAgent = false; - private int $truncateUserAgent = 1024; + protected int $truncateUserAgent = 1024; public function __construct( TokenStorageInterface $securityTokenStorage, From 2e56446e4f025a87d4e2bbf4346122fbdca0490d Mon Sep 17 00:00:00 2001 From: Andrew Cornforth Date: Thu, 10 Mar 2022 16:34:26 +0000 Subject: [PATCH 6/8] length=255 for ip address --- src/Resources/config/doctrine/AuditLog.orm.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/config/doctrine/AuditLog.orm.xml b/src/Resources/config/doctrine/AuditLog.orm.xml index 1d8450b..1261d24 100644 --- a/src/Resources/config/doctrine/AuditLog.orm.xml +++ b/src/Resources/config/doctrine/AuditLog.orm.xml @@ -7,7 +7,7 @@ - + From 0366975b70bd36119ed9fff830f06a25aa9569a6 Mon Sep 17 00:00:00 2001 From: Andrew Cornforth Date: Thu, 10 Mar 2022 16:43:50 +0000 Subject: [PATCH 7/8] don't pass null to substr() --- src/EventSubscriber/AuditSubscriber.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EventSubscriber/AuditSubscriber.php b/src/EventSubscriber/AuditSubscriber.php index 1864cce..937b385 100644 --- a/src/EventSubscriber/AuditSubscriber.php +++ b/src/EventSubscriber/AuditSubscriber.php @@ -362,7 +362,8 @@ protected function audit(EntityManager $em, array $data) // Log the ip address and User Agent String. $mainRequest = $this->requestStack->getMainRequest(); $data['ip'] = $this->logIp && $mainRequest ? $mainRequest->getClientIp() : null; - $data['userAgent'] = $this->logUserAgent && $mainRequest ? substr($mainRequest->headers->get('User-Agent'), 0, $this->truncateUserAgent) : null; + $userAgent = $mainRequest ? $mainRequest->headers->get('User-Agent') : null; + $data['userAgent'] = $this->logUserAgent && $userAgent ? substr($userAgent, 0, $this->truncateUserAgent) : null; $meta = $em->getClassMetadata(AuditLog::class); $data['loggedAt'] = new \DateTime(); From ed51724bd914c1cc2f1d19e2b47edaa19ed0a965 Mon Sep 17 00:00:00 2001 From: Andrew Cornforth Date: Tue, 15 Mar 2022 16:05:40 +0000 Subject: [PATCH 8/8] test increment strategy --- src/Resources/config/doctrine/Association.orm.xml | 2 +- src/Resources/config/doctrine/AuditLog.orm.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Resources/config/doctrine/Association.orm.xml b/src/Resources/config/doctrine/Association.orm.xml index fce2631..42a72c2 100644 --- a/src/Resources/config/doctrine/Association.orm.xml +++ b/src/Resources/config/doctrine/Association.orm.xml @@ -5,7 +5,7 @@ https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - + diff --git a/src/Resources/config/doctrine/AuditLog.orm.xml b/src/Resources/config/doctrine/AuditLog.orm.xml index 1261d24..e45c4ef 100644 --- a/src/Resources/config/doctrine/AuditLog.orm.xml +++ b/src/Resources/config/doctrine/AuditLog.orm.xml @@ -5,7 +5,7 @@ https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - +