Skip to content

Commit

Permalink
Persist device and platform in NoSQL database (#635)
Browse files Browse the repository at this point in the history
  • Loading branch information
imendes12 authored Feb 4, 2025
1 parent a87ed15 commit 2bea9a2
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 13 deletions.
1 change: 1 addition & 0 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
'increment_style' => ['style' => 'post'],
'global_namespace_import' => true,
'new_with_parentheses' => false,
'class_definition' => ['space_before_parenthesis' => true],
])
->setFinder($finder);
4 changes: 2 additions & 2 deletions cypress/e2e/admin/initiative/initiative-timeline.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ describe('Painel de Controle - Página de timeline das Iniciativas', () => {
});

it('Garante que a página de timeline da Iniciativa existe', () => {
cy.contains('Timeline').click({force: true});
cy.get('[data-cy="f0774ecd-4860-4b8c-9607-32090dc31f71"]').contains('Timeline').click({force: true});

cy.get('h2').contains('Iniciativa - Baião de Dez - Timeline').should('be.visible');
cy.get('h2').contains('Iniciativa - Vozes do Sertão - Timeline').should('be.visible');
cy.get('.d-flex > div > .btn').contains('Voltar').should('be.visible');

cy.get('tr > :nth-child(1) > a').contains('A entidade foi criada').should('be.visible');
Expand Down
50 changes: 42 additions & 8 deletions src/EventListener/Audit/AbstractAuditListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use App\Entity\User;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

abstract class AbstractAuditListener
Expand All @@ -39,21 +40,24 @@ public function __construct(

protected function getDevice(): string
{
return self::UNKNOWN;
}
$request = $this->requestStack->getCurrentRequest();

protected function getPlatform(): string
{
if (null === $this->requestStack->getCurrentRequest()) {
if (null === $request) {
return self::UNKNOWN;
}

return $this->isApiRequest() ? 'api' : 'web';
return $this->getBrowser($request);
}

protected function isApiRequest(): ?bool
protected function getPlatform(): string
{
return str_starts_with($this->requestStack->getCurrentRequest()->getPathInfo(), '/api');
$request = $this->requestStack->getCurrentRequest();

if (null === $request) {
return self::UNKNOWN;
}

return $this->getOperationalSystem($request);
}

protected function resolveNameDocument(string $class): ?string
Expand All @@ -71,4 +75,34 @@ protected function resolveNameDocument(string $class): ?string
default => null,
};
}

private function getBrowser(Request $request): string
{
$user_agent = $request->server->get('HTTP_USER_AGENT');

return match (1) {
preg_match('/msie/i', $user_agent) => 'Internet explorer',
preg_match('/firefox/i', $user_agent) => 'Firefox',
preg_match('/opr/i', $user_agent) => 'Opera',
preg_match('/edg/i', $user_agent) => 'Edge',
preg_match('/chrome/i', $user_agent) => 'Chrome',
preg_match('/safari/i', $user_agent) => 'Safari',
preg_match('/mobile/i', $user_agent) => 'Mobile browser',
default => self::UNKNOWN,
};
}

private function getOperationalSystem(Request $request): string
{
$user_agent = $request->server->get('HTTP_USER_AGENT');

return match (1) {
preg_match('/android/i', $user_agent) => 'Android',
preg_match('/linux/i', $user_agent) => 'Linux',
preg_match('/windows|win32/i', $user_agent) => 'Windows',
preg_match('/macintosh|mac os x/i', $user_agent) => 'MacOS',
preg_match('/iphone|ipad/i', $user_agent) => 'iOS',
default => self::UNKNOWN,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function testAuditLoginFailedInvalidCredentials(): void
$user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $requestBody['username']]);

$authTimeline = $this->documentManager->getRepository(AuthTimeline::class)
->findOneBy(['action' => 'login failure', 'platform' => 'api', 'userId' => $user->getId()->toRfc4122()]);
->findOneBy(['action' => 'login failure', 'platform' => 'unknown', 'userId' => $user->getId()->toRfc4122()]);

self::assertNotNull($authTimeline, 'Audit document not found');

Expand Down Expand Up @@ -95,7 +95,7 @@ public function testAuditLoginFailedForUserNotFound(): void
]);

$authTimeline = $this->documentManager->getRepository(AuthTimeline::class)
->findOneBy(['action' => 'user not found', 'platform' => 'api', 'userId' => null]);
->findOneBy(['action' => 'user not found', 'platform' => 'unknown', 'userId' => null]);

self::assertNotNull($authTimeline, 'Audit document not found');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function testAuditLoginSuccess(): void
$user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $requestBody['username']]);

$authTimeline = $this->documentManager->getRepository(AuthTimeline::class)
->findOneBy(['action' => 'login success', 'platform' => 'api', 'userId' => $user->getId()->toRfc4122()]);
->findOneBy(['action' => 'login success', 'platform' => 'unknown', 'userId' => $user->getId()->toRfc4122()]);

self::assertNotNull($authTimeline, 'Auth document not found');

Expand Down
60 changes: 60 additions & 0 deletions tests/Unit/EventListener/Audit/AbstractAuditListenerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace App\Tests\Unit\EventListener\Audit;

use App\EventListener\Audit\AbstractAuditListener;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;

final class AbstractAuditListenerTest extends KernelTestCase
{
public const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';

private AbstractAuditListener $auditListener;

protected function setUp(): void
{
parent::setUp();

$requestStack = $this->createMock(RequestStack::class);
$requestStack->expects(self::once())
->method('getCurrentRequest')
->willReturn(
new Request(server: [
'HTTP_USER_AGENT' => self::USER_AGENT,
])
);

$documentManager = $this->createMock(DocumentManager::class);
$security = $this->createMock(Security::class);

$auditListenerConcrete = new class ($documentManager, $requestStack, $security) extends AbstractAuditListener {
public function getDevice(): string
{
return parent::getDevice();
}

public function getPlatform(): string
{
return parent::getPlatform();
}
};

$this->auditListener = new $auditListenerConcrete($documentManager, $requestStack, $security);
}

public function testGetDevice(): void
{
$this->assertSame('Chrome', $this->auditListener->getDevice());
}

public function testGetPlatform(): void
{
$this->assertSame('Windows', $this->auditListener->getPlatform());
}
}

0 comments on commit 2bea9a2

Please sign in to comment.