From d42e80de5275a0145e103d5d9e2d6e3c32f6197d Mon Sep 17 00:00:00 2001 From: Ivan Mendoza Date: Mon, 9 Sep 2019 15:37:34 +0000 Subject: [PATCH 1/3] Adding controllers, services and repository for the api --- .../Controller/AuditLogController.php | 39 +++++ .../Repository/AuditLogRepository.php | 147 ++++++++++++++++++ .../AuditBundle/Resources/config/services.yml | 16 ++ .../AuditBundle/Service/AuditLogService.php | 39 +++++ 4 files changed, 241 insertions(+) create mode 100755 src/DataDog/AuditBundle/Controller/AuditLogController.php create mode 100755 src/DataDog/AuditBundle/Service/AuditLogService.php diff --git a/src/DataDog/AuditBundle/Controller/AuditLogController.php b/src/DataDog/AuditBundle/Controller/AuditLogController.php new file mode 100755 index 0000000..a669869 --- /dev/null +++ b/src/DataDog/AuditBundle/Controller/AuditLogController.php @@ -0,0 +1,39 @@ +get(AuditLogService::class)->getAll($options); + $logs = json_decode($this->container->get('jms_serializer')->serialize($result["data"], 'json') ,true); + $result["data"] = $logs; + return new DataTableRestResponse($result); + } + +} \ No newline at end of file diff --git a/src/DataDog/AuditBundle/Repository/AuditLogRepository.php b/src/DataDog/AuditBundle/Repository/AuditLogRepository.php index aaa24a0..b54f1b5 100755 --- a/src/DataDog/AuditBundle/Repository/AuditLogRepository.php +++ b/src/DataDog/AuditBundle/Repository/AuditLogRepository.php @@ -6,6 +6,8 @@ class AuditLogRepository extends \Doctrine\ORM\EntityRepository { + const MAX_RESULTS = 1000; + public function findAudit(\DateTime $dateStart, \DateTime $dateEnd){ $qb = $this->createQueryBuilder('a'); $qb ->select('a') @@ -16,4 +18,149 @@ public function findAudit(\DateTime $dateStart, \DateTime $dateEnd){ return $qb->getQuery()->getResult(); } + + /** + * Get a list of AuditLogs filtering by $options + * + * @param $options + * @return array + */ + public function findByOptions($options = array()) { + $options = array( + "draw" => isset($options["draw"]) ? $options["draw"] : 1, + "search" => isset($options["search"]) ? $options["search"] : "", + "sortBy" => isset($options["sortBy"]) ? $options["sortBy"] : "a.loggedAt", + "orderBy" => (isset($options["orderBy"]) && in_array(strtolower($options["orderBy"]), array("desc", "asc"))) ? $options["orderBy"] : "asc", + "start" => (isset($options["start"]) && $options["start"] >= 0) ? $options["start"] : 0, + "limit" => (isset($options["limit"]) && $options["limit"] < self::MAX_RESULTS) ? $options["limit"] : ( (isset($options["length"]) && $options["length"] < self::MAX_RESULTS) ? $options["length"] : self::MAX_RESULTS ), + "filters" => (isset($options["filters"]) && count($options["filters"]) > 0) ? $options["filters"] : array(), + "partnerId" => (isset($options["partnerId"])) ? $options["partnerId"] : null, + "partnerAuthorized" => (isset($options["partnerAuthorized"])) ? true : false, + "_paginate" => (isset($options["_paginate"])) ? $options["_paginate"] : true, + ); + + $qb = $this->createQueryBuilder('a') + ->join('DataDog\AuditBundle\Entity\Association', 'aa', 'WITH', 'aa = a.source'); + + // Totals Count + $totalLogsQb = clone $qb; + $totalLogsQb->select('COUNT(a.id)'); + $totalCountQuery = $totalLogsQb->getQuery(); + + try { + $totalLogsCount = $totalCountQuery->getSingleScalarResult(); + } catch (NoResultException $e) { + $totalLogsCount = 0; + } catch (NonUniqueResultException $e) { + $totalLogsCount = 0; + } + + // Apply filters + foreach($options["filters"] as $field => $search) { + if($field == "" || $search == "") continue; + switch($field) { + case "table": + switch($search) { + case "all": + $qb->andWhere($qb->expr()->andX( + $qb->expr()->neq('a.tbl', $qb->expr()->literal("audit_request")), + $qb->expr()->neq('a.tbl', $qb->expr()->literal("craue_config_setting")), + $qb->expr()->neq('a.tbl', $qb->expr()->literal("nti_sync_state")) + )); + break; + case "customer": + $qb->andWhere($qb->expr()->orX( + $qb->expr()->eq('a.tbl', $qb->expr()->literal("customer")), + $qb->expr()->eq('a.tbl', $qb->expr()->literal("customer_billing_profile")), + $qb->expr()->eq('a.tbl', $qb->expr()->literal("customer_product")), + $qb->expr()->eq('a.tbl', $qb->expr()->literal("customer_product_service_address")), + $qb->expr()->eq('a.tbl', $qb->expr()->literal("customer_tax_exemption_codes")) + )); + break; + case "invoice": + $qb->andWhere($qb->expr()->orX( + $qb->expr()->eq('a.tbl', $qb->expr()->literal("invoice")), + $qb->expr()->eq('a.tbl', $qb->expr()->literal("invoice_product")) + )); + break; + case "payment": + $qb->andWhere($qb->expr()->orX( + $qb->expr()->eq('a.tbl', $qb->expr()->literal("payment")), + $qb->expr()->eq('a.tbl', $qb->expr()->literal("payment_entry")) + )); + break; + case "users": + $qb->andWhere($qb->expr()->orX( + $qb->expr()->eq('a.tbl', $qb->expr()->literal("users")), + $qb->expr()->eq('a.tbl', $qb->expr()->literal("user_user_role_allowed")) + )); + break; + case "orders": + $qb->andWhere($qb->expr()->orX( + $qb->expr()->eq('a.tbl', $qb->expr()->literal("orders")), + $qb->expr()->eq('a.tbl', $qb->expr()->literal("order_product")) + )); + break; + default: + $qb->andWhere('a.tbl = :'.$field)->setParameter($field, $search); + break; + } + break; + case "dateStart": + $qb->andWhere('a.loggedAt >= :'.$field)->setParameter($field, $search); + break; + case "dateEnd": + $qb->andWhere('a.loggedAt <= :'.$field)->setParameter($field, $search); + break; + case "user": + $qb->andWhere('aa.fk = :'.$field)->setParameter($field, $search); + break; + case "action": + $qb->andWhere('a.action = :'.$field)->setParameter($field, $search); + break; + } + } + + // Manage SortBy + if(is_array($options["sortBy"])) { + foreach($options["sortBy"] as $sort) { + $qb->addOrderBy($sort, $options["orderBy"]); + } + } else { + $qb->orderBy($options["sortBy"], $options["orderBy"]); + } + + $countQb = clone $qb; + $countQb->select('COUNT(a.id)'); + $countQuery = $countQb->getQuery(); + + try { + $logsCount = $countQuery->getSingleScalarResult(); + } catch (NoResultException $e) { + $logsCount = 0; + } catch (NonUniqueResultException $e) { + $logsCount = 0; + } + + $resultQuery = $qb->getQuery(); + if(isset($options["_paginate"]) && $options["_paginate"] == true) { + if(null !== $options["limit"]) + $resultQuery->setMaxResults($options["limit"]); + if(null !== $options["start"]) + $resultQuery->setFirstResult($options["start"]); + } + + $logs = $resultQuery->getResult(); + + return array( + "draw" => intval( $options["draw"] ), + "recordsTotal" => $totalLogsCount, + "recordsFiltered" => $logsCount, + 'data' => $logs, + "pagination" => array( + "more" => $logsCount > ($options["start"] + $options["limit"]), + ) + ); + + } } \ No newline at end of file diff --git a/src/DataDog/AuditBundle/Resources/config/services.yml b/src/DataDog/AuditBundle/Resources/config/services.yml index aefd289..00131ed 100755 --- a/src/DataDog/AuditBundle/Resources/config/services.yml +++ b/src/DataDog/AuditBundle/Resources/config/services.yml @@ -1,4 +1,20 @@ services: + _defaults: + autowire: true + autoconfigure: true + public: false + + DataDog\: + resource: '../../../../../src/DataDog/*' + # you can exclude directories or files + # but if a service is unused, it's removed anyway + exclude: '../../../../../src/DataDog/AuditBundle/{Entity,Repository,Service}' + + # actual services to be tagged as public + DataDog\AuditBundle\Service\: + resource: '../../../../../src/DataDog/AuditBundle/Service' + public: true + datadog.event_subscriber.audit: class: DataDog\AuditBundle\EventSubscriber\AuditSubscriber arguments: ["@security.token_storage"] diff --git a/src/DataDog/AuditBundle/Service/AuditLogService.php b/src/DataDog/AuditBundle/Service/AuditLogService.php new file mode 100755 index 0000000..27c0ff7 --- /dev/null +++ b/src/DataDog/AuditBundle/Service/AuditLogService.php @@ -0,0 +1,39 @@ +container = $container; + } + + /** + * Get the list of AuditLogs based on the given $options + * + * @param $options + * @return mixed + */ + public function getAll($options = array()) { + $em = $this->container->get('doctrine')->getManager(); + $logs = $em->getRepository(AuditLog::class)->findByOptions($options); + return $logs; + } + +} \ No newline at end of file From ec28547b775fb32603b9998f93ef03140f67cdc9 Mon Sep 17 00:00:00 2001 From: Ivan Mendoza Date: Tue, 17 Sep 2019 12:19:58 +0000 Subject: [PATCH 2/3] Adding changes --- .../Controller/AuditLogController.php | 1 + .../EventSubscriber/AuditSubscriber.php | 39 +++++++++++++++---- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/DataDog/AuditBundle/Controller/AuditLogController.php b/src/DataDog/AuditBundle/Controller/AuditLogController.php index a669869..3aca425 100755 --- a/src/DataDog/AuditBundle/Controller/AuditLogController.php +++ b/src/DataDog/AuditBundle/Controller/AuditLogController.php @@ -33,6 +33,7 @@ public function getAllAction(Request $request) { $result = $this->get(AuditLogService::class)->getAll($options); $logs = json_decode($this->container->get('jms_serializer')->serialize($result["data"], 'json') ,true); $result["data"] = $logs; + // dd($result["data"]); return new DataTableRestResponse($result); } diff --git a/src/DataDog/AuditBundle/EventSubscriber/AuditSubscriber.php b/src/DataDog/AuditBundle/EventSubscriber/AuditSubscriber.php index 375ca85..471a9dc 100755 --- a/src/DataDog/AuditBundle/EventSubscriber/AuditSubscriber.php +++ b/src/DataDog/AuditBundle/EventSubscriber/AuditSubscriber.php @@ -6,6 +6,7 @@ use DataDog\AuditBundle\Entity\AuditLog; use DataDog\AuditBundle\Entity\Association; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\User\UserInterface; use Doctrine\DBAL\Types\Type; @@ -42,12 +43,14 @@ class AuditSubscriber implements EventSubscriber protected $assocInsertStmt; protected $auditInsertStmt; + protected $container; /** @var UserInterface */ protected $blameUser; - public function __construct(TokenStorage $securityTokenStorage) + public function __construct(TokenStorage $securityTokenStorage, ContainerInterface $container) { + $this->container = $container; $this->securityTokenStorage = $securityTokenStorage; } @@ -380,8 +383,8 @@ protected function diff(EntityManager $em, $entity, array $ch) $colName = $meta->getSingleAssociationJoinColumnName($fieldName); $assocMeta = $em->getClassMetadata($mapping['targetEntity']); $diff[$fieldName] = [ - 'old' => $this->assoc($em, $old), - 'new' => $this->assoc($em, $new), + 'old' => $this->assoc($em, $old, true), + 'new' => $this->assoc($em, $new, true), 'col' => $colName, ]; } @@ -389,7 +392,7 @@ protected function diff(EntityManager $em, $entity, array $ch) return $diff; } - protected function assoc(EntityManager $em, $association = null) + protected function assoc(EntityManager $em, $association = null, $diff = false) { if (null === $association) { return null; @@ -402,8 +405,8 @@ protected function assoc(EntityManager $em, $association = null) $meta = $em->getClassMetadata($meta); $res['tbl'] = $meta->table['name']; $em->getUnitOfWork()->initializeObject($association); // ensure that proxies are initialized - $res['fk'] = (string)$this->id($em, $association); - $res['label'] = $this->label($em, $association); + $res['fk'] = $this->getUser() != null && $diff == false ? $this->getUser()->getId() : (string)$this->id($em, $association); + $res['label'] = $this->label($em, $association, $diff); $res['createdOn'] = new \DateTime(); } catch (\Exception $e) { $res['fk'] = (string) $association->getId(); @@ -422,13 +425,15 @@ protected function typ($className) }, explode('\\', $className))); } - protected function label(EntityManager $em, $entity) + protected function label(EntityManager $em, $entity, $diff = false) { if (is_callable($this->labeler)) { return call_user_func($this->labeler, $entity); } $meta = $em->getClassMetadata(get_class($entity)); switch (true) { + case $this->getUser() != null && $diff == false: + return $this->getUser()->getUsername(); case $meta->hasField('title'): return $meta->getReflectionProperty('title')->getValue($entity); case $meta->hasField('name'): @@ -474,4 +479,24 @@ public function setBlameUser(UserInterface $user) { $this->blameUser = $user; } + + /** + * @return UserInterface|null + */ + public function getUser() + { + + if (null === $token = $this->container->get('security.token_storage')->getToken()) { + // no authentication information is available + return null; + } + + /** @var UserInterface $user */ + if (!is_object($user = $token->getUser())) { + // e.g. anonymous authentication + return null; + } + + return $user; + } } From 96911f883579690fc464ed0663bb6b29222d8ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Mendoza=20P=C3=A9rez?= Date: Tue, 17 Sep 2019 08:22:44 -0400 Subject: [PATCH 3/3] removing dd --- src/DataDog/AuditBundle/Controller/AuditLogController.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/DataDog/AuditBundle/Controller/AuditLogController.php b/src/DataDog/AuditBundle/Controller/AuditLogController.php index 3aca425..58b1322 100755 --- a/src/DataDog/AuditBundle/Controller/AuditLogController.php +++ b/src/DataDog/AuditBundle/Controller/AuditLogController.php @@ -33,8 +33,7 @@ public function getAllAction(Request $request) { $result = $this->get(AuditLogService::class)->getAll($options); $logs = json_decode($this->container->get('jms_serializer')->serialize($result["data"], 'json') ,true); $result["data"] = $logs; - // dd($result["data"]); return new DataTableRestResponse($result); } -} \ No newline at end of file +}