SecurityHistoryManager::hasEventOccurredWithin()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
c 1
b 0
f 0
dl 0
loc 18
rs 9.7998
cc 1
nc 1
nop 3
1
<?php
2
3
namespace ProjetNormandie\UserBundle\Security;
4
5
use Doctrine\ORM\EntityManagerInterface;
6
use ProjetNormandie\UserBundle\Entity\User;
7
use ProjetNormandie\UserBundle\Entity\SecurityEvent;
8
use ProjetNormandie\UserBundle\Security\Event\SecurityEventTypeEnum;
9
use Symfony\Component\HttpFoundation\RequestStack;
10
11
/**
12
 * Manages security event history for auditing and tracking security-related actions
13
 */
14
class SecurityHistoryManager
15
{
16
    public function __construct(
17
        private readonly EntityManagerInterface $entityManager,
18
        private readonly RequestStack $requestStack,
19
    ) {
20
    }
21
22
    /**
23
     * Record a security event for a user
24
     *
25
     * @param User $user The user
26
     * @param SecurityEventTypeEnum $eventType Type of security event (e.g., password_change, login, login_failure)
27
     * @param array $data Additional data to store with the event
28
     * @return SecurityEvent The created event
29
     */
30
    public function recordEvent(User $user, SecurityEventTypeEnum $eventType, array $data = []): SecurityEvent
31
    {
32
        // Record password change in security history
33
        $request = $this->requestStack->getCurrentRequest();
34
        $ip = $request ? $request->getClientIp() : 'unknown';
35
        $userAgent = $request ? $request->headers->get('User-Agent') : 'unknown';
36
37
        // Create a new security event
38
        $event = new SecurityEvent();
39
        $event->setUser($user);
40
        $event->setEventType($eventType->getCode());
41
        $event->setEventData($data);
42
        $event->setCreatedAt(new \DateTime());
43
        $event->setIpAddress($ip);
44
        $event->setUserAgent($userAgent);
45
46
        // Save the event
47
        $this->entityManager->persist($event);
48
        $this->entityManager->flush();
49
50
        return $event;
51
    }
52
53
    /**
54
     * Get recent security events for a user
55
     *
56
     * @param User $user The user
57
     * @param int $limit Maximum number of events to return
58
     * @return array List of security events
59
     */
60
    public function getRecentEvents(User $user, int $limit = 10): array
61
    {
62
        return $this->entityManager->getRepository(SecurityEvent::class)
63
            ->createQueryBuilder('e')
64
            ->where('e.user = :user')
65
            ->setParameter('user', $user)
66
            ->orderBy('e.createdAt', 'DESC')
67
            ->setMaxResults($limit)
68
            ->getQuery()
69
            ->getResult();
70
    }
71
72
    /**
73
     * Get events of a specific type for a user
74
     *
75
     * @param User $user The user
76
     * @param string $eventType Type of security event
77
     * @param int $limit Maximum number of events to return
78
     * @return array List of security events
79
     */
80
    public function getEventsByType(User $user, string $eventType, int $limit = 10): array
81
    {
82
        return $this->entityManager->getRepository(SecurityEvent::class)
83
            ->createQueryBuilder('e')
84
            ->where('e.user = :user')
85
            ->andWhere('e.eventType = :eventType')
86
            ->setParameter('user', $user)
87
            ->setParameter('eventType', $eventType)
88
            ->orderBy('e.createdAt', 'DESC')
89
            ->setMaxResults($limit)
90
            ->getQuery()
91
            ->getResult();
92
    }
93
94
    /**
95
     * Check if a specific event has occurred for a user within a time period
96
     *
97
     * @param User $user The user
98
     * @param string $eventType Type of security event
99
     * @param \DateInterval $interval Time interval to check
100
     * @return bool Whether the event occurred
101
     */
102
    public function hasEventOccurredWithin(User $user, string $eventType, \DateInterval $interval): bool
103
    {
104
        $date = new \DateTime();
105
        $date->sub($interval);
106
107
        $count = $this->entityManager->getRepository(SecurityEvent::class)
108
            ->createQueryBuilder('e')
109
            ->select('COUNT(e.id)')
110
            ->where('e.user = :user')
111
            ->andWhere('e.eventType = :eventType')
112
            ->andWhere('e.createdAt >= :date')
113
            ->setParameter('user', $user)
114
            ->setParameter('eventType', $eventType)
115
            ->setParameter('date', $date)
116
            ->getQuery()
117
            ->getSingleScalarResult();
118
119
        return $count > 0;
120
    }
121
}
122