Added new token/login endpoints for chat.
This commit is contained in:
parent
85c71f604a
commit
ca2c192330
6 changed files with 128 additions and 16 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
20250421
|
||||
20250422
|
||||
|
|
70
src/Chat/ChatApiRoutes.php
Normal file
70
src/Chat/ChatApiRoutes.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
namespace Misuzu\Chat;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Index\Config\Config;
|
||||
use Index\Http\{HttpRequest,HttpResponseBuilder,HttpUri};
|
||||
use Index\Http\Routing\AccessControl\AccessControl;
|
||||
use Index\Http\Routing\Processors\Before;
|
||||
use Index\Http\Routing\Routes\ExactRoute;
|
||||
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
|
||||
use Misuzu\Auth\{AuthContext,AuthInfo};
|
||||
use Misuzu\Routing\{HandlerRoles,RouteHandler,RouteHandlerCommon};
|
||||
|
||||
#[HandlerRoles('main')]
|
||||
final class ChatApiRoutes implements RouteHandler, UrlSource {
|
||||
use RouteHandlerCommon, UrlSourceCommon;
|
||||
|
||||
public function __construct(
|
||||
private ChatContext $chatCtx,
|
||||
private UrlRegistry $urls,
|
||||
private AuthContext $authCtx,
|
||||
private AuthInfo $authInfo,
|
||||
) {}
|
||||
|
||||
/** @return int|void */
|
||||
#[ExactRoute('GET', '/api/v1/chat/login')]
|
||||
#[Before('authz:cookie')]
|
||||
#[UrlFormat('api-v1-chat-login', '/api/v1/chat/login', ['redirect' => '<redirect>'])]
|
||||
public function getLogin(HttpResponseBuilder $response, HttpRequest $request) {
|
||||
if(!$request->hasParam('redirect'))
|
||||
return 400;
|
||||
|
||||
$redirect = $request->getFilteredParam('redirect', FILTER_VALIDATE_URL);
|
||||
if(!is_string($redirect))
|
||||
return 400;
|
||||
|
||||
try {
|
||||
$redirect = HttpUri::createUri($redirect);
|
||||
} catch(InvalidArgumentException $ex) {
|
||||
return 400;
|
||||
}
|
||||
|
||||
if(!$this->chatCtx->isTrustedHost($redirect))
|
||||
return 403;
|
||||
|
||||
if(!$this->authInfo->loggedIn)
|
||||
$redirect = $this->urls->format('auth-login', [
|
||||
'redirect' => $this->urls->format('api-v1-chat-login', ['redirect' => $redirect]),
|
||||
]);
|
||||
|
||||
$response->redirect($redirect);
|
||||
}
|
||||
|
||||
/** @return int|array{token_type: 'Misuzu', access_token: string} */
|
||||
#[AccessControl(credentials: true)]
|
||||
#[ExactRoute('GET', '/api/v1/chat/token')]
|
||||
#[Before('authz:cookie')]
|
||||
public function getToken(HttpResponseBuilder $response, HttpRequest $request): int|array {
|
||||
$response->setCacheControl('no-store');
|
||||
|
||||
if(!$this->authInfo->tokenInfo->hasSessionToken
|
||||
|| $this->authInfo->sessionInfo?->expired !== false)
|
||||
return 403;
|
||||
|
||||
return [
|
||||
'token_type' => 'Misuzu',
|
||||
'access_token' => $this->authCtx->createAuthTokenPacker()->pack($this->authInfo->tokenInfo),
|
||||
];
|
||||
}
|
||||
}
|
27
src/Chat/ChatContext.php
Normal file
27
src/Chat/ChatContext.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
namespace Misuzu\Chat;
|
||||
|
||||
use Index\Config\Config;
|
||||
use Index\Http\HttpUri;
|
||||
|
||||
class ChatContext {
|
||||
/** @var string[] */
|
||||
public array $origins {
|
||||
get => $this->config->getArray('origins');
|
||||
}
|
||||
|
||||
public string $storagePoolName {
|
||||
get => $this->config->getString('storage_pool');
|
||||
}
|
||||
|
||||
public function __construct(
|
||||
public private(set) Config $config,
|
||||
) {}
|
||||
|
||||
public function isTrustedHost(HttpUri|string $host): bool {
|
||||
if($host instanceof HttpUri)
|
||||
$host = $host->host;
|
||||
|
||||
return in_array($host, $this->origins);
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ class MisuzuContext implements RouteHandler {
|
|||
public private(set) DatabaseContext $dbCtx;
|
||||
public private(set) Apps\AppsContext $appsCtx;
|
||||
public private(set) Auth\AuthContext $authCtx;
|
||||
public private(set) Chat\ChatContext $chatCtx;
|
||||
public private(set) Colours\ColoursContext $coloursCtx;
|
||||
public private(set) Comments\CommentsContext $commentsCtx;
|
||||
public private(set) Emoticons\EmotesContext $emotesCtx;
|
||||
|
@ -95,6 +96,10 @@ class MisuzuContext implements RouteHandler {
|
|||
Auth\AuthContext::class,
|
||||
config: $this->config->scopeTo('auth'),
|
||||
));
|
||||
$this->deps->register($this->chatCtx = $this->deps->constructLazy(
|
||||
Chat\ChatContext::class,
|
||||
config: $this->config->scopeTo('chat'),
|
||||
));
|
||||
$this->deps->register($this->coloursCtx = $this->deps->constructLazy(Colours\ColoursContext::class));
|
||||
$this->deps->register($this->commentsCtx = $this->deps->constructLazy(Comments\CommentsContext::class));
|
||||
$this->deps->register($this->csrfCtx = $this->deps->constructLazy(
|
||||
|
@ -185,6 +190,7 @@ class MisuzuContext implements RouteHandler {
|
|||
|
||||
$this->routingCtx->register($this->deps->constructLazy(WebFinger\WebFingerRoutes::class), $roles);
|
||||
|
||||
$this->routingCtx->register($this->deps->constructLazy(Chat\ChatApiRoutes::class), $roles);
|
||||
$this->routingCtx->register($this->deps->constructLazy(Colours\ColoursApiRoutes::class), $roles);
|
||||
$this->routingCtx->register($this->deps->constructLazy(Emoticons\EmotesApiRoutes::class), $roles);
|
||||
$this->routingCtx->register($this->deps->constructLazy(Kaomoji\KaomojiApiRoutes::class), $roles);
|
||||
|
|
|
@ -31,7 +31,10 @@ class RoutingAccessControlHandler extends SimpleAccessControlHandler {
|
|||
): string|bool {
|
||||
if($accessControl->credentials) {
|
||||
$result = null;
|
||||
if($context->request->requestTarget === '/_sockchat'
|
||||
if($context->request->requestTarget === '/api/v1/chat'
|
||||
|| str_starts_with($context->request->requestTarget, '/api/v1/chat/')) {
|
||||
$result = self::filterOrigin($this->config->getArray('chat.origins'), $origin);
|
||||
} elseif($context->request->requestTarget === '/_sockchat'
|
||||
|| str_starts_with($context->request->requestTarget, '/_sockchat/')) {
|
||||
$result = self::filterOrigin($this->config->getArray('sockChat.origins'), $origin);
|
||||
} elseif($context->request->requestTarget === '/uploads'
|
||||
|
|
|
@ -8,25 +8,31 @@ use Index\Http\Streams\Stream;
|
|||
use Misuzu\Misuzu;
|
||||
|
||||
class RoutingErrorHandler extends HtmlErrorHandler {
|
||||
public const array FORCE_HTML = [
|
||||
'/api/v1/chat/login',
|
||||
];
|
||||
|
||||
public function handle(HandlerContext $context): void {
|
||||
if(!$context->response->needsBody)
|
||||
return;
|
||||
|
||||
if(str_starts_with($context->request->requestTarget, '/_')) {
|
||||
$context->response->setTypePlain();
|
||||
$context->response->body = Stream::createStream(sprintf('HTTP %03d', $context->response->statusCode));
|
||||
return;
|
||||
}
|
||||
if(!in_array($context->request->requestTarget, self::FORCE_HTML)) {
|
||||
if(str_starts_with($context->request->requestTarget, '/_')) {
|
||||
$context->response->setTypePlain();
|
||||
$context->response->body = Stream::createStream(sprintf('HTTP %03d', $context->response->statusCode));
|
||||
return;
|
||||
}
|
||||
|
||||
if(str_starts_with($context->request->requestTarget, '/api')) {
|
||||
$context->response->setTypeJson();
|
||||
$context->response->body = Stream::createStream(json_encode([
|
||||
'error' => sprintf('http:%s', $context->response->statusCode),
|
||||
'message' => $context->response->reasonPhrase === ''
|
||||
? HttpResponse::defaultReasonPhase($context->response->statusCode)
|
||||
: $context->response->reasonPhrase,
|
||||
], JSON_UNESCAPED_SLASHES));
|
||||
return;
|
||||
if(str_starts_with($context->request->requestTarget, '/api')) {
|
||||
$context->response->setTypeJson();
|
||||
$context->response->body = Stream::createStream(json_encode([
|
||||
'error' => sprintf('http:%s', $context->response->statusCode),
|
||||
'message' => $context->response->reasonPhrase === ''
|
||||
? HttpResponse::defaultReasonPhase($context->response->statusCode)
|
||||
: $context->response->reasonPhrase,
|
||||
], JSON_UNESCAPED_SLASHES));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$path = sprintf('%s/error-%03d.html', Misuzu::PATH_PUBLIC, $context->response->statusCode);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue