Upgrade project to PHP 8.3, add PHPStan, upgrade almost every dependency (#36)

* start updating to PHP 8.3

* taking off!

Co-authored-by: ErickSkrauch <erickskrauch@yandex.ru>
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* dropped this

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* migrate to symfonymailer

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* this is so stupid 😭

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* ah, free, at last.

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* oh, Gabriel.

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* now dawns thy reckoning.

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* and thy gore shall GLISTEN before the temples of man.

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* creature of steel.

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* my gratitude upon thee for my freedom.

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* but the crimes thy kind has committed against humanity

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* Upgrade PHP-CS-Fixer and do fix the codebase

* First review round (maybe I have broken something)

* are NOT forgotten.

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>

* Enable parallel PHP-CS-Fixer runner

* PHPStan level 1

* PHPStan level 2

* PHPStan level 3

* PHPStan level 4

* PHPStan level 5

* Levels 6 and 7 takes too much effort. Generate a baseline and fix them eventually

* Resolve TODO's related to the php-mock

* Drastically reduce baseline size with the Rector

* More code modernization with help of the Rector

* Update GitLab CI

---------

Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
Co-authored-by: ErickSkrauch <erickskrauch@yandex.ru>
This commit is contained in:
Octol1ttle
2024-12-02 15:10:55 +05:00
committed by GitHub
parent 625250b367
commit 57d492da8a
356 changed files with 10531 additions and 4761 deletions

View File

@@ -5,31 +5,40 @@ namespace api\components\Tokens;
use Carbon\Carbon;
use Exception;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use InvalidArgumentException;
use Lcobucci\JWT\Encoding\ChainedFormatter;
use Lcobucci\JWT\Encoding\JoseEncoder;
use Lcobucci\JWT\Token;
use Lcobucci\JWT\Token\Builder;
use Lcobucci\JWT\Token\Parser;
use Lcobucci\JWT\Token\RegisteredClaims;
use Lcobucci\JWT\UnencryptedToken;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
use Lcobucci\JWT\Validation\Validator;
use ParagonIE\ConstantTime\Base64UrlSafe;
use RangeException;
use SodiumException;
use Webmozart\Assert\Assert;
use yii\base\Component as BaseComponent;
class Component extends BaseComponent {
private const PREFERRED_ALGORITHM = 'ES256';
private const string PREFERRED_ALGORITHM = 'ES256';
/**
* @var string
*/
public $privateKeyPath;
public string $privateKeyPath;
/**
* @var string|null
*/
public $privateKeyPass;
public ?string $privateKeyPass = null;
/**
* @var string
*/
public $encryptionKey;
public string $encryptionKey;
private ?AlgorithmsManager $algorithmManager = null;
@@ -39,19 +48,49 @@ class Component extends BaseComponent {
Assert::notEmpty($this->encryptionKey, 'encryptionKey must be set');
}
public function create(array $payloads = [], array $headers = []): Token {
/**
* @param array{
* sub?: string,
* jti?: string,
* iat?: \DateTimeImmutable,
* nbf?: \DateTimeImmutable,
* exp?: \DateTimeImmutable,
* } $payloads
* @param array $headers
*
* @throws \api\components\Tokens\AlgorithmIsNotDefinedException
*/
public function create(array $payloads = [], array $headers = []): UnencryptedToken {
$now = Carbon::now();
$builder = (new Builder())->issuedAt($now->getTimestamp());
$builder = (new Builder(new JoseEncoder(), ChainedFormatter::default()))->issuedAt($now->toDateTimeImmutable());
if (isset($payloads['sub'])) {
$builder = $builder->relatedTo($payloads['sub']);
}
if (isset($payloads['jti'])) {
$builder = $builder->identifiedBy($payloads['jti']);
}
if (isset($payloads['iat'])) {
$builder = $builder->issuedAt($payloads['iat']);
}
if (isset($payloads['nbf'])) {
$builder = $builder->canOnlyBeUsedAfter($payloads['nbf']);
}
if (isset($payloads['exp'])) {
$builder->expiresAt($payloads['exp']);
$builder = $builder->expiresAt($payloads['exp']);
}
foreach ($payloads as $claim => $value) {
$builder->withClaim($claim, $this->prepareValue($value));
if (!in_array($claim, RegisteredClaims::ALL, true)) { // Registered claims are handled by the if-chain above
$builder = $builder->withClaim($claim, $this->prepareValue($value));
}
}
foreach ($headers as $claim => $value) {
$builder->withHeader($claim, $this->prepareValue($value));
$builder = $builder->withHeader($claim, $this->prepareValue($value));
}
/** @noinspection PhpUnhandledExceptionInspection */
@@ -64,17 +103,17 @@ class Component extends BaseComponent {
* @param string $jwt
*
* @return Token
* @throws \InvalidArgumentException
* @throws InvalidArgumentException
*/
public function parse(string $jwt): Token {
return (new Parser())->parse($jwt);
return (new Parser(new JoseEncoder()))->parse($jwt);
}
public function verify(Token $token): bool {
try {
$algorithm = $this->getAlgorithmManager()->get($token->getHeader('alg'));
return $token->verify($algorithm->getSigner(), $algorithm->getPublicKey());
} catch (Exception $e) {
$algorithm = $this->getAlgorithmManager()->get($token->headers()->get('alg'));
return (new Validator())->validate($token, new SignedWith($algorithm->getSigner(), $algorithm->getPublicKey()));
} catch (Exception) {
return false;
}
}
@@ -92,8 +131,8 @@ class Component extends BaseComponent {
* @param string $encryptedValue
*
* @return string
* @throws \SodiumException
* @throws \RangeException
* @throws SodiumException
* @throws RangeException
*/
public function decryptValue(string $encryptedValue): string {
$decoded = Base64UrlSafe::decode($encryptedValue);
@@ -109,7 +148,7 @@ class Component extends BaseComponent {
}
public function getPublicKey(): string {
return $this->getAlgorithmManager()->get(self::PREFERRED_ALGORITHM)->getPublicKey()->getContent();
return $this->getAlgorithmManager()->get(self::PREFERRED_ALGORITHM)->getPublicKey()->contents();
}
private function getAlgorithmManager(): AlgorithmsManager {
@@ -122,9 +161,9 @@ class Component extends BaseComponent {
return $this->algorithmManager;
}
private function prepareValue($value) {
private function prepareValue(EncryptedValue|string $value): string {
if ($value instanceof EncryptedValue) {
return $this->encryptValue($value->getValue());
return $this->encryptValue($value->value);
}
return $value;