AccessControlListenerTest   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 191
Duplicated Lines 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 9
eloc 143
c 1
b 1
f 0
dl 0
loc 191
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A testWhenAccessControlIsDisabled() 0 14 1
A testWithEmptyTokenStorage() 0 20 1
A testWithIncorrectAccessForUser() 0 20 1
A testWithCorrectAccessForUser() 0 19 1
A testWithInvalidTokenStorage() 0 24 1
A testWithNonSecureRoute() 0 18 1
A testWithIncorrectAccessForUserAndCustomResponse() 0 28 1
A mockTokenStorage() 0 16 1
A mockRequestEvent() 0 14 1
1
<?php
2
3
namespace Sil\RouteSecurityBundle\Tests\Listener;
4
5
use PHPUnit\Framework\TestCase;
6
use Sil\RouteSecurityBundle\Event\AccessDeniedToRouteEvent;
7
use Sil\RouteSecurityBundle\Exception\LogicException;
8
use Sil\RouteSecurityBundle\Listener\AccessControlListener;
9
use Sil\RouteSecurityBundle\Security\AccessControl;
10
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
11
use Symfony\Component\HttpFoundation\Response;
12
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
13
use Symfony\Component\HttpFoundation\ParameterBag;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\HttpKernel\Event\RequestEvent;
16
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
17
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
18
use Symfony\Component\Security\Core\User\UserInterface;
19
20
class AccessControlListenerTest extends TestCase
21
{
22
    public function testWhenAccessControlIsDisabled()
23
    {
24
        $accessControl = $this->createMock(AccessControl::class);
25
        $accessControl
26
            ->method('isEnable')
27
            ->willReturn(false);
28
        $tokenStorage = $this->createMock(TokenStorageInterface::class);
29
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
30
        $event = $this->mockRequestEvent();
31
32
        $accessControlListener = new AccessControlListener($accessControl, $tokenStorage, $eventDispatcher);
33
        $accessControlListener->onKernelRequest($event);
34
35
        $this->assertNull($accessControlListener->onKernelRequest($event));
36
    }
37
38
    public function testWithNonSecureRoute()
39
    {
40
        $accessControl = $this->createMock(AccessControl::class);
41
        $accessControl
42
            ->method('isEnable')
43
            ->willReturn(true);
44
        $accessControl
45
            ->method('isRouteSecure')
46
            ->with('non_secure_route')
47
            ->willReturn(false);
48
        $tokenStorage = $this->createMock(TokenStorageInterface::class);
49
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
50
        $event = $this->mockRequestEvent('non_secure_route');
51
52
        $accessControlListener = new AccessControlListener($accessControl, $tokenStorage, $eventDispatcher);
53
        $accessControlListener->onKernelRequest($event);
54
55
        $this->assertNull($accessControlListener->onKernelRequest($event));
56
    }
57
58
    public function testWithEmptyTokenStorage()
59
    {
60
        $accessControl = $this->createMock(AccessControl::class);
61
        $accessControl
62
            ->method('isEnable')
63
            ->willReturn(true);
64
        $accessControl
65
            ->method('isRouteSecure')
66
            ->with('secure_route')
67
            ->willReturn(true);
68
        $tokenStorage = $this->createMock(TokenStorageInterface::class);
69
        $tokenStorage
70
            ->method('getToken')
71
            ->willReturn(null);
72
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
73
        $event = $this->mockRequestEvent('secure_route');
74
75
        $accessControlListener = new AccessControlListener($accessControl, $tokenStorage, $eventDispatcher);
76
        $this->expectException(LogicException::class);
77
        $accessControlListener->onKernelRequest($event);
78
    }
79
80
    public function testWithInvalidTokenStorage()
81
    {
82
        $accessControl = $this->createMock(AccessControl::class);
83
        $accessControl
84
            ->method('isEnable')
85
            ->willReturn(true);
86
        $accessControl
87
            ->method('isRouteSecure')
88
            ->with('secure_route')
89
            ->willReturn(true);
90
        $token = $this->createMock(TokenInterface::class);
91
        $token
92
            ->method('getUser')
93
            ->willReturn('invalid user type');
94
        $tokenStorage = $this->createMock(TokenStorageInterface::class);
95
        $tokenStorage
96
            ->method('getToken')
97
            ->willReturn($token);
98
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
99
        $event = $this->mockRequestEvent('secure_route');
100
101
        $accessControlListener = new AccessControlListener($accessControl, $tokenStorage, $eventDispatcher);
102
        $this->expectException(LogicException::class);
103
        $accessControlListener->onKernelRequest($event);
104
    }
105
106
    public function testWithCorrectAccessForUser()
107
    {
108
        $accessControl = $this->createMock(AccessControl::class);
109
        $accessControl
110
            ->method('isEnable')
111
            ->willReturn(true);
112
        $accessControl
113
            ->method('isRouteSecure')
114
            ->with('secure_route')
115
            ->willReturn(true);
116
        $accessControl
117
            ->method('hasUserAccessToRoute')
118
            ->willReturn(true);
119
        $tokenStorage = $this->mockTokenStorage();
120
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
121
        $event = $this->mockRequestEvent('secure_route');
122
123
        $accessControlListener = new AccessControlListener($accessControl, $tokenStorage, $eventDispatcher);
124
        $this->assertNull($accessControlListener->onKernelRequest($event));
125
    }
126
127
    public function testWithIncorrectAccessForUser()
128
    {
129
        $accessControl = $this->createMock(AccessControl::class);
130
        $accessControl
131
            ->method('isEnable')
132
            ->willReturn(true);
133
        $accessControl
134
            ->method('isRouteSecure')
135
            ->with('secure_route')
136
            ->willReturn(true);
137
        $accessControl
138
            ->method('hasUserAccessToRoute')
139
            ->willReturn(false);
140
        $tokenStorage = $this->mockTokenStorage();
141
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
142
        $event = $this->mockRequestEvent('secure_route');
143
144
        $accessControlListener = new AccessControlListener($accessControl, $tokenStorage, $eventDispatcher);
145
        $this->expectException(AccessDeniedException::class);
146
        $this->assertNull($accessControlListener->onKernelRequest($event));
147
    }
148
149
    public function testWithIncorrectAccessForUserAndCustomResponse()
150
    {
151
        $accessControl = $this->createMock(AccessControl::class);
152
        $accessControl
153
            ->method('isEnable')
154
            ->willReturn(true);
155
        $accessControl
156
            ->method('isRouteSecure')
157
            ->with('secure_route')
158
            ->willReturn(true);
159
        $accessControl
160
            ->method('hasUserAccessToRoute')
161
            ->willReturn(false);
162
        $tokenStorage = $this->mockTokenStorage();
163
        $event = $this->mockRequestEvent('secure_route');
164
        $eventDispatcher = $this->createMock(EventDispatcherInterface::class);
165
        $response = new Response('Custom Response');
166
        $eventDispatcher
167
            ->expects($this->once())
168
            ->method('dispatch')
169
            ->with($this->isInstanceOf(AccessDeniedToRouteEvent::class), AccessDeniedToRouteEvent::ON_ACCESS_DENIED_TO_ROUTE)
170
            ->will($this->returnCallback(function ($access_denied_event, $name) use ($response) {
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

170
            ->will($this->returnCallback(function ($access_denied_event, /** @scrutinizer ignore-unused */ $name) use ($response) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
171
                $access_denied_event->setResponse($response);
172
                return $access_denied_event;
173
            }));
174
175
        $accessControlListener = new AccessControlListener($accessControl, $tokenStorage, $eventDispatcher);
176
        $this->assertInstanceOf(RequestEvent::class, $accessControlListener->onKernelRequest($event));
177
    }
178
179
    protected function mockRequestEvent($route = null)
180
    {
181
        $event = $this->createMock(RequestEvent::class);
182
        $request = $this->createMock(Request::class);
183
        $parameterBag = $this->createMock(ParameterBag::class);
184
        $parameterBag
185
            ->method('get')
186
            ->with('_route')
187
            ->willReturn($route);
188
189
        $request->attributes = $parameterBag;
0 ignored issues
show
Bug introduced by
Accessing attributes on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
190
        $event->method('getRequest')->willReturn($request);
191
192
        return $event;
193
    }
194
195
    protected function mockTokenStorage($roles = [])
196
    {
197
        $tokenStorage = $this->createMock(TokenStorageInterface::class);
198
        $user = $this->createMock(UserInterface::class);
199
        $user
200
            ->method('getRoles')
201
            ->willReturn($roles);
202
        $token = $this->createMock(TokenInterface::class);
203
        $token
204
            ->method('getUser')
205
            ->willReturn($user);
206
        $tokenStorage
207
            ->method('getToken')
208
            ->willReturn($token);
209
210
        return $tokenStorage;
211
    }
212
}
213