Issues (536)

src/Middlewares/EncryptCookies.php (9 issues)

1
<?php
2
3
/**
4
 * This file is part of Blitz PHP framework.
5
 *
6
 * (c) 2022 Dimitri Sitchet Tomkeu <[email protected]>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11
12
namespace BlitzPHP\Middlewares;
13
14
use BlitzPHP\Contracts\Security\EncrypterInterface;
15
use BlitzPHP\Contracts\Session\CookieInterface;
16
use BlitzPHP\Contracts\Session\CookieManagerInterface;
17
use BlitzPHP\Http\Request;
18
use BlitzPHP\Http\Response;
19
use BlitzPHP\Session\Cookie\CookieCollection;
20
use BlitzPHP\Session\Cookie\CookieValuePrefix;
21
use Exception;
22
use Psr\Http\Message\ResponseInterface;
23
use Psr\Http\Message\ServerRequestInterface;
24
use Psr\Http\Server\MiddlewareInterface;
25
use Psr\Http\Server\RequestHandlerInterface;
26
27
class EncryptCookies implements MiddlewareInterface
28
{
29
    /**
30
     * Les noms des cookies qui ne doivent pas être cryptés.
31
     *
32
     * @var list<string>
0 ignored issues
show
The type BlitzPHP\Middlewares\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
     */
34
    protected array $except = [];
35
36
    /**
37
     * Indique si les cookies doivent être sérialisés.
38
     */
39
    protected static bool $serialize = false;
40
41
    /**
42
     * Créez une nouvelle instance CookieGuard.
43
     */
44
    public function __construct(protected EncrypterInterface $encrypter, protected CookieManagerInterface $cookieManager)
45
    {
46
    }
47
48
    /**
49
     * Désactivez le cryptage pour le(s) nom(s) de cookie donné(s).
50
     */
51
    public function disableFor(array|string $name): void
52
    {
53
        $this->except = array_merge($this->except, (array) $name);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($this->except, (array)$name) of type array is incompatible with the declared type BlitzPHP\Middlewares\list of property $except.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
54
    }
55
56
    /**
57
     * @param Request $request
58
     */
59
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
60
    {
61
        return $this->encrypt($handler->handle($this->decrypt($request)));
62
    }
63
64
    /**
65
     * Décryptez les cookies sur requete.
66
     */
67
    protected function decrypt(Request $request): Request
68
    {
69
        $cookies = new CookieCollection();
70
71
        foreach ($request->getCookieParams() as $name => $cookie) {
72
            if ($this->isDisabled($name)) {
73
                continue;
74
            }
75
76
            try {
77
                $value = $this->decryptCookie($name, $cookie);
78
                $value = $this->validateValue($name, $value);
79
                $cookies->add($this->cookieManager->make($name, $value));
80
            } catch (Exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
81
            }
82
        }
83
84
        return $request->withCookieCollection($cookies);
85
    }
86
87
    /**
88
     * Validez et supprimez le préfixe de valeur du cookie de la valeur.
89
     *
90
     * @return array|string|null
91
     */
92
    protected function validateValue(string $key, array|string $value)
93
    {
94
        return is_array($value)
0 ignored issues
show
The condition is_array($value) is always true.
Loading history...
95
                    ? $this->validateArray($key, $value)
96
                    : CookieValuePrefix::validate($key, $value, $this->encrypter->getKey());
97
    }
98
99
    /**
100
     * Validez et supprimez le préfixe de valeur du cookie de toutes les valeurs d'un tableau.
101
     */
102
    protected function validateArray(string $key, array $value): array
103
    {
104
        $validated = [];
105
106
        foreach ($value as $index => $subValue) {
107
            $validated[$index] = $this->validateValue("{$key}[{$index}]", $subValue);
108
        }
109
110
        return $validated;
111
    }
112
113
    /**
114
     * Décryptez le cookie donné et renvoyez la valeur.
115
     */
116
    protected function decryptCookie(string $name, array|string $cookie): array|string
0 ignored issues
show
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

116
    protected function decryptCookie(/** @scrutinizer ignore-unused */ string $name, array|string $cookie): array|string

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...
117
    {
118
        return is_array($cookie)
0 ignored issues
show
The condition is_array($cookie) is always true.
Loading history...
119
                        ? $this->decryptArray($cookie)
120
                        : $this->encrypter->decrypt($cookie);
121
    }
122
123
    /**
124
     * Décryptez un cookie basé sur un tableau.
125
     */
126
    protected function decryptArray(array $cookie): array
127
    {
128
        $decrypted = [];
129
130
        foreach ($cookie as $key => $value) {
131
            if (is_string($value)) {
132
                $decrypted[$key] = $this->encrypter->decrypt($value);
133
            }
134
135
            if (is_array($value)) {
136
                $decrypted[$key] = $this->decryptArray($value);
137
            }
138
        }
139
140
        return $decrypted;
141
    }
142
143
    /**
144
     * Chiffrez les cookies sur une réponse sortante.
145
     *
146
     * @param Response $response
147
     */
148
    protected function encrypt(ResponseInterface $response): Response
149
    {
150
        foreach ($response->getCookieCollection() as $cookie) {
0 ignored issues
show
The method getCookieCollection() does not exist on Psr\Http\Message\ResponseInterface. It seems like you code against a sub-type of Psr\Http\Message\ResponseInterface such as BlitzPHP\Http\Response. ( Ignorable by Annotation )

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

150
        foreach ($response->/** @scrutinizer ignore-call */ getCookieCollection() as $cookie) {
Loading history...
151
            if ($this->isDisabled($cookie->getName())) {
152
                continue;
153
            }
154
155
            $response = $response->withCookie($this->duplicate(
0 ignored issues
show
The method withCookie() does not exist on Psr\Http\Message\ResponseInterface. It seems like you code against a sub-type of Psr\Http\Message\ResponseInterface such as BlitzPHP\Http\Response. ( Ignorable by Annotation )

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

155
            /** @scrutinizer ignore-call */ 
156
            $response = $response->withCookie($this->duplicate(
Loading history...
156
                $cookie,
157
                $this->encrypter->encrypt(
158
                    CookieValuePrefix::create($cookie->getName(), $this->encrypter->getKey()) . $cookie->getValue(),
159
                )
160
            ));
161
        }
162
163
        return $response;
164
    }
165
166
    /**
167
     * Dupliquez un cookie avec une nouvelle valeur.
168
     */
169
    protected function duplicate(CookieInterface $cookie, mixed $value): CookieInterface
170
    {
171
        return $cookie->withValue($value);
172
    }
173
174
    /**
175
     * Déterminez si le cryptage a été désactivé pour le cookie donné.
176
     */
177
    public function isDisabled(string $name): bool
178
    {
179
        return in_array($name, $this->except, true);
180
    }
181
182
    /**
183
     * Déterminez si le contenu du cookie doit être sérialisé.
184
     */
185
    public static function serialized(string $name): bool
0 ignored issues
show
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

185
    public static function serialized(/** @scrutinizer ignore-unused */ string $name): bool

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...
186
    {
187
        return static::$serialize;
188
    }
189
}
190