diff --git a/src/Api.php b/src/Api.php index e57e882..d2985cd 100644 --- a/src/Api.php +++ b/src/Api.php @@ -13,8 +13,6 @@ use Siteworxpro\App\Controllers\AccessTokenController; use Siteworxpro\App\Controllers\AuthorizeController; use Siteworxpro\App\Controllers\CapabilitiesController; use Siteworxpro\App\Controllers\HealthcheckController; -use Siteworxpro\App\Controllers\IndexController; -use Siteworxpro\App\Controllers\OpenApiController; use Siteworxpro\App\Controllers\OpenIdController; use Siteworxpro\App\Http\JsonResponseFactory; use Siteworxpro\App\Http\Middleware\CorsMiddleware; diff --git a/src/Cli/ClimateOutput.php b/src/Cli/ClimateOutput.php index 0c5152d..39e1ec0 100644 --- a/src/Cli/ClimateOutput.php +++ b/src/Cli/ClimateOutput.php @@ -73,12 +73,6 @@ use Symfony\Component\Console\Output\OutputInterface; * @method mixed progress(integer $total = null) * @method Spinner spinner(string $label = null, string ...$characters = null) * @method mixed padding(integer $length = 0, string $char = '.') - * @method mixed input(string $prompt, Util\Reader\ReaderInterface $reader = null) - * @method mixed confirm(string $prompt, Util\Reader\ReaderInterface $reader = null) - * @method mixed password(string $prompt, Util\Reader\ReaderInterface $reader = null) - * @method mixed checkboxes(string $prompt, array $options, Util\Reader\ReaderInterface $reader = null) - * @method mixed radio(string $prompt, array $options, Util\Reader\ReaderInterface $reader = null) - * @method mixed animation(string $art, TerminalObject\Helper\Sleeper $sleeper = null) * @method mixed columns(array $data, $column_count = null) * @method mixed clear() * @method CLImate clearLine() @@ -146,6 +140,9 @@ class ClimateOutput extends ConsoleSectionOutput implements ConsoleOutputInterfa $this->verbosity = $level; } + /** + * @return int + */ public function getVerbosity(): int { return $this->verbosity; diff --git a/src/Cli/Commands/OAuth/ListClients.php b/src/Cli/Commands/OAuth/ListClients.php index fa8e9fc..d876f64 100644 --- a/src/Cli/Commands/OAuth/ListClients.php +++ b/src/Cli/Commands/OAuth/ListClients.php @@ -21,7 +21,12 @@ class ListClients extends Command $this->addArgument('client-id', null, 'Filter by client ID'); } - public function __invoke(ArgvInput|InputInterface $input, ClimateOutput|OutputInterface $output): int + /** + * @param ArgvInput|InputInterface $input + * @param ClimateOutput $output + * @return int + */ + public function __invoke(ArgvInput|InputInterface $input, $output): int { if ($input->getArgument('client-id')) { $client = Client::find($input->getArgument('client-id')); @@ -57,7 +62,7 @@ class ListClients extends Command $outputArray = []; - $clients->map(function (Client $client) use (&$outputArray, $input) { + $clients->map(function (Client $client) use (&$outputArray) { $outputValues = [ 'ID' => $client->id, 'Name' => $client->name, diff --git a/src/Cli/Commands/User/Add.php b/src/Cli/Commands/User/Add.php index a54983d..3e521e0 100644 --- a/src/Cli/Commands/User/Add.php +++ b/src/Cli/Commands/User/Add.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Siteworxpro\App\Cli\Commands\User; +use Illuminate\Database\Eloquent\Collection; use Siteworxpro\App\Cli\Commands\Command; use Siteworxpro\App\Models\ClientUser; use Siteworxpro\App\Models\User; @@ -18,6 +19,7 @@ class Add extends Command { public function __invoke($input, $output): int { + /** @var Collection $clients */ $clients = Client::whereJsonContains('grant_types', 'authorization_code') ->get(['id', 'name']); @@ -51,6 +53,7 @@ class Add extends Command $email = $helper->ask($input, $output, $emailQuestion); + /** @var User| null $user */ $user = User::where('email', $email)->first(); if ($user) { $output->yellow('A user with this email already exists. Associating the user with the client.'); diff --git a/src/CommandBus/Handlers/OAuth/CreateClient.php b/src/CommandBus/Handlers/OAuth/CreateClient.php index 134a1b3..8381d9b 100644 --- a/src/CommandBus/Handlers/OAuth/CreateClient.php +++ b/src/CommandBus/Handlers/OAuth/CreateClient.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Siteworxpro\App\CommandBus\Handlers\OAuth; +use Illuminate\Support\Collection; use Siteworxpro\App\Attributes\CommandBus\HandlesCommand; use Siteworxpro\App\CommandBus\Commands\Command; use Siteworxpro\App\CommandBus\Exceptions\CommandHandlerException; @@ -22,7 +23,7 @@ class CreateClient extends CommandHandler $client = new Client(); $client->name = $command->getClientName(); $client->description = $command->getClientDescription(); - $client->grant_types = $command->getClientGrants(); + $client->grant_types = new Collection($command->getClientGrants()); // @phpstan-ignore-line assign.propertyType $client->save(); diff --git a/src/Controllers/AuthorizeController.php b/src/Controllers/AuthorizeController.php index 7038782..a10cda8 100644 --- a/src/Controllers/AuthorizeController.php +++ b/src/Controllers/AuthorizeController.php @@ -103,7 +103,7 @@ final class AuthorizeController extends Controller if ( isset($request->getCookieParams()['s']) && - Redis::exists('session:' . $request->getCookieParams()['s'] ?? '') + Redis::exists('session:' . $request->getCookieParams()['s']) ) { $s = $request->getCookieParams()['s']; } else { diff --git a/src/Controllers/IndexController.php b/src/Controllers/IndexController.php deleted file mode 100644 index dfed66a..0000000 --- a/src/Controllers/IndexController.php +++ /dev/null @@ -1,66 +0,0 @@ -getQueryParams()['name'] ?? 'Guest'); - $greeting = CommandBus::handle($command); - - return JsonResponseFactory::createJsonResponse(new GenericResponse('Server is running. ' . $greeting)); - } - - /** - * Handles the POST request for the index route. - * - * @throws \JsonException - */ - #[Guards\Jwt] - #[Guards\Scope(['post.index'])] - #[OA\Post(path: '/', security: [new TokenSecurity()], tags: ['Examples'])] - #[OA\Response( - response: '200', - description: 'An Example Response', - content: new OA\JsonContent(ref: '#/components/schemas/GenericResponse') - )] - #[UnauthorizedResponse] - public function post(ServerRequest $request): ResponseInterface - { - return JsonResponseFactory::createJsonResponse(new GenericResponse('POST request received')); - } -} diff --git a/src/GrpcHandlers/GreeterHandler.php b/src/GrpcHandlers/GreeterHandler.php index 3c124ab..73c8217 100644 --- a/src/GrpcHandlers/GreeterHandler.php +++ b/src/GrpcHandlers/GreeterHandler.php @@ -7,18 +7,15 @@ namespace Siteworxpro\App\GrpcHandlers; use GRPC\Greeter\GreeterInterface; use GRPC\Greeter\HelloReply; use GRPC\Greeter\HelloRequest; -use Siteworxpro\App\CommandBus\Commands\ExampleCommand; -use Siteworxpro\App\Services\Facades\CommandBus; use Spiral\RoadRunner\GRPC; class GreeterHandler implements GreeterInterface { public function SayHello(GRPC\ContextInterface $ctx, HelloRequest $in): HelloReply // phpcs:ignore { - $command = new ExampleCommand($in->getName()); $reply = new HelloReply(); - $reply->setMessage(CommandBus::handle($command)); + $reply->setMessage('Hello ' . $in->getName()); return $reply; } diff --git a/src/Models/Model.php b/src/Models/Model.php index a7f444d..8b7514c 100644 --- a/src/Models/Model.php +++ b/src/Models/Model.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Siteworxpro\App\Models; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model as ORM; use Siteworxpro\App\Helpers\Ulid; @@ -12,8 +13,8 @@ use Siteworxpro\App\Helpers\Ulid; * * @package Siteworxpro\App\Models * @method static static|null find(string $id, array $columns = ['*']) - * @method static where(string $column, string $operator = null, string $value = null, string $boolean = 'and') - * @method static whereJsonContains(string $column, mixed $value, string $boolean = 'and', bool $not = false) + * @method static Builder where(string $column, string $operator = null, string $value = null, string $boolean = 'and') + * @method static Builder whereJsonContains(string $column, mixed $value, string $boolean = 'and', bool $not = false) */ abstract class Model extends ORM { diff --git a/src/OAuth/AccessTokenRepository.php b/src/OAuth/AccessTokenRepository.php index 29db034..00a8a52 100644 --- a/src/OAuth/AccessTokenRepository.php +++ b/src/OAuth/AccessTokenRepository.php @@ -29,16 +29,15 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface public function persistNewAccessToken(AccessTokenEntityInterface | AccessToken $accessTokenEntity): void { - $accessTokenEntity->save(); + if ($accessTokenEntity instanceof AccessToken) { + $accessTokenEntity->save(); + } } public function revokeAccessToken(string $tokenId): void { $accessToken = AccessToken::find($tokenId); - - if ($accessToken) { - $accessToken->delete(); - } + $accessToken?->delete(); } public function isAccessTokenRevoked(string $tokenId): bool diff --git a/src/OAuth/AuthCodeRepository.php b/src/OAuth/AuthCodeRepository.php index 1010540..8f33226 100644 --- a/src/OAuth/AuthCodeRepository.php +++ b/src/OAuth/AuthCodeRepository.php @@ -18,12 +18,11 @@ class AuthCodeRepository implements AuthCodeRepositoryInterface public function persistNewAuthCode(AuthCodeEntityInterface | AuthorizationCode $authCodeEntity): void { - $authCodeEntity->save(); + if ($authCodeEntity instanceof AuthorizationCode) { + $authCodeEntity->save(); + } } - /** - * @throws InvalidArgumentException - */ public function revokeAuthCode(string $codeId): void { $authCode = AuthorizationCode::find($codeId); diff --git a/src/OAuth/Entities/AccessToken.php b/src/OAuth/Entities/AccessToken.php index ac02f42..6161807 100644 --- a/src/OAuth/Entities/AccessToken.php +++ b/src/OAuth/Entities/AccessToken.php @@ -17,11 +17,11 @@ class AccessToken extends RedisModel implements AccessTokenEntityInterface { use AccessTokenTrait; - private Client |null $client = null; + private ClientEntityInterface | Client |null $client = null; private string | null $userIdentifier = null; - /** @var ScopeEntityInterface|Scope[] */ + /** @var ScopeEntityInterface[]|Scope[] */ private array $scopes = []; public function getClient(): ClientEntityInterface @@ -29,7 +29,10 @@ class AccessToken extends RedisModel implements AccessTokenEntityInterface return $this->client; } - private function convertToJWT(): Token + /** + * @return Token + */ + private function convertToJWT(): Token // @phpstan-ignore method.unused { $this->initJwtConfiguration(); diff --git a/src/OAuth/Entities/AuthorizationCode.php b/src/OAuth/Entities/AuthorizationCode.php index 1349690..c567878 100644 --- a/src/OAuth/Entities/AuthorizationCode.php +++ b/src/OAuth/Entities/AuthorizationCode.php @@ -15,7 +15,7 @@ class AuthorizationCode extends RedisModel implements AuthCodeEntityInterface { use AuthCodeTrait; - private Client | null $client = null; + private ClientEntityInterface | Client | null $client = null; private string | null $userIdentifier = null; diff --git a/src/OAuth/Entities/Client.php b/src/OAuth/Entities/Client.php index c0be3a5..6646321 100644 --- a/src/OAuth/Entities/Client.php +++ b/src/OAuth/Entities/Client.php @@ -35,7 +35,7 @@ use Siteworxpro\App\OAuth\ScopeRepository; * @property string $description * @property string $private_key * @property string $encryption_key - * @property Collection $grant_types + * @property Collection $grant_types * @property bool $confidential * * @property-read ClientCapabilities $capabilities @@ -66,7 +66,10 @@ class Client extends Model implements ClientEntityInterface public static function byClientId(string $clientId): ?Client { - return self::where('client_id', $clientId)->first(); + /** @var Client|null $client */ + $client = self::where('client_id', $clientId)->first(); + + return $client; } /** diff --git a/src/OAuth/Entities/RefreshToken.php b/src/OAuth/Entities/RefreshToken.php index 282a704..d7758c0 100644 --- a/src/OAuth/Entities/RefreshToken.php +++ b/src/OAuth/Entities/RefreshToken.php @@ -11,7 +11,7 @@ use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; class RefreshToken extends RedisModel implements RefreshTokenEntityInterface { - private AccessToken | null $accessToken = null; + private AccessTokenEntityInterface | AccessToken | null $accessToken = null; protected static function getRedisPrefix(): string { diff --git a/src/OAuth/RefreshTokenRepository.php b/src/OAuth/RefreshTokenRepository.php index 47af82b..9eec4fe 100644 --- a/src/OAuth/RefreshTokenRepository.php +++ b/src/OAuth/RefreshTokenRepository.php @@ -18,12 +18,11 @@ class RefreshTokenRepository implements RefreshTokenRepositoryInterface public function persistNewRefreshToken(RefreshTokenEntityInterface | RefreshToken $refreshTokenEntity): void { - $refreshTokenEntity->save(); + if ($refreshTokenEntity instanceof RefreshToken) { + $refreshTokenEntity->save(); + } } - /** - * @throws InvalidArgumentException - */ public function revokeRefreshToken(string $tokenId): void { $token = RefreshToken::find($tokenId); diff --git a/src/OAuth/ScopeRepository.php b/src/OAuth/ScopeRepository.php index 92c90e9..cdd552f 100644 --- a/src/OAuth/ScopeRepository.php +++ b/src/OAuth/ScopeRepository.php @@ -13,7 +13,10 @@ class ScopeRepository implements ScopeRepositoryInterface { public function getScopeEntityByIdentifier(string $identifier): ?ScopeEntityInterface { - return Scope::where('name', $identifier)->first(); + /** @var Scope $scope */ + $scope = Scope::where('name', $identifier)->first(); + + return $scope; } public function finalizeScopes( diff --git a/tests/CommandBus/AttributeLocatorTest.php b/tests/CommandBus/AttributeLocatorTest.php index 2b71b30..9692f59 100644 --- a/tests/CommandBus/AttributeLocatorTest.php +++ b/tests/CommandBus/AttributeLocatorTest.php @@ -6,16 +6,16 @@ namespace Siteworxpro\Tests\CommandBus; use League\Tactician\Exception\CanNotInvokeHandlerException; use Siteworxpro\App\CommandBus\AttributeLocator; -use Siteworxpro\App\CommandBus\Commands\ExampleCommand; -use Siteworxpro\App\CommandBus\Handlers\ExampleHandler; use Siteworxpro\Tests\Unit; class AttributeLocatorTest extends Unit { private const array HANDLERS = [ - ExampleCommand::class => ExampleHandler::class, ]; + /** + * @return void + */ public function testResolvesFiles(): void { $attributeLocator = new AttributeLocator(); diff --git a/tests/CommandBus/Handlers/ExampleHandlerTest.php b/tests/CommandBus/Handlers/ExampleHandlerTest.php deleted file mode 100644 index 7d33bd6..0000000 --- a/tests/CommandBus/Handlers/ExampleHandlerTest.php +++ /dev/null @@ -1,32 +0,0 @@ -assertEquals('test payload', $command->getName()); - - $handler = new ExampleHandler(); - $result = $handler($command); - $this->assertEquals('Hello, test payload!', $result); - } - - public function testThrowsException(): void - { - $class = new readonly class extends Command - { - }; - - $this->expectException(\TypeError::class); - $handler = new ExampleHandler(); - $handler($class); - } -} diff --git a/tests/Controllers/IndexControllerTest.php b/tests/Controllers/IndexControllerTest.php deleted file mode 100644 index 842c55d..0000000 --- a/tests/Controllers/IndexControllerTest.php +++ /dev/null @@ -1,48 +0,0 @@ -assertTrue(true); - - $this->getContainer()->bind(CommandBus::class, function () { - return \Mockery::mock(CommandBus::class) - ->shouldReceive('handle') - ->andReturn('Hello World') - ->getMock(); - }); - - $controller = new IndexController(); - - $response = $controller->get($this->getMockRequest()); - - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('{"message":"Server is running. Hello World"}', (string)$response->getBody()); - } - - /** - * @throws \JsonException - */ - public function testPost(): void - { - $this->assertTrue(true); - - $controller = new IndexController(); - - $response = $controller->post($this->getMockRequest()); - - $this->assertEquals(200, $response->getStatusCode()); - $this->assertEquals('{"message":"POST request received"}', (string)$response->getBody()); - } -} diff --git a/tests/Helpers/UlidTest.php b/tests/Helpers/UlidTest.php index 592d1f4..38f0e2c 100644 --- a/tests/Helpers/UlidTest.php +++ b/tests/Helpers/UlidTest.php @@ -14,6 +14,6 @@ class UlidTest extends Unit { $ulid = Ulid::generate(); $this->assertIsString($ulid); - $this->assertEquals(16, strlen($ulid)); + $this->assertEquals(26, strlen($ulid)); } }