src/Cms/LogBundle/Service/LoggingService.php line 209

Open in your IDE?
  1. <?php
  2. namespace Cms\LogBundle\Service;
  3. use Cms\CoreBundle\Model\Interfaces\Identifiable\IdentifiableInterface;
  4. use Cms\CoreBundle\Model\Interfaces\Loggable\LoggableInterface;
  5. use Cms\CoreBundle\Service\ContextManager;
  6. use Cms\CoreBundle\Util\Doctrine\EntityManager;
  7. use Cms\LogBundle\Entity\ActivityLog;
  8. use Doctrine\Common\Util\ClassUtils;
  9. use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\RequestStack;
  13. use Symfony\Component\HttpKernel\KernelEvents;
  14. use Symfony\Component\Security\Http\FirewallMapInterface;
  15. final class LoggingService implements EventSubscriberInterface
  16. {
  17.     /**
  18.      * @var array
  19.      */
  20.     private $logs = [];
  21.     /**
  22.      * @var array|null
  23.      */
  24.     private $backup null;
  25.     /**
  26.      * @var EntityManager
  27.      */
  28.     private $em;
  29.     /**
  30.      * @var RequestStack
  31.      */
  32.     private $requestStack;
  33.     /**
  34.      * @var ContextManager
  35.      */
  36.     private $contextManager;
  37.     /**
  38.      * @var FirewallMapInterface
  39.      */
  40.     private FirewallMapInterface $firewallMap;
  41.     /**
  42.      * @param EntityManager $em
  43.      * @param RequestStack $requestStack
  44.      * @param ContextManager $contextManager
  45.      * @param FirewallMap $firewallMap
  46.      */
  47.     public function __construct(EntityManager $emRequestStack $requestStackContextManager $contextManagerFirewallMapInterface $firewallMap)
  48.     {
  49.         $this->em $em;
  50.         $this->requestStack $requestStack;
  51.         $this->contextManager $contextManager;
  52.         $this->firewallMap $firewallMap;
  53.     }
  54.     /**
  55.      * {@inheritdoc}
  56.      */
  57.     public static function getSubscribedEvents(): array
  58.     {
  59.         return [
  60.             KernelEvents::TERMINATE => ['onKernelTerminate'],
  61.         ];
  62.     }
  63.     /**
  64.      * @param array $logs
  65.      */
  66.     public function createLogs(array $logs)
  67.     {
  68.         foreach ($logs as $log) {
  69.             if ( ! is_array($log)) {
  70.                 $log = [
  71.                     $log,
  72.                 ];
  73.             }
  74.             call_user_func_array([$this'createLog'], $log);
  75.         }
  76.     }
  77.     /**
  78.      * @param IdentifiableInterface $object
  79.      * @param int $objectId Default null
  80.      */
  81.     public function createLog($object$objectId null)
  82.     {
  83.         // create a new log object
  84.         $entry = new ActivityLog();
  85.         // obtain ip from master request
  86.         $ip $this->requestStack->getMasterRequest()->headers->get('X-FORWARDED-FOR');
  87.         if (empty($ip)) {
  88.             $ip $this->requestStack->getMasterRequest()->getClientIp();
  89.         }
  90.         $entry->setIp($ip);
  91.         // get the action
  92.         $entry->setAction(
  93.             $this->requestStack->getCurrentRequest()->get('_controller')
  94.         );
  95.         // assign id, if object has no id then use provided objectId
  96.         $entry->setObjectId($object->getId());
  97.         if (empty($entry->getObjectId())) {
  98.             $entry->setObjectId($objectId);
  99.         }
  100.         // attach the user currently logged in, could be impersonated
  101.         if ( ! empty($this->contextManager->getGlobalContext()->getEffectiveAccount())) {
  102.             $entry->setAccount(
  103.                 $this->contextManager->getGlobalContext()->getEffectiveAccount()
  104.             );
  105.         }
  106.         // attach the real, logged in account
  107.         if ( ! empty($this->contextManager->getGlobalContext()->getAuthenticatedAccount())) {
  108.             $entry->setRealAccount(
  109.                 $this->contextManager->getGlobalContext()->getAuthenticatedAccount()
  110.             );
  111.         }
  112.         // attach class name
  113.         $entry->setObjectClass(ClassUtils::getClass($object));
  114.         // log any extra details
  115.         if ($object instanceof LoggableInterface) {
  116.             if ( ! empty($object->getLoggableDetails())) {
  117.                 $entry->setDetails(
  118.                     array_merge(
  119.                         $object->getLoggableDetails(),
  120.                         [
  121.                             // TODO: might want to do this a different way
  122.                             'blame' => ( ! empty($this->contextManager->getGlobalContext()->getImpersonatedAccount()))
  123.                                 ? [
  124.                                     'impersonated' => [
  125.                                         'id' => $this->contextManager->getGlobalContext()->getImpersonatedAccount(
  126.                                         )->getId(),
  127.                                         'email' => $this->contextManager->getGlobalContext()->getImpersonatedAccount(
  128.                                         )->getEmail(),
  129.                                         'name' => $this->contextManager->getGlobalContext()->getImpersonatedAccount(
  130.                                         )->getDisplayName(),
  131.                                     ],
  132.                                     'authenticated' => [
  133.                                         'id' => $this->contextManager->getGlobalContext()->getAuthenticatedAccount(
  134.                                         )->getId(),
  135.                                         'email' => $this->contextManager->getGlobalContext()->getAuthenticatedAccount(
  136.                                         )->getEmail(),
  137.                                         'name' => $this->contextManager->getGlobalContext()->getAuthenticatedAccount(
  138.                                         )->getDisplayName(),
  139.                                     ],
  140.                                 ]
  141.                                 : [
  142.                                     'authenticated' => [
  143.                                         'id' => $this->contextManager->getGlobalContext()->getAuthenticatedAccount(
  144.                                         )->getId(),
  145.                                         'email' => $this->contextManager->getGlobalContext()->getAuthenticatedAccount(
  146.                                         )->getEmail(),
  147.                                         'name' => $this->contextManager->getGlobalContext()->getAuthenticatedAccount(
  148.                                         )->getDisplayName(),
  149.                                     ],
  150.                                 ]
  151.                             ,
  152.                         ]
  153.                     )
  154.                 );
  155.             }
  156.         }
  157.         $request $this->requestStack->getCurrentRequest();
  158.         if ($request instanceof Request) {
  159.             $firewallName $this->firewallMap->getFirewallConfig($request)?->getName();
  160.             if (in_array($firewallName, ['portal_api''portal_admin_api'], true)) {
  161.                 $entry->setAuthType(ActivityLog::AUTH_TYPE__API);
  162.             } elseif ($firewallName === 'dashboard') {
  163.                 $entry->setAuthType(ActivityLog::AUTH_TYPE__WEB);
  164.             }
  165.         }
  166.         // we are spooling
  167.         $this->logs[] = $entry;
  168.     }
  169.     public function backup()
  170.     {
  171.         $this->backup $this->logs;
  172.     }
  173.     public function restore()
  174.     {
  175.         if ( ! is_array($this->backup)) {
  176.             throw new \Exception();
  177.         }
  178.         $this->logs $this->backup;
  179.     }
  180.     public function commit()
  181.     {
  182.         $this->backup null;
  183.     }
  184.     public function onKernelTerminate()
  185.     {
  186.         // see if we have any logs to save
  187.         if ( ! empty($this->logs)) {
  188.             // save all to db
  189.             $this->em->saveAll($this->logs);
  190.             // clear
  191.             $this->logs = [];
  192.         }
  193.     }
  194. }