Skip to content

Commit

Permalink
Merge pull request #4 from ntidev/audit-time-line-api
Browse files Browse the repository at this point in the history
Adding controllers, services and repository for the api
  • Loading branch information
bvisonl authored Sep 25, 2019
2 parents aeb85cc + 96911f8 commit af2e047
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 7 deletions.
39 changes: 39 additions & 0 deletions src/DataDog/AuditBundle/Controller/AuditLogController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace DataDog\AuditBundle\Controller;

use AppBundle\Util\DataTable\DataTableOptionsProcessor;
use AppBundle\Util\Rest\DataTableRestResponse;
use AppBundle\Util\Rest\RestResponse;
use DataDog\AuditBundle\Service\AuditLogService;
use JMS\Serializer\SerializationContext;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;

/**
* Class AuditLogController
* @package DataDog\AuditBundle\Controller
* @Route("/")
*/
class AuditLogController extends Controller {

// REST Methods
/**
* @Route("/rest/getAll", name="nti_rest_audit_log_get_all", options={"expose"=true}, methods={"GET"})
* @param Request $request
* @return DataTableRestResponse
*/
public function getAllAction(Request $request) {
$options = DataTableOptionsProcessor::GetOptions($request);
$result = $this->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);
}

}
39 changes: 32 additions & 7 deletions src/DataDog/AuditBundle/EventSubscriber/AuditSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -380,16 +383,16 @@ 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,
];
}
}
return $diff;
}

protected function assoc(EntityManager $em, $association = null)
protected function assoc(EntityManager $em, $association = null, $diff = false)
{
if (null === $association) {
return null;
Expand All @@ -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();
Expand All @@ -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'):
Expand Down Expand Up @@ -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;
}
}
147 changes: 147 additions & 0 deletions src/DataDog/AuditBundle/Repository/AuditLogRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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"]),
)
);

}
}
16 changes: 16 additions & 0 deletions src/DataDog/AuditBundle/Resources/config/services.yml
Original file line number Diff line number Diff line change
@@ -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"]
Expand Down
39 changes: 39 additions & 0 deletions src/DataDog/AuditBundle/Service/AuditLogService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace DataDog\AuditBundle\Service;

use DataDog\AuditBundle\Entity\AuditLog;
use PHPUnit\Runner\Exception;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Class AuditLogService
* @package DataDog\AuditBundle\Service
*/
class AuditLogService {

/** @var ContainerInterface $container */
private $container;

/**
* AuditLogService constructor.
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->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;
}

}

0 comments on commit af2e047

Please sign in to comment.