Passed
Pull Request — master (#257)
by Wilmer
23:33 queued 08:42
created

CsrfTest   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 54
dl 0
loc 134
rs 10
c 3
b 0
f 0
wmc 18
1
<?php
2
3
4
namespace Yiisoft\Yii\Web\Tests\Middleware;
5
6
use Nyholm\Psr7\Factory\Psr17Factory;
7
use Nyholm\Psr7\Response;
8
use Nyholm\Psr7\ServerRequest;
9
use PHPUnit\Framework\MockObject\MockObject;
10
use PHPUnit\Framework\TestCase;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Psr\Http\Server\RequestHandlerInterface;
13
use Yiisoft\Http\Method;
14
use Yiisoft\Security\Random;
15
use Yiisoft\Security\TokenMask;
16
use Yiisoft\Yii\Web\Middleware\Csrf;
17
use Yiisoft\Yii\Web\Session\SessionInterface;
18
19
final class CsrfTest extends TestCase
20
{
21
    private const PARAM_NAME = 'csrf';
22
23
    public function testValidTokenInBodyPostRequestResultIn200(): void
24
    {
25
        $token = $this->generateToken();
26
        $middleware = $this->createCsrfMiddlewareWithToken($token);
27
        $response = $middleware->process($this->createPostServerRequestWithBodyToken($token), $this->createRequestHandler());
28
        $this->assertEquals(200, $response->getStatusCode());
29
    }
30
31
    public function testValidTokenInBodyPutRequestResultIn200(): void
32
    {
33
        $token = $this->generateToken();
34
        $middleware = $this->createCsrfMiddlewareWithToken($token);
35
        $response = $middleware->process($this->createPutServerRequestWithBodyToken($token), $this->createRequestHandler());
36
        $this->assertEquals(200, $response->getStatusCode());
37
    }
38
39
    public function testValidTokenInBodyDeleteRequestResultIn200(): void
40
    {
41
        $token = $this->generateToken();
42
        $middleware = $this->createCsrfMiddlewareWithToken($token);
43
        $response = $middleware->process($this->createDeleteServerRequestWithBodyToken($token), $this->createRequestHandler());
44
        $this->assertEquals(200, $response->getStatusCode());
45
    }
46
47
    public function testValidTokenInHeaderResultIn200(): void
48
    {
49
        $token = $this->generateToken();
50
        $middleware = $this->createCsrfMiddlewareWithToken($token);
51
        $response = $middleware->process($this->createPostServerRequestWithHeaderToken($token), $this->createRequestHandler());
52
        $this->assertEquals(200, $response->getStatusCode());
53
    }
54
55
    public function testGetIsAlwaysAllowed(): void
56
    {
57
        $middleware = $this->createCsrfMiddlewareWithToken('');
58
        $response = $middleware->process($this->createServerRequest(Method::GET), $this->createRequestHandler());
59
        $this->assertEquals(200, $response->getStatusCode());
60
    }
61
62
    public function testInvalidTokenResultIn422(): void
63
    {
64
        $middleware = $this->createCsrfMiddlewareWithToken($this->generateToken());
65
        $response = $middleware->process($this->createPostServerRequestWithBodyToken($this->generateToken()), $this->createRequestHandler());
66
        $this->assertEquals(422, $response->getStatusCode());
67
    }
68
69
    public function testEmptyTokenInSessionResultIn422(): void
70
    {
71
        $middleware = $this->createCsrfMiddlewareWithToken('');
72
        $response = $middleware->process($this->createPostServerRequestWithBodyToken($this->generateToken()), $this->createRequestHandler());
73
        $this->assertEquals(422, $response->getStatusCode());
74
    }
75
76
    public function testEmptyTokenInRequestResultIn422(): void
77
    {
78
        $middleware = $this->createCsrfMiddlewareWithToken($this->generateToken());
79
        $response = $middleware->process($this->createServerRequest(), $this->createRequestHandler());
80
        $this->assertEquals(422, $response->getStatusCode());
81
    }
82
83
    private function createServerRequest(string $method = Method::POST, array $bodyParams = [], array $headParams = []): ServerRequestInterface
84
    {
85
        $request = new ServerRequest($method, '/', $headParams);
86
        return $request->withParsedBody($bodyParams);
87
    }
88
89
    private function createPostServerRequestWithBodyToken(string $token): ServerRequestInterface
90
    {
91
        return $this->createServerRequest(Method::POST, $this->getBodyRequestParamsByToken($token));
92
    }
93
94
    private function createPutServerRequestWithBodyToken(string $token): ServerRequestInterface
95
    {
96
        return $this->createServerRequest(Method::PUT, $this->getBodyRequestParamsByToken($token));
97
    }
98
99
    private function createDeleteServerRequestWithBodyToken(string $token): ServerRequestInterface
100
    {
101
        return $this->createServerRequest(Method::DELETE, $this->getBodyRequestParamsByToken($token));
102
    }
103
104
    private function createPostServerRequestWithHeaderToken(string $token): ServerRequestInterface
105
    {
106
        return $this->createServerRequest(Method::POST, [], [
107
            Csrf::HEADER_NAME => TokenMask::apply($token),
108
        ]);
109
    }
110
111
    private function createRequestHandler(): RequestHandlerInterface
112
    {
113
        $requestHandler = $this->createMock(RequestHandlerInterface::class);
114
        $requestHandler
115
            ->method('handle')
116
            ->willReturn(new Response(200));
117
118
        return $requestHandler;
119
    }
120
121
    private function createSessionMock(string $returnToken): SessionInterface
122
    {
123
        /**
124
         * @var SessionInterface|MockObject $sessionMock
125
         */
126
        $sessionMock = $this->createMock(SessionInterface::class);
127
128
        $sessionMock
129
            ->expects($this->once())
130
            ->method('get')
131
            ->willReturn($returnToken);
132
133
        return $sessionMock;
134
    }
135
136
    private function createCsrfMiddlewareWithToken(string $token): Csrf
137
    {
138
        $middleware = new Csrf(new Psr17Factory(), $this->createSessionMock($token));
139
        $middleware->setName(self::PARAM_NAME);
140
141
        return $middleware;
142
    }
143
144
    private function generateToken(): string
145
    {
146
        return Random::string();
147
    }
148
149
    private function getBodyRequestParamsByToken(string $token): array
150
    {
151
        return [
152
            self::PARAM_NAME => TokenMask::apply($token),
153
        ];
154
    }
155
}
156