UserEventListener::onPostWrite()   A
last analyzed

Complexity

Conditions 6
Paths 2

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 10
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 15
ccs 0
cts 10
cp 0
crap 42
rs 9.2222
1
<?php
2
3
/*
4
 * This file is part of the Silverback API Components Bundle Project
5
 *
6
 * (c) Daniel West <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Silverback\ApiComponentsBundle\EventListener\Api;
15
16
use Silverback\ApiComponentsBundle\Entity\User\AbstractUser;
17
use Silverback\ApiComponentsBundle\Helper\User\UserMailer;
18
use Symfony\Bundle\SecurityBundle\Security;
19
use Symfony\Component\HttpFoundation\Request;
20
use Symfony\Component\HttpKernel\Event\RequestEvent;
21
use Symfony\Component\HttpKernel\Event\ViewEvent;
22
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
23
24
/**
25
 * @author Daniel West <[email protected]>
26
 */
27
class UserEventListener
28
{
29
    public function __construct(
30
        private readonly UserMailer $userMailer,
31
        private readonly Security $security
32
    ) {
33
    }
34
35
    /**
36
     * @description this is for the /me endpoint to ensure a user is found, supported and to set the id request attribute to be used in other services required for this route
37
     */
38
    public function onPreRead(RequestEvent $event): void
39
    {
40
        $request = $event->getRequest();
41
        $resourceClass = $request->attributes->get('_api_resource_class');
42
        if (
43
            empty($resourceClass)
44
            || !is_a($resourceClass, AbstractUser::class, true)
45
            || 'me' !== $request->attributes->get('_api_operation_name')
46
        ) {
47
            return;
48
        }
49
50
        $user = $this->security->getUser();
51
        if (!$user) {
52
            throw new AccessDeniedException('Access denied.');
53
        }
54
        if (!$user instanceof AbstractUser) {
55
            throw new AccessDeniedException('Access denied. User not supported.');
56
        }
57
58
        // the id cannot be trusted if the data was reloaded and the ID changed for any reason
59
        // technically the JWT token is still valid, but the id may not be found. So we don't
60
        // want to give a user the response of being unauthenticated when they are authenticated.
61
        // Could be abused and attacked. So we will want to refresh the user's jwt token
62
        $request->attributes->set('id', $user->getUsername());
63
    }
64
65
    public function onPostWrite(ViewEvent $event): void
66
    {
67
        $request = $event->getRequest();
68
        $data = $request->attributes->get('data');
69
        $previousData = $request->attributes->get('previous_data');
70
        if (
71
            empty($data)
72
            || !$data instanceof AbstractUser
73
            || $request->isMethod(Request::METHOD_GET)
74
            || $request->isMethod(Request::METHOD_DELETE)
75
        ) {
76
            return;
77
        }
78
79
        $this->postWrite($data, !$request->isMethod(Request::METHOD_POST) ? $previousData : null);
80
    }
81
82
    public function postWrite(AbstractUser $user, ?AbstractUser $previousUser): void
83
    {
84
        if (!$previousUser) {
85
            $this->userMailer->sendWelcomeEmail($user);
86
87
            return;
88
        }
89
90
        if (!$previousUser->isEnabled() && $user->isEnabled()) {
91
            $this->userMailer->sendUserEnabledEmail($user);
92
        }
93
94
        if ($previousUser->getUsername() !== $user->getUsername()) {
95
            $this->userMailer->sendUsernameChangedEmail($user);
96
        }
97
98
        if ($previousUser->getPassword() !== $user->getPassword()) {
99
            $this->userMailer->sendPasswordChangedEmail($user);
100
        }
101
102
        if (($token = $user->getEmailAddressVerifyToken()) && $token !== $previousUser->getEmailAddressVerifyToken()) {
103
            $this->userMailer->sendEmailVerifyEmail($user);
104
        }
105
106
        if (($token = $user->getNewEmailConfirmationToken()) && $token !== $previousUser->getNewEmailConfirmationToken()) {
107
            $this->userMailer->sendChangeEmailConfirmationEmail($user);
108
        }
109
    }
110
}
111