From aac8911b4b114f0aa1b515e09f667ce59d8534a4 Mon Sep 17 00:00:00 2001 From: flashwave Date: Sun, 1 Dec 2024 02:50:21 +0000 Subject: [PATCH] Updated to use asymmetric access and property hooks. --- composer.json | 1 + composer.lock | 107 ++++++++++---------- public/index.php | 2 +- src/AuthzContext.php | 127 +++++++++--------------- src/OAuth2/OAuth2Routes.php | 37 +++---- src/RpcModels/Hanyuu/OAuth2AuthInfo.php | 38 ------- src/RpcModels/Hanyuu/OAuth2RfcModel.php | 16 +-- src/RpcModels/RpcModel.php | 12 +-- src/SyokuhouContext.php | 27 ++--- src/V1/V1Context.php | 8 +- src/V1/V1Routes.php | 9 +- src/V1/V1UsersRoutes.php | 12 +-- 12 files changed, 156 insertions(+), 240 deletions(-) delete mode 100644 src/RpcModels/Hanyuu/OAuth2AuthInfo.php diff --git a/composer.json b/composer.json index 91e9f0d..04daa87 100644 --- a/composer.json +++ b/composer.json @@ -5,6 +5,7 @@ } }, "require": { + "php": ">=8.4", "flashwave/index": "^0.2410", "flashii/rpcii": "^2.0", "sentry/sdk": "^4.0" diff --git a/composer.lock b/composer.lock index 0fbce1b..0883a28 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "591ddfd1386e0218b3ee6aa17e883587", + "content-hash": "8cc0e0402ab4ec0726e19e63558e6299", "packages": [ { "name": "flashii/rpcii", @@ -47,11 +47,11 @@ }, { "name": "flashwave/index", - "version": "v0.2410.191603", + "version": "v0.2410.211811", "source": { "type": "git", "url": "https://patchii.net/flash/index.git", - "reference": "17cdb4d1c239241200d7e30968122a8cd8b26509" + "reference": "40cbd35ba3855056987d2f7647f669e66f938979" }, "require": { "ext-mbstring": "*", @@ -98,7 +98,7 @@ ], "description": "Composer package for the common library for my projects.", "homepage": "https://railgun.sh/index", - "time": "2024-10-19T16:04:17+00:00" + "time": "2024-10-21T18:15:09+00:00" }, { "name": "guzzlehttp/psr7", @@ -218,28 +218,28 @@ }, { "name": "jean85/pretty-package-versions", - "version": "2.0.6", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" + "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", + "reference": "3c4e5f62ba8d7de1734312e4fff32f67a8daaf10", "shasum": "" }, "require": { - "composer-runtime-api": "^2.0.0", - "php": "^7.1|^8.0" + "composer-runtime-api": "^2.1.0", + "php": "^7.4|^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "jean85/composer-provided-replaced-stub-package": "^1.0", "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^7.5|^8.5|^9.4", - "vimeo/psalm": "^4.3" + "phpunit/phpunit": "^7.5|^8.5|^9.6", + "vimeo/psalm": "^4.3 || ^5.0" }, "type": "library", "extra": { @@ -271,9 +271,9 @@ ], "support": { "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.1.0" }, - "time": "2024-03-08T09:58:59+00:00" + "time": "2024-11-18T16:19:46+00:00" }, { "name": "psr/http-factory", @@ -623,16 +623,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -670,7 +670,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -686,20 +686,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/mime", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "caa1e521edb2650b8470918dfe51708c237f0598" + "reference": "cc84a4b81f62158c3846ac7ff10f696aae2b524d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598", - "reference": "caa1e521edb2650b8470918dfe51708c237f0598", + "url": "https://api.github.com/repos/symfony/mime/zipball/cc84a4b81f62158c3846ac7ff10f696aae2b524d", + "reference": "cc84a4b81f62158c3846ac7ff10f696aae2b524d", "shasum": "" }, "require": { @@ -754,7 +754,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.1.6" + "source": "https://github.com/symfony/mime/tree/v7.2.0" }, "funding": [ { @@ -770,20 +770,20 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:11:02+00:00" + "time": "2024-11-23T09:19:39+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85" + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/85e95eeede2d41cd146146e98c9c81d9214cae85", - "reference": "85e95eeede2d41cd146146e98c9c81d9214cae85", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", "shasum": "" }, "require": { @@ -821,7 +821,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.1.6" + "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" }, "funding": [ { @@ -837,7 +837,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-20T11:17:29+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1240,16 +1240,16 @@ }, { "name": "twig/html-extra", - "version": "v3.13.0", + "version": "v3.16.0", "source": { "type": "git", "url": "https://github.com/twigphp/html-extra.git", - "reference": "8229e750091171c1f11801a525927811c7ac5a7e" + "reference": "2086023d3ffc4bae2b1115f715d17f97fd013665" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/html-extra/zipball/8229e750091171c1f11801a525927811c7ac5a7e", - "reference": "8229e750091171c1f11801a525927811c7ac5a7e", + "url": "https://api.github.com/repos/twigphp/html-extra/zipball/2086023d3ffc4bae2b1115f715d17f97fd013665", + "reference": "2086023d3ffc4bae2b1115f715d17f97fd013665", "shasum": "" }, "require": { @@ -1292,7 +1292,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/html-extra/tree/v3.13.0" + "source": "https://github.com/twigphp/html-extra/tree/v3.16.0" }, "funding": [ { @@ -1304,20 +1304,20 @@ "type": "tidelift" } ], - "time": "2024-09-03T13:08:40+00:00" + "time": "2024-09-30T06:41:48+00:00" }, { "name": "twig/twig", - "version": "v3.14.2", + "version": "v3.16.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a" + "reference": "475ad2dc97d65d8631393e721e7e44fb544f0561" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", - "reference": "0b6f9d8370bb3b7f1ce5313ed8feb0fafd6e399a", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/475ad2dc97d65d8631393e721e7e44fb544f0561", + "reference": "475ad2dc97d65d8631393e721e7e44fb544f0561", "shasum": "" }, "require": { @@ -1328,6 +1328,7 @@ "symfony/polyfill-php81": "^1.29" }, "require-dev": { + "phpstan/phpstan": "^2.0", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, @@ -1371,7 +1372,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.14.2" + "source": "https://github.com/twigphp/Twig/tree/v3.16.0" }, "funding": [ { @@ -1383,22 +1384,22 @@ "type": "tidelift" } ], - "time": "2024-11-07T12:36:22+00:00" + "time": "2024-11-29T08:27:05+00:00" } ], "packages-dev": [ { "name": "phpstan/phpstan", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d" + "reference": "46b4d3529b12178112d9008337beda0cc2a1a6b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d", - "reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46b4d3529b12178112d9008337beda0cc2a1a6b4", + "reference": "46b4d3529b12178112d9008337beda0cc2a1a6b4", "shasum": "" }, "require": { @@ -1443,15 +1444,17 @@ "type": "github" } ], - "time": "2024-11-11T15:43:04+00:00" + "time": "2024-11-28T22:19:37+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": { + "php": ">=8.4" + }, + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/public/index.php b/public/index.php index 618898f..1e21760 100644 --- a/public/index.php +++ b/public/index.php @@ -18,4 +18,4 @@ set_exception_handler(function(\Throwable $ex) { exit; }); -$ctx->getRouter()->dispatch(); +$ctx->router->dispatch(); diff --git a/src/AuthzContext.php b/src/AuthzContext.php index de41e47..8638201 100644 --- a/src/AuthzContext.php +++ b/src/AuthzContext.php @@ -5,109 +5,85 @@ use RuntimeException; use RPCii\Client\RpcClient; class AuthzContext { - private bool $authed = false; - private string $error = ''; - private string $method = ''; - private string $type = ''; - private string $userId = ''; - private string $appId = ''; - private ?array $scope = null; - private ?int $expires = null; + public private(set) bool $authed = false; + public private(set) string $error = ''; + public private(set) string $method = ''; + public private(set) string $type = ''; + public private(set) string $userId = ''; + public private(set) string $appId = ''; + private ?array $scopeRaw = null; + private ?int $expiresAtRaw = null; public function __construct( private RpcClient $rpcClient ) {} - public function hasAuthed(): bool { - return $this->authed; + public bool $hasError { + get => $this->error !== ''; } - public function hasError(): bool { - return $this->error !== ''; + public bool $isBasicAuth { + get => strcasecmp('basic', $this->method) === 0; } - public function getError(): string { - return $this->error; + public bool $isBearerAuth { + get => strcasecmp('bearer', $this->method) === 0; } - public function getMethod(): string { - return $this->method; + public bool $isMisuzuAuth { + get => strcasecmp('misuzu', $this->method) === 0; } - public function isBasicAuth(): bool { - return strcasecmp('basic', $this->method) === 0; + public bool $isRealUser { + get => strcasecmp('user', $this->type) === 0; } - public function isBearerAuth(): bool { - return strcasecmp('bearer', $this->method) === 0; + public bool $isAppUser { + get => strcasecmp('app', $this->type) === 0; } - public function isMisuzuAuth(): bool { - return strcasecmp('misuzu', $this->method) === 0; + public bool $isUser { + get => $this->isRealUser + || $this->isAppUser; } - public function getType(): string { - return $this->type; + public bool $isPublicApp { + get => strcasecmp('pubapp', $this->type) === 0; } - public function isRealUser(): bool { - return strcasecmp('user', $this->type) === 0; + public bool $isConfidentialApp { + get => strcasecmp('confapp', $this->type) === 0; } - public function isAppUser(): bool { - return strcasecmp('app', $this->type) === 0; + public bool $isApp { + get => $this->isPublicApp + || $this->isConfidentialApp; } - public function isUser(): bool { - return $this->isRealUser() - || $this->isAppUser(); + public bool $hasWildcardScope { + get => $this->scopeRaw === null; } - public function isPublicApp(): bool { - return strcasecmp('pubapp', $this->type) === 0; + public string $scopeString { + get => $this->scopeRaw === null ? '' : implode(' ', $this->scopeRaw); } - public function isConfidentialApp(): bool { - return strcasecmp('confapp', $this->type) === 0; - } - - public function isApp(): bool { - return $this->isPublicApp() - || $this->isConfidentialApp(); - } - - public function getAppId(): string { - return $this->appId; - } - - public function getUserId(): string { - return $this->userId; - } - - public function hasWildcardScope(): bool { - return $this->scope === null; - } - - public function getScopeString(): string { - return $this->scope === null ? '' : implode(' ', $this->scope); - } - - public function getScopeArray(): array { - return $this->scope ?? []; + public array $scope { + get => $this->scopeRaw ?? []; } public function hasScope(string $scope): bool { - return $this->scope === null - || in_array($scope, $this->scope); + return $this->scopeRaw === null + || in_array($scope, $this->scopeRaw); } - public function getExpiresAt(): int { - return $this->expires ?? PHP_INT_MAX; + public int $expiresAt { + get => $this->expiresAtRaw ?? PHP_INT_MAX; } - public function hasExpired(): bool { - return $this->expires !== null - && $this->expires <= time(); + public bool $expired { + get => $this->expiresAtRaw !== null + && $this->expiresAtRaw <= time(); } private function handleRpcResponse(mixed $info): void { @@ -132,23 +108,10 @@ class AuthzContext { $this->appId = $info['app']; if(array_key_exists('scope', $info) && is_array($info['scope'])) - $this->scope = $info['scope']; + $this->scopeRaw = $info['scope']; if(array_key_exists('expires', $info) && is_int($info['expires'])) - $this->expires = $info['expires']; - } - - public function dump(): array { - return [ - 'authed' => $this->authed, - 'error' => $this->error, - 'method' => $this->method, - 'type' => $this->type, - 'user' => $this->userId, - 'app' => $this->appId, - 'scope' => $this->scope, - 'expires' => $this->expires, - ]; + $this->expiresAtRaw = $info['expires']; } private function attemptBasicAppAuthInternal(string $remoteAddr, string $clientId, string $clientSecret = ''): void { diff --git a/src/OAuth2/OAuth2Routes.php b/src/OAuth2/OAuth2Routes.php index 2c94188..b258dce 100644 --- a/src/OAuth2/OAuth2Routes.php +++ b/src/OAuth2/OAuth2Routes.php @@ -3,7 +3,7 @@ namespace Syokuhou\OAuth2; use RuntimeException; use Syokuhou\SyokuhouContext; -use Syokuhou\RpcModels\Hanyuu\{OAuth2AuthInfo,OAuth2RfcModel}; +use Syokuhou\RpcModels\Hanyuu\OAuth2RfcModel; use Index\Config\Config; use Index\Http\Routing\{HandlerAttribute,HttpGet,HttpOptions,HttpPost,Router,RouteHandler,RouteHandlerTrait}; @@ -21,7 +21,7 @@ class OAuth2Routes implements RouteHandler { ) {} public function registerRoutes(Router $router): void { - $router->use('/', $this->ctx->getAuthzContext()->basicAppAuthMiddleware(...)); + $router->use('/', $this->ctx->authz->basicAppAuthMiddleware(...)); HandlerAttribute::register($router, $this); } @@ -62,8 +62,7 @@ class OAuth2Routes implements RouteHandler { public function postRequestAuthorise($response, $request) { $response->setHeader('Cache-Control', 'no-store'); - $authz = $this->ctx->getAuthzContext(); - if($authz->getError() === 'secret') + if($this->ctx->authz->error === 'secret') return self::filter($response, [ 'error' => 'invalid_client', 'error_description' => 'Provided client secret is not correct for this application.', @@ -75,16 +74,16 @@ class OAuth2Routes implements RouteHandler { 'error_description' => 'Your request must use content type application/x-www-form-urlencoded.', ]); - $rpc = $this->ctx->getRpcClient(); + $rpc = $this->ctx->rpc; $content = $request->getContent(); - if(!$authz->hasAuthed()) - $authz->attemptBasicAppAuth( + if(!$this->ctx->authz->authed) + $this->ctx->authz->attemptBasicAppAuth( (string)filter_input(INPUT_SERVER, 'REMOTE_ADDR'), (string)$content->getParam('client_id') ); - if(!$authz->isApp()) + if(!$this->ctx->authz->isApp) return self::filter($response, [ 'error' => 'invalid_client', 'error_description' => 'App authentication failed.', @@ -92,20 +91,20 @@ class OAuth2Routes implements RouteHandler { try { $reqInfo = new OAuth2RfcModel($rpc->action('hanyuu:oauth2:createAuthoriseRequest', [ - 'appId' => $authz->getAppId(), + 'appId' => $this->ctx->authz->appId, 'scope' => (string)$content->getParam('scope'), ])); } catch(RuntimeException $ex) { $reqInfo = null; } - if($reqInfo === null || ($reqInfo->hasError() && !in_array($reqInfo->getError(), self::REQ_AUTH_ERRORS))) + if($reqInfo === null || ($reqInfo->hasError && !in_array($reqInfo->error, self::REQ_AUTH_ERRORS))) return self::filter($response, [ 'error' => 'server_error', 'error_description' => 'Authorisation server gave unexpected response.', ]); - return self::filter($response, $reqInfo->getRaw()); + return self::filter($response, $reqInfo->raw); } #[HttpOptions('/token')] @@ -142,27 +141,26 @@ class OAuth2Routes implements RouteHandler { 'error_description' => 'Your request must use content type application/x-www-form-urlencoded.', ]); - $rpc = $this->ctx->getRpcClient(); + $rpc = $this->ctx->rpc; $content = $request->getContent(); - $authz = $this->ctx->getAuthzContext(); $authzHeader = true; - if(!$authz->hasAuthed()) { + if(!$this->ctx->authz->authed) { $authzHeader = false; - $authz->attemptBasicAppAuth( + $this->ctx->authz->attemptBasicAppAuth( (string)filter_input(INPUT_SERVER, 'REMOTE_ADDR'), (string)$content->getParam('client_id'), (string)$content->getParam('client_secret') ); } - if(!$authz->isApp()) + if(!$this->ctx->authz->isApp) return self::filter($response, [ 'error' => 'invalid_client', 'error_description' => 'App authentication failed.', ]); - if($authz->getError() === 'secret') + if($this->ctx->authz->error === 'secret') return self::filter($response, [ 'error' => 'invalid_client', 'error_description' => 'Provided client secret is not correct for this application.' @@ -170,7 +168,10 @@ class OAuth2Routes implements RouteHandler { try { $name = ''; - $args = ['appId' => $authz->getAppId(), 'isAuthed' => $authz->isConfidentialApp()]; + $args = [ + 'appId' => $this->ctx->authz->appId, + 'isAuthed' => $this->ctx->authz->isConfidentialApp + ]; switch($content->getParam('grant_type')) { case 'authorization_code': diff --git a/src/RpcModels/Hanyuu/OAuth2AuthInfo.php b/src/RpcModels/Hanyuu/OAuth2AuthInfo.php deleted file mode 100644 index 29a213a..0000000 --- a/src/RpcModels/Hanyuu/OAuth2AuthInfo.php +++ /dev/null @@ -1,38 +0,0 @@ -getString('method'); - } - - public function isAuthed(): bool { - return $this->getBoolean('authed'); - } - - public function getAppId(): string { - return $this->getString('app_id'); - } - - public function hasUserId(): bool { - return $this->hasValue('user_id'); - } - - public function isAppUser(): bool { - return $this->getMethod() === 'basic' || $this->getUserId() === '0'; - } - - public function getUserId(): string { - return $this->getString('user_id'); - } - - public function getScope(): string { - return $this->getString('scope'); - } - - public function getExpiresIn(): int { - return $this->getInteger('expires_in'); - } -} diff --git a/src/RpcModels/Hanyuu/OAuth2RfcModel.php b/src/RpcModels/Hanyuu/OAuth2RfcModel.php index 22b1f40..d9bfdd9 100644 --- a/src/RpcModels/Hanyuu/OAuth2RfcModel.php +++ b/src/RpcModels/Hanyuu/OAuth2RfcModel.php @@ -4,19 +4,19 @@ namespace Syokuhou\RpcModels\Hanyuu; use Syokuhou\RpcModels\RpcModel; class OAuth2RfcModel extends RpcModel { - public function hasErrorDescription(): bool { - return $this->hasValue('error_description'); + public bool $hasErrorDescription { + get => $this->hasValue('error_description'); } - public function getErrorDescription(): string { - return $this->getString('error_description'); + public string $errorDescription { + get => $this->getString('error_description'); } - public function hasErrorUri(): bool { - return $this->hasValue('error_uri'); + public bool $hasErrorUri { + get => $this->hasValue('error_uri'); } - public function getErrorUri(): string { - return $this->getString('error_uri'); + public string $errorUri { + get => $this->getString('error_uri'); } } diff --git a/src/RpcModels/RpcModel.php b/src/RpcModels/RpcModel.php index 8d4e4fb..5a01b7f 100644 --- a/src/RpcModels/RpcModel.php +++ b/src/RpcModels/RpcModel.php @@ -8,16 +8,16 @@ abstract class RpcModel { $this->info = $info; } - public function hasError(): bool { - return $this->hasValue('error'); + public bool $hasError { + get => $this->hasValue('error'); } - public function getError(): string { - return $this->getString('error'); + public string $error { + get => $this->getString('error'); } - public function getRaw(): array { - return $this->info; + public array $raw { + get => $this->info; } protected function hasValue(string $name): bool { diff --git a/src/SyokuhouContext.php b/src/SyokuhouContext.php index e911d04..c96d720 100644 --- a/src/SyokuhouContext.php +++ b/src/SyokuhouContext.php @@ -2,21 +2,20 @@ namespace Syokuhou; use RuntimeException; -use Syokuhou\RpcModels\Hanyuu\OAuth2AuthInfo; use Index\Config\Config; use Index\Http\Routing\{HttpRouter,Router}; class SyokuhouContext { - private RpcClientWrapper $rpcWrapper; - private HttpRouter $router; - private AuthzContext $authz; + public private(set) RpcClientWrapper $rpc; + public private(set) AuthzContext $authz; + public private(set) HttpRouter $router; public function __construct(Config $config) { - $this->rpcWrapper = new RpcClientWrapper; - $this->rpcWrapper->createHmacConfig($config, 'hanyuu'); - $this->rpcWrapper->createHmacConfig($config, 'misuzu'); + $this->rpc = new RpcClientWrapper; + $this->rpc->createHmacConfig($config, 'hanyuu'); + $this->rpc->createHmacConfig($config, 'misuzu'); - $this->authz = new AuthzContext($this->rpcWrapper); + $this->authz = new AuthzContext($this->rpc); $this->router = new HttpRouter( errorHandler: 'plain', @@ -30,18 +29,6 @@ class SyokuhouContext { $this->router->scopeTo('/v1')->register(new V1\V1Routes(new V1\V1Context($this))); } - public function getRpcClient(): RpcClientWrapper { - return $this->rpcWrapper; - } - - public function getRouter(): Router { - return $this->router; - } - - public function getAuthzContext(): AuthzContext { - return $this->authz; - } - public function handleAcceptHeader($response, $request) { $accept = HttpAcceptHeader::parse($request->getHeaderLine('Accept')); $contentHandler = new SyokuhouContentHandler($accept); diff --git a/src/V1/V1Context.php b/src/V1/V1Context.php index 0bf30c0..0959cce 100644 --- a/src/V1/V1Context.php +++ b/src/V1/V1Context.php @@ -9,11 +9,11 @@ class V1Context { private SyokuhouContext $ctx ) {} - public function getRpcClient(): RpcClient { - return $this->ctx->getRpcClient(); + public RpcClient $rpc { + get => $this->ctx->rpc; } - public function getAuthzContext(): AuthzContext { - return $this->ctx->getAuthzContext(); + public AuthzContext $authz { + get => $this->ctx->authz; } } diff --git a/src/V1/V1Routes.php b/src/V1/V1Routes.php index 5d5e395..c1b25d7 100644 --- a/src/V1/V1Routes.php +++ b/src/V1/V1Routes.php @@ -9,17 +9,16 @@ class V1Routes implements RouteHandler { ) {} public function registerRoutes(Router $router): void { - $authz = $this->ctx->getAuthzContext(); - $router->use('/', $authz->bearerTokenAuthMiddleware(...)); - $router->use('/', $authz->misuzuTokenAuthMiddleware(...)); + $router->use('/', $this->ctx->authz->bearerTokenAuthMiddleware(...)); + $router->use('/', $this->ctx->authz->misuzuTokenAuthMiddleware(...)); $router->get('/', fn() => ['status' => 'operational']); $router->scopeTo('/emotes')->register( - new V1EmotesRoutes($this->ctx->getRpcClient()->scopeTo('misuzu:emotes:')) + new V1EmotesRoutes($this->ctx->rpc->scopeTo('misuzu:emotes:')) ); - $usersRoutes = new V1UsersRoutes($this->ctx, $this->ctx->getRpcClient()->scopeTo('misuzu:users:')); + $usersRoutes = new V1UsersRoutes($this->ctx, $this->ctx->rpc->scopeTo('misuzu:users:')); $router->options('/me', $usersRoutes->getMe(...)); $router->get('/me', $usersRoutes->getMe(...)); $router->scopeTo('/users')->register($usersRoutes); diff --git a/src/V1/V1UsersRoutes.php b/src/V1/V1UsersRoutes.php index 51b10d0..9753f53 100644 --- a/src/V1/V1UsersRoutes.php +++ b/src/V1/V1UsersRoutes.php @@ -17,19 +17,19 @@ class V1UsersRoutes implements RouteHandler { $response->setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET'); $response->setHeader('Cache-Control', 'no-store'); - $authz = $this->ctx->getAuthzContext(); - if(!$authz->hasScope('identify') && !$authz->hasScope('beans')) + if(!$this->ctx->authz->hasScope('identify') + && !$this->ctx->authz->hasScope('beans')) return 403; - if($authz->isAppUser()) { + if($this->ctx->authz->isAppUser) { // TODO: what should app users even look like? return 501; } - if($authz->isRealUser()) { + if($this->ctx->authz->isRealUser) { $userInfo = $this->rpc->query('getUser', [ - 'userId' => $authz->getUserId(), - 'includeEMailAddress' => $authz->hasScope('identify:email'), + 'userId' => $this->ctx->authz->userId, + 'includeEMailAddress' => $this->ctx->authz->hasScope('identify:email'), ]); if(!is_array($userInfo)) return 500;