mirror of
				https://github.com/elyby/accounts.git
				synced 2025-05-31 14:11:46 +05:30 
			
		
		
		
	Move OAuth module from API to common and solve PHPStan's errors
This commit is contained in:
		| @@ -1,10 +0,0 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace api\components\OAuth2\Events; | ||||
|  | ||||
| use League\OAuth2\Server\EventEmitting\AbstractEvent; | ||||
|  | ||||
| class RequestedRefreshToken extends AbstractEvent { | ||||
|  | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace api\components\OAuth2\Grants; | ||||
|  | ||||
| use api\components\OAuth2\CryptTrait; | ||||
| use League\OAuth2\Server\Grant\ClientCredentialsGrant as BaseClientCredentialsGrant; | ||||
|  | ||||
| class ClientCredentialsGrant extends BaseClientCredentialsGrant { | ||||
|     use CryptTrait; | ||||
|  | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace api\components\OAuth2\ResponseTypes; | ||||
|  | ||||
| use api\components\OAuth2\CryptTrait; | ||||
| use League\OAuth2\Server\ResponseTypes\BearerTokenResponse as BaseBearerTokenResponse; | ||||
|  | ||||
| class BearerTokenResponse extends BaseBearerTokenResponse { | ||||
|     use CryptTrait; | ||||
|  | ||||
| } | ||||
| @@ -30,6 +30,9 @@ final readonly class TokenReader { | ||||
|         return $this->token->claims()->get('client_id', false) ?: null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return list<string>|null | ||||
|      */ | ||||
|     public function getScopes(): ?array { | ||||
|         $scopes = $this->token->claims()->get('scope', false); | ||||
|         if ($scopes !== false) { | ||||
|   | ||||
| @@ -26,9 +26,6 @@ return [ | ||||
|         'user' => [ | ||||
|             'class' => api\components\User\Component::class, | ||||
|         ], | ||||
|         'oauth' => [ | ||||
|             'class' => api\components\OAuth2\Component::class, | ||||
|         ], | ||||
|         'tokens' => [ | ||||
|             'class' => api\components\Tokens\Component::class, | ||||
|             'privateKeyPath' => getenv('JWT_PRIVATE_KEY_PATH') ?: __DIR__ . '/../../data/certs/private.pem', | ||||
|   | ||||
| @@ -9,10 +9,20 @@ use api\rbac\Permissions as P; | ||||
| use GuzzleHttp\Psr7\ServerRequest; | ||||
| use Psr\Http\Message\ServerRequestInterface; | ||||
| use Yii; | ||||
| use yii\base\Module; | ||||
| use yii\filters\AccessControl; | ||||
| use yii\helpers\ArrayHelper; | ||||
|  | ||||
| class AuthorizationController extends Controller { | ||||
| final class AuthorizationController extends Controller { | ||||
|  | ||||
|     public function __construct( | ||||
|         string $id, | ||||
|         Module $module, | ||||
|         private readonly OauthProcess $oauthProcess, | ||||
|         array $config = [], | ||||
|     ) { | ||||
|         parent::__construct($id, $module, $config); | ||||
|     } | ||||
|  | ||||
|     public function behaviors(): array { | ||||
|         return ArrayHelper::merge(Controller::behaviors(), [ | ||||
| @@ -45,19 +55,15 @@ class AuthorizationController extends Controller { | ||||
|     } | ||||
|  | ||||
|     public function actionValidate(): array { | ||||
|         return $this->createOauthProcess()->validate($this->getServerRequest()); | ||||
|         return $this->oauthProcess->validate($this->getServerRequest()); | ||||
|     } | ||||
|  | ||||
|     public function actionComplete(): array { | ||||
|         return $this->createOauthProcess()->complete($this->getServerRequest()); | ||||
|         return $this->oauthProcess->complete($this->getServerRequest()); | ||||
|     } | ||||
|  | ||||
|     public function actionToken(): array { | ||||
|         return $this->createOauthProcess()->getToken($this->getServerRequest()); | ||||
|     } | ||||
|  | ||||
|     private function createOauthProcess(): OauthProcess { | ||||
|         return new OauthProcess(Yii::$app->oauth->getAuthServer()); | ||||
|         return $this->oauthProcess->getToken($this->getServerRequest()); | ||||
|     } | ||||
|  | ||||
|     private function getServerRequest(): ServerRequestInterface { | ||||
|   | ||||
| @@ -3,9 +3,9 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace api\modules\oauth\models; | ||||
|  | ||||
| use api\components\OAuth2\Entities\UserEntity; | ||||
| use api\components\OAuth2\Events\RequestedRefreshToken; | ||||
| use api\rbac\Permissions as P; | ||||
| use common\components\OAuth2\Entities\UserEntity; | ||||
| use common\components\OAuth2\Events\RequestedRefreshToken; | ||||
| use common\models\Account; | ||||
| use common\models\OauthClient; | ||||
| use common\models\OauthSession; | ||||
| @@ -18,14 +18,16 @@ use Psr\Http\Message\ServerRequestInterface; | ||||
| use Webmozart\Assert\Assert; | ||||
| use Yii; | ||||
|  | ||||
| class OauthProcess { | ||||
| final readonly class OauthProcess { | ||||
|  | ||||
|     private const array INTERNAL_PERMISSIONS_TO_PUBLIC_SCOPES = [ | ||||
|         P::OBTAIN_OWN_ACCOUNT_INFO => 'account_info', | ||||
|         P::OBTAIN_ACCOUNT_EMAIL => 'account_email', | ||||
|     ]; | ||||
|  | ||||
|     public function __construct(private readonly AuthorizationServer $server) { | ||||
|     public function __construct( | ||||
|         private AuthorizationServer $server, | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -43,8 +45,7 @@ class OauthProcess { | ||||
|      * | ||||
|      * In addition, you can pass the description value to override the application's description. | ||||
|      * | ||||
|      * @param ServerRequestInterface $request | ||||
|      * @return array | ||||
|      * @return array<mixed> | ||||
|      */ | ||||
|     public function validate(ServerRequestInterface $request): array { | ||||
|         try { | ||||
| @@ -77,8 +78,7 @@ class OauthProcess { | ||||
|      * If the field is present, it will be interpreted as any value resulting in false positives. | ||||
|      * Otherwise, the value will be interpreted as "true". | ||||
|      * | ||||
|      * @param ServerRequestInterface $request | ||||
|      * @return array | ||||
|      * @return array<mixed> | ||||
|      */ | ||||
|     public function complete(ServerRequestInterface $request): array { | ||||
|         try { | ||||
| @@ -144,8 +144,7 @@ class OauthProcess { | ||||
|      *     grant_type, | ||||
|      * ] | ||||
|      * | ||||
|      * @param ServerRequestInterface $request | ||||
|      * @return array | ||||
|      * @return array<mixed> | ||||
|      */ | ||||
|     public function getToken(ServerRequestInterface $request): array { | ||||
|         $params = (array)$request->getParsedBody(); | ||||
| @@ -232,11 +231,9 @@ class OauthProcess { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param ServerRequestInterface $request | ||||
|      * @param OauthClient $client | ||||
|      * @param ScopeEntityInterface[] $scopes | ||||
|      * | ||||
|      * @return array | ||||
|      * @return array<mixed> | ||||
|      */ | ||||
|     private function buildSuccessResponse(ServerRequestInterface $request, OauthClient $client, array $scopes): array { | ||||
|         return [ | ||||
| @@ -262,7 +259,7 @@ class OauthProcess { | ||||
|  | ||||
|     /** | ||||
|      * @param ScopeEntityInterface[] $scopes | ||||
|      * @return array | ||||
|      * @return string[] | ||||
|      */ | ||||
|     private function buildScopesArray(array $scopes): array { | ||||
|         $result = []; | ||||
| @@ -273,6 +270,15 @@ class OauthProcess { | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array{ | ||||
|      *     success: false, | ||||
|      *     error: string, | ||||
|      *     parameter: string|null, | ||||
|      *     statusCode: int, | ||||
|      *     redirectUri?: string, | ||||
|      * } | ||||
|      */ | ||||
|     private function buildCompleteErrorResponse(OAuthServerException $e): array { | ||||
|         $hint = $e->getPayload()['hint'] ?? ''; | ||||
|         if (preg_match('/the `(\w+)` scope/', $hint, $matches)) { | ||||
| @@ -304,8 +310,10 @@ class OauthProcess { | ||||
|      * | ||||
|      * Part of the existing texts are the legacy from the previous implementation. | ||||
|      * | ||||
|      * @param OAuthServerException $e | ||||
|      * @return array | ||||
|      * @return array{ | ||||
|      *     error: string, | ||||
|      *     message: string, | ||||
|      * } | ||||
|      */ | ||||
|     private function buildIssueErrorResponse(OAuthServerException $e): array { | ||||
|         $errorType = $e->getErrorType(); | ||||
| @@ -331,6 +339,9 @@ class OauthProcess { | ||||
|         return new OAuthServerException('Client must accept authentication request.', 0, 'accept_required', 401); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return list<string> | ||||
|      */ | ||||
|     private function getScopesList(AuthorizationRequestInterface $request): array { | ||||
|         return array_values(array_map(fn(ScopeEntityInterface $scope): string => $scope->getIdentifier(), $request->getScopes())); | ||||
|     } | ||||
|   | ||||
| @@ -3,8 +3,8 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace api\tests\functional\_steps; | ||||
|  | ||||
| use api\components\OAuth2\Repositories\PublicScopeRepository; | ||||
| use api\tests\FunctionalTester; | ||||
| use common\components\OAuth2\Repositories\PublicScopeRepository; | ||||
|  | ||||
| class OauthSteps extends FunctionalTester { | ||||
|  | ||||
|   | ||||
| @@ -3,8 +3,8 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace api\tests\unit\components\OAuth2\Entities; | ||||
|  | ||||
| use api\components\OAuth2\Entities\AccessTokenEntity; | ||||
| use api\tests\unit\TestCase; | ||||
| use common\components\OAuth2\Entities\AccessTokenEntity; | ||||
| use DateTimeImmutable; | ||||
| use League\OAuth2\Server\Entities\ClientEntityInterface; | ||||
| use League\OAuth2\Server\Entities\ScopeEntityInterface; | ||||
|   | ||||
| @@ -34,7 +34,6 @@ abstract class BaseApplication extends yii\base\Application { | ||||
|  * | ||||
|  * @property \api\components\User\Component       $user | ||||
|  * @property \api\components\ReCaptcha\Component  $reCaptcha | ||||
|  * @property \api\components\OAuth2\Component     $oauth | ||||
|  * @property \api\components\Tokens\Component     $tokens | ||||
|  * @property \api\components\Tokens\TokensFactory $tokensFactory | ||||
|  * | ||||
|   | ||||
| @@ -1,26 +1,16 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2; | ||||
| namespace common\components\OAuth2; | ||||
| 
 | ||||
| use Carbon\CarbonInterval; | ||||
| use DateInterval; | ||||
| use League\OAuth2\Server\AuthorizationServer; | ||||
| use yii\base\Component as BaseComponent; | ||||
| 
 | ||||
| final class Component extends BaseComponent { | ||||
| final class AuthorizationServerFactory extends BaseComponent { | ||||
| 
 | ||||
|     private ?AuthorizationServer $_authServer = null; | ||||
| 
 | ||||
|     public function getAuthServer(): AuthorizationServer { | ||||
|         if ($this->_authServer === null) { | ||||
|             $this->_authServer = $this->createAuthServer(); | ||||
|         } | ||||
| 
 | ||||
|         return $this->_authServer; | ||||
|     } | ||||
| 
 | ||||
|     private function createAuthServer(): AuthorizationServer { | ||||
|     public static function build(): AuthorizationServer { | ||||
|         $clientsRepo = new Repositories\ClientRepository(); | ||||
|         $accessTokensRepo = new Repositories\AccessTokenRepository(); | ||||
|         $publicScopesRepo = new Repositories\PublicScopeRepository(); | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2; | ||||
| namespace common\components\OAuth2; | ||||
| 
 | ||||
| use LogicException; | ||||
| use RangeException; | ||||
| @@ -18,11 +18,11 @@ use Yii; | ||||
|  */ | ||||
| trait CryptTrait { | ||||
| 
 | ||||
|     protected function encrypt($unencryptedData): string { | ||||
|     protected function encrypt(string $unencryptedData): string { | ||||
|         return Yii::$app->tokens->encryptValue($unencryptedData); | ||||
|     } | ||||
| 
 | ||||
|     protected function decrypt($encryptedData): string { | ||||
|     protected function decrypt(string $encryptedData): string { | ||||
|         try { | ||||
|             return Yii::$app->tokens->decryptValue($encryptedData); | ||||
|         } catch (SodiumException|RangeException $e) { | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Entities; | ||||
| namespace common\components\OAuth2\Entities; | ||||
| 
 | ||||
| use League\OAuth2\Server\CryptKeyInterface; | ||||
| use League\OAuth2\Server\Entities\AccessTokenEntityInterface; | ||||
| @@ -1,14 +1,14 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Entities; | ||||
| namespace common\components\OAuth2\Entities; | ||||
| 
 | ||||
| use League\OAuth2\Server\Entities\AuthCodeEntityInterface; | ||||
| use League\OAuth2\Server\Entities\Traits\AuthCodeTrait; | ||||
| use League\OAuth2\Server\Entities\Traits\EntityTrait; | ||||
| use League\OAuth2\Server\Entities\Traits\TokenEntityTrait; | ||||
| 
 | ||||
| class AuthCodeEntity implements AuthCodeEntityInterface { | ||||
| final class AuthCodeEntity implements AuthCodeEntityInterface { | ||||
|     use EntityTrait; | ||||
|     use AuthCodeTrait; | ||||
|     use TokenEntityTrait; | ||||
| @@ -1,19 +1,19 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Entities; | ||||
| namespace common\components\OAuth2\Entities; | ||||
| 
 | ||||
| use League\OAuth2\Server\Entities\ClientEntityInterface; | ||||
| use League\OAuth2\Server\Entities\Traits\ClientTrait; | ||||
| use League\OAuth2\Server\Entities\Traits\EntityTrait; | ||||
| 
 | ||||
| class ClientEntity implements ClientEntityInterface { | ||||
| final class ClientEntity implements ClientEntityInterface { | ||||
|     use EntityTrait; | ||||
|     use ClientTrait; | ||||
| 
 | ||||
|     /** | ||||
|      * @param non-empty-string $id | ||||
|      * @param string|string[] $redirectUri | ||||
|      * @phpstan-param non-empty-string $id | ||||
|      * @phpstan-param string|list<string> $redirectUri | ||||
|      */ | ||||
|     public function __construct( | ||||
|         string $id, | ||||
| @@ -1,16 +1,19 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Entities; | ||||
| namespace common\components\OAuth2\Entities; | ||||
| 
 | ||||
| use League\OAuth2\Server\Entities\ScopeEntityInterface; | ||||
| use League\OAuth2\Server\Entities\Traits\EntityTrait; | ||||
| use League\OAuth2\Server\Entities\Traits\ScopeTrait; | ||||
| 
 | ||||
| class ScopeEntity implements ScopeEntityInterface { | ||||
| final class ScopeEntity implements ScopeEntityInterface { | ||||
|     use EntityTrait; | ||||
|     use ScopeTrait; | ||||
| 
 | ||||
|     /** | ||||
|      * @phpstan-param non-empty-string $id | ||||
|      */ | ||||
|     public function __construct(string $id) { | ||||
|         $this->identifier = $id; | ||||
|     } | ||||
| @@ -1,12 +1,12 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Entities; | ||||
| namespace common\components\OAuth2\Entities; | ||||
| 
 | ||||
| use League\OAuth2\Server\Entities\Traits\EntityTrait; | ||||
| use League\OAuth2\Server\Entities\UserEntityInterface; | ||||
| 
 | ||||
| class UserEntity implements UserEntityInterface { | ||||
| final class UserEntity implements UserEntityInterface { | ||||
|     use EntityTrait; | ||||
| 
 | ||||
|     public function __construct(int $id) { | ||||
							
								
								
									
										10
									
								
								common/components/OAuth2/Events/RequestedRefreshToken.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								common/components/OAuth2/Events/RequestedRefreshToken.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace common\components\OAuth2\Events; | ||||
|  | ||||
| use League\OAuth2\Server\EventEmitting\AbstractEvent; | ||||
|  | ||||
| final class RequestedRefreshToken extends AbstractEvent { | ||||
|  | ||||
| } | ||||
| @@ -1,35 +1,23 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Grants; | ||||
| namespace common\components\OAuth2\Grants; | ||||
| 
 | ||||
| use api\components\OAuth2\CryptTrait; | ||||
| use api\components\OAuth2\Events\RequestedRefreshToken; | ||||
| use api\components\OAuth2\Repositories\PublicScopeRepository; | ||||
| use common\components\OAuth2\CryptTrait; | ||||
| use common\components\OAuth2\Events\RequestedRefreshToken; | ||||
| use common\components\OAuth2\Repositories\PublicScopeRepository; | ||||
| use DateInterval; | ||||
| use League\OAuth2\Server\Entities\AccessTokenEntityInterface; | ||||
| use League\OAuth2\Server\Entities\ClientEntityInterface; | ||||
| use League\OAuth2\Server\Entities\ScopeEntityInterface; | ||||
| use League\OAuth2\Server\Exception\OAuthServerException; | ||||
| use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException; | ||||
| use League\OAuth2\Server\Grant\AuthCodeGrant as BaseAuthCodeGrant; | ||||
| use League\OAuth2\Server\RequestEvent; | ||||
| use Psr\Http\Message\ServerRequestInterface; | ||||
| use yii\helpers\StringHelper; | ||||
| 
 | ||||
| class AuthCodeGrant extends BaseAuthCodeGrant { | ||||
| final class AuthCodeGrant extends BaseAuthCodeGrant { | ||||
|     use CryptTrait; | ||||
| 
 | ||||
|     /** | ||||
|      * @param DateInterval $accessTokenTTL | ||||
|      * @param ClientEntityInterface $client | ||||
|      * @param string|null $userIdentifier | ||||
|      * @param ScopeEntityInterface[] $scopes | ||||
|      * | ||||
|      * @return AccessTokenEntityInterface | ||||
|      * @throws OAuthServerException | ||||
|      * @throws UniqueTokenIdentifierConstraintViolationException | ||||
|      */ | ||||
|     protected function issueAccessToken( | ||||
|         DateInterval $accessTokenTTL, | ||||
|         ClientEntityInterface $client, | ||||
							
								
								
									
										12
									
								
								common/components/OAuth2/Grants/ClientCredentialsGrant.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								common/components/OAuth2/Grants/ClientCredentialsGrant.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace common\components\OAuth2\Grants; | ||||
|  | ||||
| use common\components\OAuth2\CryptTrait; | ||||
| use League\OAuth2\Server\Grant\ClientCredentialsGrant as BaseClientCredentialsGrant; | ||||
|  | ||||
| final class ClientCredentialsGrant extends BaseClientCredentialsGrant { | ||||
|     use CryptTrait; | ||||
|  | ||||
| } | ||||
| @@ -1,11 +1,11 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Grants; | ||||
| namespace common\components\OAuth2\Grants; | ||||
| 
 | ||||
| use api\components\OAuth2\CryptTrait; | ||||
| use api\components\Tokens\TokenReader; | ||||
| use Carbon\FactoryImmutable; | ||||
| use common\components\OAuth2\CryptTrait; | ||||
| use common\models\OauthSession; | ||||
| use InvalidArgumentException; | ||||
| use Lcobucci\JWT\Validation\Constraint\LooseValidAt; | ||||
| @@ -18,7 +18,7 @@ use Psr\Http\Message\ServerRequestInterface; | ||||
| use Throwable; | ||||
| use Yii; | ||||
| 
 | ||||
| class RefreshTokenGrant extends BaseRefreshTokenGrant { | ||||
| final class RefreshTokenGrant extends BaseRefreshTokenGrant { | ||||
|     use CryptTrait; | ||||
| 
 | ||||
|     /** | ||||
| @@ -26,11 +26,7 @@ class RefreshTokenGrant extends BaseRefreshTokenGrant { | ||||
|      * If received refresh token is matches the legacy token template, | ||||
|      * restore the information from the legacy storage. | ||||
|      * | ||||
|      * @param ServerRequestInterface $request | ||||
|      * @param string $clientId | ||||
|      * | ||||
|      * @return array | ||||
|      * @throws OAuthServerException | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     protected function validateOldRefreshToken(ServerRequestInterface $request, string $clientId): array { | ||||
|         $refreshToken = $this->getRequestParameter('refresh_token', $request); | ||||
| @@ -45,18 +41,13 @@ class RefreshTokenGrant extends BaseRefreshTokenGrant { | ||||
|      * Currently we're not rotating refresh tokens. | ||||
|      * So we're overriding this method to always return null, which means, | ||||
|      * that refresh_token will not be issued. | ||||
|      * | ||||
|      * @param AccessTokenEntityInterface $accessToken | ||||
|      * | ||||
|      * @return RefreshTokenEntityInterface|null | ||||
|      */ | ||||
|     protected function issueRefreshToken(AccessTokenEntityInterface $accessToken): ?RefreshTokenEntityInterface { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @param string $refreshToken | ||||
|      * @return array | ||||
|      * @return array<string, mixed> | ||||
|      * @throws OAuthServerException | ||||
|      */ | ||||
|     private function validateLegacyRefreshToken(string $refreshToken): array { | ||||
| @@ -91,14 +82,7 @@ class RefreshTokenGrant extends BaseRefreshTokenGrant { | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return array{ | ||||
|      *     client_id: string, | ||||
|      *     refresh_token_id?: string, | ||||
|      *     access_token_id?: string, | ||||
|      *     scopes: list<string>|null, | ||||
|      *     user_id: string|null, | ||||
|      *     expire_time: int|null, | ||||
|      * } | ||||
|      * @return array<string, mixed> | ||||
|      * @throws OAuthServerException | ||||
|      */ | ||||
|     private function validateAccessToken(string $jwt): array { | ||||
| @@ -1,11 +1,11 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Keys; | ||||
| namespace common\components\OAuth2\Keys; | ||||
| 
 | ||||
| use League\OAuth2\Server\CryptKeyInterface; | ||||
| 
 | ||||
| class EmptyKey implements CryptKeyInterface { | ||||
| final class EmptyKey implements CryptKeyInterface { | ||||
| 
 | ||||
|     public function getKeyPath(): string { | ||||
|         return ''; | ||||
| @@ -1,28 +1,23 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Repositories; | ||||
| namespace common\components\OAuth2\Repositories; | ||||
| 
 | ||||
| use api\components\OAuth2\Entities\AccessTokenEntity; | ||||
| use common\components\OAuth2\Entities\AccessTokenEntity; | ||||
| use League\OAuth2\Server\Entities\AccessTokenEntityInterface; | ||||
| use League\OAuth2\Server\Entities\ClientEntityInterface; | ||||
| use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; | ||||
| 
 | ||||
| class AccessTokenRepository implements AccessTokenRepositoryInterface { | ||||
| final class AccessTokenRepository implements AccessTokenRepositoryInterface { | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new access token | ||||
|      * | ||||
|      * @param ClientEntityInterface $clientEntity | ||||
|      * @param \League\OAuth2\Server\Entities\ScopeEntityInterface[] $scopes | ||||
|      * @param mixed $userIdentifier | ||||
|      * | ||||
|      * @return AccessTokenEntityInterface | ||||
|      * @inheritDoc | ||||
|      * @phpstan-param non-empty-string|null $userIdentifier | ||||
|      */ | ||||
|     public function getNewToken( | ||||
|         ClientEntityInterface $clientEntity, | ||||
|         array $scopes, | ||||
|         $userIdentifier = null, | ||||
|         ?string $userIdentifier = null, | ||||
|     ): AccessTokenEntityInterface { | ||||
|         $accessToken = new AccessTokenEntity(); | ||||
|         $accessToken->setClient($clientEntity); | ||||
| @@ -38,11 +33,11 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface { | ||||
|         // We don't store access tokens, so there's no need to do anything here
 | ||||
|     } | ||||
| 
 | ||||
|     public function revokeAccessToken($tokenId): void { | ||||
|     public function revokeAccessToken(string $tokenId): void { | ||||
|         // We don't store access tokens, so there's no need to do anything here
 | ||||
|     } | ||||
| 
 | ||||
|     public function isAccessTokenRevoked($tokenId): bool { | ||||
|     public function isAccessTokenRevoked(string $tokenId): bool { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
| @@ -1,13 +1,13 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Repositories; | ||||
| namespace common\components\OAuth2\Repositories; | ||||
| 
 | ||||
| use api\components\OAuth2\Entities\AuthCodeEntity; | ||||
| use common\components\OAuth2\Entities\AuthCodeEntity; | ||||
| use League\OAuth2\Server\Entities\AuthCodeEntityInterface; | ||||
| use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface; | ||||
| 
 | ||||
| class AuthCodeRepository implements AuthCodeRepositoryInterface { | ||||
| final class AuthCodeRepository implements AuthCodeRepositoryInterface { | ||||
| 
 | ||||
|     public function getNewAuthCode(): AuthCodeEntityInterface { | ||||
|         return new AuthCodeEntity(); | ||||
| @@ -16,10 +16,10 @@ class AuthCodeRepository implements AuthCodeRepositoryInterface { | ||||
|     public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity): void { | ||||
|     } | ||||
| 
 | ||||
|     public function revokeAuthCode($codeId): void { | ||||
|     public function revokeAuthCode(string $codeId): void { | ||||
|     } | ||||
| 
 | ||||
|     public function isAuthCodeRevoked($codeId): bool { | ||||
|     public function isAuthCodeRevoked(string $codeId): bool { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
| @@ -1,26 +1,27 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Repositories; | ||||
| namespace common\components\OAuth2\Repositories; | ||||
| 
 | ||||
| use api\components\OAuth2\Entities\ClientEntity; | ||||
| use common\components\OAuth2\Entities\ClientEntity; | ||||
| use common\models\OauthClient; | ||||
| use League\OAuth2\Server\Entities\ClientEntityInterface; | ||||
| use League\OAuth2\Server\Repositories\ClientRepositoryInterface; | ||||
| 
 | ||||
| class ClientRepository implements ClientRepositoryInterface { | ||||
| final class ClientRepository implements ClientRepositoryInterface { | ||||
| 
 | ||||
|     public function getClientEntity($clientId): ?ClientEntityInterface { | ||||
|         $client = $this->findModel($clientId); | ||||
|     public function getClientEntity(string $clientIdentifier): ?ClientEntityInterface { | ||||
|         $client = $this->findModel($clientIdentifier); | ||||
|         if ($client === null) { | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         return new ClientEntity($client->id, $client->name, $client->redirect_uri ?? '', (bool)$client->is_trusted); | ||||
|         // @phpstan-ignore argument.type
 | ||||
|         return new ClientEntity($client->id, $client->name, $client->redirect_uri ?: '', (bool)$client->is_trusted); | ||||
|     } | ||||
| 
 | ||||
|     public function validateClient($clientId, $clientSecret, $grantType): bool { | ||||
|         $client = $this->findModel($clientId); | ||||
|     public function validateClient(string $clientIdentifier, ?string $clientSecret, ?string $grantType): bool { | ||||
|         $client = $this->findModel($clientIdentifier); | ||||
|         if ($client === null) { | ||||
|             return false; | ||||
|         } | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Repositories; | ||||
| namespace common\components\OAuth2\Repositories; | ||||
| 
 | ||||
| use League\OAuth2\Server\Entities\ClientEntityInterface; | ||||
| use League\OAuth2\Server\Entities\ScopeEntityInterface; | ||||
| @@ -12,7 +12,7 @@ use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; | ||||
|  * To create an instance of the authorization server, you need to pass the scopes | ||||
|  * repository. This class acts as a dummy to meet this requirement. | ||||
|  */ | ||||
| class EmptyScopeRepository implements ScopeRepositoryInterface { | ||||
| final class EmptyScopeRepository implements ScopeRepositoryInterface { | ||||
| 
 | ||||
|     public function getScopeEntityByIdentifier($identifier): ?ScopeEntityInterface { | ||||
|         return null; | ||||
| @@ -20,9 +20,9 @@ class EmptyScopeRepository implements ScopeRepositoryInterface { | ||||
| 
 | ||||
|     public function finalizeScopes( | ||||
|         array $scopes, | ||||
|         $grantType, | ||||
|         string $grantType, | ||||
|         ClientEntityInterface $clientEntity, | ||||
|         $userIdentifier = null, | ||||
|         ?string $userIdentifier = null, | ||||
|         ?string $authCodeId = null, | ||||
|     ): array { | ||||
|         return $scopes; | ||||
| @@ -1,17 +1,17 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Repositories; | ||||
| namespace common\components\OAuth2\Repositories; | ||||
| 
 | ||||
| use api\components\OAuth2\Entities\ClientEntity; | ||||
| use api\components\OAuth2\Entities\ScopeEntity; | ||||
| use api\rbac\Permissions as P; | ||||
| use common\components\OAuth2\Entities\ClientEntity; | ||||
| use common\components\OAuth2\Entities\ScopeEntity; | ||||
| use League\OAuth2\Server\Entities\ClientEntityInterface; | ||||
| use League\OAuth2\Server\Entities\ScopeEntityInterface; | ||||
| use League\OAuth2\Server\Exception\OAuthServerException; | ||||
| use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; | ||||
| 
 | ||||
| class InternalScopeRepository implements ScopeRepositoryInterface { | ||||
| final class InternalScopeRepository implements ScopeRepositoryInterface { | ||||
| 
 | ||||
|     private const array ALLOWED_SCOPES = [ | ||||
|         P::CHANGE_ACCOUNT_USERNAME, | ||||
| @@ -39,9 +39,9 @@ class InternalScopeRepository implements ScopeRepositoryInterface { | ||||
|      */ | ||||
|     public function finalizeScopes( | ||||
|         array $scopes, | ||||
|         $grantType, | ||||
|         string $grantType, | ||||
|         ClientEntityInterface $clientEntity, | ||||
|         $userIdentifier = null, | ||||
|         ?string $userIdentifier = null, | ||||
|         ?string $authCodeId = null, | ||||
|     ): array { | ||||
|         if (empty($scopes)) { | ||||
| @@ -1,15 +1,15 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Repositories; | ||||
| namespace common\components\OAuth2\Repositories; | ||||
| 
 | ||||
| use api\components\OAuth2\Entities\ScopeEntity; | ||||
| use api\rbac\Permissions as P; | ||||
| use common\components\OAuth2\Entities\ScopeEntity; | ||||
| use League\OAuth2\Server\Entities\ClientEntityInterface; | ||||
| use League\OAuth2\Server\Entities\ScopeEntityInterface; | ||||
| use League\OAuth2\Server\Repositories\ScopeRepositoryInterface; | ||||
| 
 | ||||
| class PublicScopeRepository implements ScopeRepositoryInterface { | ||||
| final class PublicScopeRepository implements ScopeRepositoryInterface { | ||||
| 
 | ||||
|     public const string OFFLINE_ACCESS = 'offline_access'; | ||||
|     public const string CHANGE_SKIN = 'change_skin'; | ||||
| @@ -41,9 +41,9 @@ class PublicScopeRepository implements ScopeRepositoryInterface { | ||||
| 
 | ||||
|     public function finalizeScopes( | ||||
|         array $scopes, | ||||
|         $grantType, | ||||
|         string $grantType, | ||||
|         ClientEntityInterface $clientEntity, | ||||
|         $userIdentifier = null, | ||||
|         ?string $userIdentifier = null, | ||||
|         ?string $authCodeId = null, | ||||
|     ): array { | ||||
|         return $scopes; | ||||
| @@ -1,12 +1,12 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| 
 | ||||
| namespace api\components\OAuth2\Repositories; | ||||
| namespace common\components\OAuth2\Repositories; | ||||
| 
 | ||||
| use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; | ||||
| use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; | ||||
| 
 | ||||
| class RefreshTokenRepository implements RefreshTokenRepositoryInterface { | ||||
| final class RefreshTokenRepository implements RefreshTokenRepositoryInterface { | ||||
| 
 | ||||
|     public function getNewRefreshToken(): ?RefreshTokenEntityInterface { | ||||
|         return null; | ||||
| @@ -16,11 +16,11 @@ class RefreshTokenRepository implements RefreshTokenRepositoryInterface { | ||||
|         // Do nothing
 | ||||
|     } | ||||
| 
 | ||||
|     public function revokeRefreshToken($tokenId): void { | ||||
|     public function revokeRefreshToken(string $tokenId): void { | ||||
|         // Do nothing
 | ||||
|     } | ||||
| 
 | ||||
|     public function isRefreshTokenRevoked($tokenId): bool { | ||||
|     public function isRefreshTokenRevoked(string $tokenId): bool { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
| @@ -0,0 +1,12 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace common\components\OAuth2\ResponseTypes; | ||||
|  | ||||
| use common\components\OAuth2\CryptTrait; | ||||
| use League\OAuth2\Server\ResponseTypes\BearerTokenResponse as BaseBearerTokenResponse; | ||||
|  | ||||
| final class BearerTokenResponse extends BaseBearerTokenResponse { | ||||
|     use CryptTrait; | ||||
|  | ||||
| } | ||||
| @@ -26,6 +26,7 @@ return [ | ||||
|                     'http://' . (getenv('CHRLY_HOST') ?: 'skinsystem.ely.by'), | ||||
|                 ], | ||||
|             ], | ||||
|             League\OAuth2\Server\AuthorizationServer::class => common\components\OAuth2\AuthorizationServerFactory::build(...), | ||||
|         ], | ||||
|     ], | ||||
|     'components' => [ | ||||
|   | ||||
| @@ -5,151 +5,6 @@ parameters: | ||||
| 			count: 1 | ||||
| 			path: api/components/ErrorHandler.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Property api\\\\components\\\\OAuth2\\\\Entities\\\\ScopeEntity\\:\\:\\$identifier \\(non\\-empty\\-string\\) does not accept string\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Entities/ScopeEntity.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\AuthCodeGrant\\:\\:decrypt\\(\\) has parameter \\$encryptedData with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/AuthCodeGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\AuthCodeGrant\\:\\:encrypt\\(\\) has parameter \\$unencryptedData with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/AuthCodeGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\ClientCredentialsGrant\\:\\:decrypt\\(\\) has parameter \\$encryptedData with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/ClientCredentialsGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\ClientCredentialsGrant\\:\\:encrypt\\(\\) has parameter \\$unencryptedData with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/ClientCredentialsGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:decrypt\\(\\) has parameter \\$encryptedData with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/RefreshTokenGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:encrypt\\(\\) has parameter \\$unencryptedData with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/RefreshTokenGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:validateAccessToken\\(\\) should return array\\{client_id\\: string, refresh_token_id\\?\\: string, access_token_id\\?\\: string, scopes\\: array\\<int, string\\>\\|null, user_id\\: string\\|null, expire_time\\: int\\|null\\} but returns array\\{client_id\\: string\\|null, refresh_token_id\\: '', access_token_id\\: '', scopes\\: array\\|null, user_id\\: int\\|null, expire_time\\: null\\}\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/RefreshTokenGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:validateLegacyRefreshToken\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/RefreshTokenGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Grants\\\\RefreshTokenGrant\\:\\:validateOldRefreshToken\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Grants/RefreshTokenGrant.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\AccessTokenRepository\\:\\:isAccessTokenRevoked\\(\\) has parameter \\$tokenId with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/AccessTokenRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\AccessTokenRepository\\:\\:revokeAccessToken\\(\\) has parameter \\$tokenId with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/AccessTokenRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\AuthCodeRepository\\:\\:isAuthCodeRevoked\\(\\) has parameter \\$codeId with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/AuthCodeRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\AuthCodeRepository\\:\\:revokeAuthCode\\(\\) has parameter \\$codeId with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/AuthCodeRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\ClientRepository\\:\\:getClientEntity\\(\\) has parameter \\$clientId with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/ClientRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\ClientRepository\\:\\:validateClient\\(\\) has parameter \\$clientId with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/ClientRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\ClientRepository\\:\\:validateClient\\(\\) has parameter \\$clientSecret with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/ClientRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\ClientRepository\\:\\:validateClient\\(\\) has parameter \\$grantType with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/ClientRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Parameter \\#1 \\$id of class api\\\\components\\\\OAuth2\\\\Entities\\\\ClientEntity constructor expects non\\-empty\\-string, string given\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/ClientRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\EmptyScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$grantType with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/EmptyScopeRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\EmptyScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$userIdentifier with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/EmptyScopeRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\InternalScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$grantType with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/InternalScopeRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\InternalScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$userIdentifier with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/InternalScopeRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\PublicScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$grantType with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/PublicScopeRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\PublicScopeRepository\\:\\:finalizeScopes\\(\\) has parameter \\$userIdentifier with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/PublicScopeRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\RefreshTokenRepository\\:\\:isRefreshTokenRevoked\\(\\) has parameter \\$tokenId with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/RefreshTokenRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\Repositories\\\\RefreshTokenRepository\\:\\:revokeRefreshToken\\(\\) has parameter \\$tokenId with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/Repositories/RefreshTokenRepository.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\ResponseTypes\\\\BearerTokenResponse\\:\\:decrypt\\(\\) has parameter \\$encryptedData with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/ResponseTypes/BearerTokenResponse.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\OAuth2\\\\ResponseTypes\\\\BearerTokenResponse\\:\\:encrypt\\(\\) has parameter \\$unencryptedData with no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/OAuth2/ResponseTypes/BearerTokenResponse.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Property api\\\\components\\\\ReCaptcha\\\\Component\\:\\:\\$public has no type specified\\.$#" | ||||
| 			count: 1 | ||||
| @@ -220,11 +75,6 @@ parameters: | ||||
| 			count: 1 | ||||
| 			path: api/components/Tokens/Component.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\components\\\\Tokens\\\\TokenReader\\:\\:getScopes\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/components/Tokens/TokenReader.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Property api\\\\components\\\\User\\\\Component\\:\\:\\$loginUrl type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| @@ -305,16 +155,6 @@ parameters: | ||||
| 			count: 1 | ||||
| 			path: api/models/authentication/ConfirmEmailForm.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Property api\\\\models\\\\authentication\\\\ForgotPasswordForm\\:\\:\\$captcha has no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/models/authentication/ForgotPasswordForm.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Property api\\\\models\\\\authentication\\\\ForgotPasswordForm\\:\\:\\$login has no type specified\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/models/authentication/ForgotPasswordForm.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Property api\\\\models\\\\authentication\\\\RecoverPasswordForm\\:\\:\\$key has no type specified\\.$#" | ||||
| 			count: 1 | ||||
| @@ -695,46 +535,6 @@ parameters: | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthClientTypeForm.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:buildCompleteErrorResponse\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthProcess.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:buildIssueErrorResponse\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthProcess.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:buildScopesArray\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthProcess.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:buildSuccessResponse\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthProcess.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:complete\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthProcess.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:getScopesList\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthProcess.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:getToken\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthProcess.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\oauth\\\\models\\\\OauthProcess\\:\\:validate\\(\\) return type has no value type specified in iterable type array\\.$#" | ||||
| 			count: 1 | ||||
| 			path: api/modules/oauth/models/OauthProcess.php | ||||
|  | ||||
| 		- | ||||
| 			message: "#^Method api\\\\modules\\\\session\\\\Module\\:\\:error\\(\\) has parameter \\$message with no type specified\\.$#" | ||||
| 			count: 1 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user