diff --git a/VERSION b/VERSION index 8839305d..91d54fb4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -20250202.1 +20250202.2 diff --git a/src/Hanyuu/HanyuuRpcHandler.php b/src/Hanyuu/HanyuuRpcHandler.php deleted file mode 100644 index e7357325..00000000 --- a/src/Hanyuu/HanyuuRpcHandler.php +++ /dev/null @@ -1,169 +0,0 @@ - $attrs - * @return array{name: string, attrs: array} - */ - private static function createPayload(string $name, array $attrs = []): array { - $payload = ['name' => $name, 'attrs' => []]; - foreach($attrs as $name => $value) { - if($value === null) - continue; - $payload['attrs'][(string)$name] = $value; - } - - return $payload; - } - - /** @return array{name: string, attrs: array{code: string, text?: string}} */ - private static function createErrorPayload(string $code, ?string $text = null): array { - $attrs = ['code' => $code]; - if($text !== null && $text !== '') - $attrs['text'] = $text; - - return self::createPayload('error', $attrs); - } - - private function canImpersonateUserId(UserInfo $impersonator, string $targetId): bool { - if($impersonator->super) - return true; - - return in_array( - $targetId, - $this->impersonateConfig->getArray(sprintf('allow.u%s', $impersonator->id)), - true - ); - } - - /** @return array{name: string, attrs: array} */ - #[RpcAction('mszhau:authCheck')] - public function procAuthCheck(string $method, string $remoteAddr, string $token, string $avatars = ''): array { - if($method !== 'Misuzu') - return self::createErrorPayload('auth:check:method', 'Requested auth method is not supported.'); - - if(filter_var($remoteAddr, FILTER_VALIDATE_IP) === false) - return self::createErrorPayload('auth:check:remote_addr', 'Provided remote address is not in a valid format.'); - - $avatarResolutions = trim($avatars); - if($avatarResolutions === '') { - $avatarResolutions = []; - } else { - $avatarResolutions = explode(',', $avatarResolutions); - foreach($avatarResolutions as $key => $avatarRes) { - if(!ctype_digit($avatarRes)) - return self::createErrorPayload('auth:check:avatars', 'Avatar resolution set must be a comma separated set of numbers or empty.'); - $avatarResolutions[$key] = (int)$avatarRes; - } - $avatarResolutions = array_unique($avatarResolutions); - } - - $baseUrl = ($this->getBaseUrl)(); - $loginUrl = $baseUrl . $this->urls->format('auth-login'); - $registerUrl = $baseUrl . $this->urls->format('auth-register'); - - $tokenPacker = $this->authCtx->createAuthTokenPacker(); - $tokenInfo = $tokenPacker->unpack(trim($token)); - if($tokenInfo->isEmpty) - return self::createPayload('auth:check:fail', ['reason' => 'empty', 'login_url' => $loginUrl, 'register_url' => $registerUrl]); - - try { - $sessionInfo = $this->authCtx->sessions->getSession(sessionToken: $tokenInfo->sessionToken); - } catch(RuntimeException $ex) { - return self::createPayload('auth:check:fail', ['reason' => 'session', 'login_url' => $loginUrl, 'register_url' => $registerUrl]); - } - - if($sessionInfo->expired) { - $this->authCtx->sessions->deleteSessions(sessionInfos: $sessionInfo); - return self::createPayload('auth:check:fail', ['reason' => 'expired', 'login_url' => $loginUrl, 'register_url' => $registerUrl]); - } - - $this->authCtx->sessions->recordSessionActivity(sessionInfo: $sessionInfo, remoteAddr: $remoteAddr); - - $userInfo = $userInfoReal = $this->usersCtx->users->getUser($sessionInfo->userId, 'id'); - if($tokenInfo->hasImpersonatedUserId && $this->canImpersonateUserId($userInfo, $tokenInfo->impersonatedUserId)) { - try { - $userInfo = $this->usersCtx->users->getUser($tokenInfo->impersonatedUserId, 'id'); - } catch(RuntimeException $ex) { - $userInfo = $userInfoReal; - } - } - - $response = []; - $response['session'] = [ - 'token' => $sessionInfo->token, - 'created_at' => $sessionInfo->createdTime, - 'expires_at' => $sessionInfo->expiresTime, - 'lifetime_extends' => $sessionInfo->shouldBumpExpires, - ]; - - $banInfo = $this->usersCtx->tryGetActiveBan($userInfo); - if($banInfo !== null) - $response['ban'] = [ - 'severity' => $banInfo->severity, - 'reason' => $banInfo->publicReason, - 'created_at' => $banInfo->createdTime, - 'is_permanent' => $banInfo->permanent, - 'expires_at' => $banInfo->expiresTime, - 'duration_str' => $banInfo->durationString, - 'remaining_str' => $banInfo->remainingString, - ]; - - $gatherRequestedAvatars = function($userInfo) use ($avatarResolutions, $baseUrl) { - $formatAvatarUrl = fn($res = 0) => ( - $baseUrl . $this->urls->format('user-avatar', ['user' => $userInfo->id, 'res' => $res]) - ); - - $avatars = ['original' => $formatAvatarUrl()]; - - foreach($avatarResolutions as $avatarRes) - $avatars[sprintf('x%d', $avatarRes)] = $formatAvatarUrl($avatarRes); - - return $avatars; - }; - - $extractUserInfo = fn($userInfo) => [ - 'id' => $userInfo->id, - 'name' => $userInfo->name, - 'colour' => (string)$this->usersCtx->users->getUserColour($userInfo), - 'rank' => $this->usersCtx->users->getUserRank($userInfo), - 'is_super' => $userInfo->super, - 'country_code' => $userInfo->countryCode, - 'is_deleted' => $userInfo->deleted, - 'has_totp' => $userInfo->hasTOTP, - 'profile_url' => $baseUrl . $this->urls->format('user-profile', ['user' => $userInfo->id]), - 'avatars' => $gatherRequestedAvatars($userInfo), - ]; - - $response['user'] = $extractUserInfo($userInfo); - if($userInfo !== $userInfoReal) { - $response['guise'] = $extractUserInfo($userInfoReal); - - $csrf = CSRF::create($sessionInfo->token); - $response['guise']['revert_url'] = $baseUrl . $this->urls->format('auth-revert', ['csrf' => $csrf->createToken()]); - } - - return self::createPayload('auth:check:success', $response); - } -} diff --git a/src/MisuzuContext.php b/src/MisuzuContext.php index 1d1149f1..34504316 100644 --- a/src/MisuzuContext.php +++ b/src/MisuzuContext.php @@ -233,17 +233,6 @@ class MisuzuContext { )); $rpcServer->register($this->deps->constructLazy(Emoticons\EmotesRpcHandler::class)); $rpcServer->register($this->deps->constructLazy(Users\UsersRpcHandler::class)); - - $hanyuuRpcServer = new HttpRpcServer; - $routingCtx->scopeTo('', '/_hanyuu')->register($hanyuuRpcServer->createRouteHandler( - new HmacVerificationProvider(fn() => $this->config->getString('hanyuu.secret')) - )); - - $hanyuuRpcServer->register($this->deps->constructLazy( - Hanyuu\HanyuuRpcHandler::class, - getBaseUrl: fn() => $this->config->getString('hanyuu.endpoint'), - impersonateConfig: $this->config->scopeTo('impersonate') - )); } public function registerRedirectorRoutes(RoutingContext $routingCtx): void {