Replaced Misuzu interop stuff with RPC library.
This commit is contained in:
parent
8d6f7c5b7b
commit
b43c1ad2fd
12 changed files with 347 additions and 157 deletions
|
@ -8,7 +8,8 @@
|
|||
"matomo/device-detector": "^6.1",
|
||||
"sentry/sdk": "^4.0",
|
||||
"phpseclib/phpseclib": "~3.0",
|
||||
"nesbot/carbon": "^3.7"
|
||||
"nesbot/carbon": "^3.7",
|
||||
"flashwave/aiwass": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
|
|
41
composer.lock
generated
41
composer.lock
generated
|
@ -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": "16b27dc9d1837e8435dc95cecc4eeea2",
|
||||
"content-hash": "8cfa8c2738ab51aba3efea42afb68771",
|
||||
"packages": [
|
||||
{
|
||||
"name": "carbonphp/carbon-doctrine-types",
|
||||
|
@ -366,6 +366,45 @@
|
|||
],
|
||||
"time": "2023-10-06T06:47:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "flashwave/aiwass",
|
||||
"version": "v1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://patchii.net/flashii/aiwass.git",
|
||||
"reference": "de27da54b603f0fdc06dab89341908e73ea7a880"
|
||||
},
|
||||
"require": {
|
||||
"ext-msgpack": ">=2.2",
|
||||
"flashwave/index": "^0.2408.40014",
|
||||
"php": ">=8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.11",
|
||||
"phpunit/phpunit": "^11.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Aiwass\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"bsd-3-clause-clear"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "flashwave",
|
||||
"email": "packagist@flash.moe",
|
||||
"homepage": "https://flash.moe",
|
||||
"role": "mom"
|
||||
}
|
||||
],
|
||||
"description": "Shared HTTP RPC client/server library.",
|
||||
"homepage": "https://railgun.sh/aiwass",
|
||||
"time": "2024-08-16T15:59:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "flashwave/index",
|
||||
"version": "v0.2408.40014",
|
||||
|
|
|
@ -14,8 +14,8 @@ class HanyuuContext {
|
|||
private SasaeEnvironment $templating;
|
||||
private SiteInfo $siteInfo;
|
||||
|
||||
private MisuzuInterop $misuzuInterop;
|
||||
private object $authInfo;
|
||||
private MisuzuRpcClient $misuzuRpc;
|
||||
private MisuzuAuthInfo $authInfo;
|
||||
|
||||
private Apps\AppsContext $appsCtx;
|
||||
private OAuth2\OAuth2Context $oauth2Ctx;
|
||||
|
@ -24,7 +24,7 @@ class HanyuuContext {
|
|||
$this->config = $config;
|
||||
$this->dbConn = $dbConn;
|
||||
$this->siteInfo = new SiteInfo($config->scopeTo('site'));
|
||||
$this->misuzuInterop = new MisuzuInterop($config->scopeTo('misuzu'));
|
||||
$this->misuzuRpc = new MisuzuRpcClient($config->scopeTo('misuzu'));
|
||||
|
||||
$this->appsCtx = new Apps\AppsContext($dbConn);
|
||||
$this->oauth2Ctx = new OAuth2\OAuth2Context($dbConn);
|
||||
|
@ -41,8 +41,8 @@ class HanyuuContext {
|
|||
]);
|
||||
}
|
||||
|
||||
public function getMisuzu(): MisuzuInterop {
|
||||
return $this->misuzuInterop;
|
||||
public function getMisuzuRpc(): MisuzuRpcClient {
|
||||
return $this->misuzuRpc;
|
||||
}
|
||||
|
||||
public function getDatabase(): IDbConnection {
|
||||
|
@ -62,7 +62,7 @@ class HanyuuContext {
|
|||
return new FsDbMigrationRepo(HAU_DIR_MIGRATIONS);
|
||||
}
|
||||
|
||||
public function getAuthInfo(): object {
|
||||
public function getAuthInfo(): MisuzuAuthInfo {
|
||||
return $this->authInfo;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ class HanyuuContext {
|
|||
$routingCtx = new RoutingContext($this->getTemplating());
|
||||
|
||||
$routingCtx->getRouter()->use('/', function($response, $request) {
|
||||
$this->authInfo = $this->misuzuInterop->authCheck(
|
||||
$this->authInfo = $this->misuzuRpc->authCheck(
|
||||
'Misuzu',
|
||||
(string)$request->getCookie('msz_auth'),
|
||||
$_SERVER['REMOTE_ADDR'],
|
||||
|
|
44
src/MisuzuAuthBanInfo.php
Normal file
44
src/MisuzuAuthBanInfo.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
namespace Hanyuu;
|
||||
|
||||
class MisuzuAuthBanInfo {
|
||||
public function __construct(
|
||||
private array $info
|
||||
) {}
|
||||
|
||||
public function getSeverity(): int {
|
||||
return array_key_exists('severity', $this->info) && is_int($this->info['severity'])
|
||||
? $this->info['severity'] : 0;
|
||||
}
|
||||
|
||||
public function getReason(): string {
|
||||
return array_key_exists('reason', $this->info) && is_string($this->info['reason'])
|
||||
? $this->info['reason'] : '';
|
||||
}
|
||||
|
||||
public function getCreatedAt(): int {
|
||||
return array_key_exists('created_at', $this->info) && is_int($this->info['created_at'])
|
||||
? $this->info['created_at'] : 0;
|
||||
}
|
||||
|
||||
public function isPermanent(): bool {
|
||||
return array_key_exists('is_permanent', $this->info)
|
||||
&& is_bool($this->info['is_permanent'])
|
||||
&& $this->info['is_permanent'];
|
||||
}
|
||||
|
||||
public function getExpiresAt(): int {
|
||||
return array_key_exists('expires_at', $this->info) && is_int($this->info['expires_at'])
|
||||
? $this->info['expires_at'] : 0;
|
||||
}
|
||||
|
||||
public function getDurationString(): string {
|
||||
return array_key_exists('duration_str', $this->info) && is_string($this->info['duration_str'])
|
||||
? $this->info['duration_str'] : '';
|
||||
}
|
||||
|
||||
public function getRemainingString(): string {
|
||||
return array_key_exists('remaining_str', $this->info) && is_string($this->info['remaining_str'])
|
||||
? $this->info['remaining_str'] : '';
|
||||
}
|
||||
}
|
15
src/MisuzuAuthGuiseInfo.php
Normal file
15
src/MisuzuAuthGuiseInfo.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
namespace Hanyuu;
|
||||
|
||||
class MisuzuAuthGuiseInfo extends MisuzuAuthUserInfo {
|
||||
public function __construct(
|
||||
private array $info
|
||||
) {
|
||||
parent::__construct($info);
|
||||
}
|
||||
|
||||
public function getRevertUrl(): string {
|
||||
return array_key_exists('revert_url', $this->info) && is_string($this->info['revert_url'])
|
||||
? $this->info['revert_url'] : '';
|
||||
}
|
||||
}
|
51
src/MisuzuAuthInfo.php
Normal file
51
src/MisuzuAuthInfo.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
namespace Hanyuu;
|
||||
|
||||
class MisuzuAuthInfo {
|
||||
public function __construct(
|
||||
private array $info
|
||||
) {}
|
||||
|
||||
public function isFailure(): bool {
|
||||
return array_key_exists('reason', $this->info);
|
||||
}
|
||||
|
||||
public function getFailureReason(): string {
|
||||
return array_key_exists('reason', $this->info) && is_string($this->info['reason'])
|
||||
? $this->info['reason'] : '';
|
||||
}
|
||||
|
||||
public function getLoginUrl(): string {
|
||||
return array_key_exists('login_url', $this->info) && is_string($this->info['login_url'])
|
||||
? $this->info['login_url'] : '';
|
||||
}
|
||||
|
||||
public function getRegisterUrl(): string {
|
||||
return array_key_exists('register_url', $this->info) && is_string($this->info['register_url'])
|
||||
? $this->info['register_url'] : '';
|
||||
}
|
||||
|
||||
public function getSessionInfo(): MisuzuAuthSessionInfo {
|
||||
return new MisuzuAuthSessionInfo($this->info['session'] ?? []);
|
||||
}
|
||||
|
||||
public function isBanned(): bool {
|
||||
return array_key_exists('ban', $this->info);
|
||||
}
|
||||
|
||||
public function getBanInfo(): MisuzuAuthBanInfo {
|
||||
return new MisuzuAuthBanInfo($this->info['ban'] ?? []);
|
||||
}
|
||||
|
||||
public function getUserInfo(): MisuzuAuthUserInfo {
|
||||
return new MisuzuAuthUserInfo($this->info['user'] ?? []);
|
||||
}
|
||||
|
||||
public function isGuise(): bool {
|
||||
return array_key_exists('guise', $this->info);
|
||||
}
|
||||
|
||||
public function getGuiseInfo(): MisuzuAuthGuiseInfo {
|
||||
return new MisuzuAuthGuiseInfo($this->info['guise'] ?? []);
|
||||
}
|
||||
}
|
29
src/MisuzuAuthSessionInfo.php
Normal file
29
src/MisuzuAuthSessionInfo.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
namespace Hanyuu;
|
||||
|
||||
class MisuzuAuthSessionInfo {
|
||||
public function __construct(
|
||||
private array $info
|
||||
) {}
|
||||
|
||||
public function getToken(): string {
|
||||
return array_key_exists('token', $this->info) && is_string($this->info['token'])
|
||||
? $this->info['token'] : '';
|
||||
}
|
||||
|
||||
public function getCreatedAt(): int {
|
||||
return array_key_exists('created_at', $this->info) && is_int($this->info['created_at'])
|
||||
? $this->info['created_at'] : 0;
|
||||
}
|
||||
|
||||
public function getExpiresAt(): int {
|
||||
return array_key_exists('expires_at', $this->info) && is_int($this->info['expires_at'])
|
||||
? $this->info['expires_at'] : 0;
|
||||
}
|
||||
|
||||
public function doesLifetimeExtend(): bool {
|
||||
return array_key_exists('lifetime_extends', $this->info)
|
||||
&& is_bool($this->info['lifetime_extends'])
|
||||
&& $this->info['lifetime_extends'];
|
||||
}
|
||||
}
|
70
src/MisuzuAuthUserInfo.php
Normal file
70
src/MisuzuAuthUserInfo.php
Normal file
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
namespace Hanyuu;
|
||||
|
||||
class MisuzuAuthUserInfo {
|
||||
public function __construct(
|
||||
private array $info
|
||||
) {}
|
||||
|
||||
public function getId(): string {
|
||||
return array_key_exists('id', $this->info) && is_string($this->info['id'])
|
||||
? $this->info['id'] : '';
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return array_key_exists('name', $this->info) && is_string($this->info['name'])
|
||||
? $this->info['name'] : '';
|
||||
}
|
||||
|
||||
public function getColour(): string {
|
||||
return array_key_exists('colour', $this->info) && is_string($this->info['colour'])
|
||||
? $this->info['colour'] : 'inherit';
|
||||
}
|
||||
|
||||
public function getRank(): int {
|
||||
return array_key_exists('rank', $this->info) && is_int($this->info['rank'])
|
||||
? $this->info['rank'] : 0;
|
||||
}
|
||||
|
||||
public function isSuper(): bool {
|
||||
return array_key_exists('is_super', $this->info)
|
||||
&& is_bool($this->info['is_super'])
|
||||
&& $this->info['is_super'];
|
||||
}
|
||||
|
||||
public function getCountryCode(): string {
|
||||
return array_key_exists('country_code', $this->info) && is_string($this->info['country_code'])
|
||||
? $this->info['country_code'] : '';
|
||||
}
|
||||
|
||||
public function isDeleted(): bool {
|
||||
return array_key_exists('is_deleted', $this->info)
|
||||
&& is_bool($this->info['is_deleted'])
|
||||
&& $this->info['is_deleted'];
|
||||
}
|
||||
|
||||
public function has2fa(): bool {
|
||||
return array_key_exists('has_totp', $this->info)
|
||||
&& is_bool($this->info['has_totp'])
|
||||
&& $this->info['has_totp'];
|
||||
}
|
||||
|
||||
public function getProfileUrl(): string {
|
||||
return array_key_exists('profile_url', $this->info) && is_string($this->info['profile_url'])
|
||||
? $this->info['profile_url'] : '';
|
||||
}
|
||||
|
||||
public function getAvatars(): array {
|
||||
return array_key_exists('avatars', $this->info) && is_array($this->info['avatars'])
|
||||
? $this->info['avatars'] : [];
|
||||
}
|
||||
|
||||
public function getAvatar(string $variant): string {
|
||||
$avatars = $this->getAvatars();
|
||||
if(array_key_exists($variant, $avatars))
|
||||
return $avatars[$variant];
|
||||
if(array_key_exists('original', $avatars))
|
||||
return $avatars['original'];
|
||||
return '';
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
<?php
|
||||
namespace Hanyuu;
|
||||
|
||||
use stdClass;
|
||||
use RuntimeException;
|
||||
use Index\UriBase64;
|
||||
use Syokuhou\IConfig;
|
||||
|
||||
class MisuzuInterop {
|
||||
public function __construct(
|
||||
private IConfig $config
|
||||
) {}
|
||||
|
||||
private function getEndpoint(): string {
|
||||
return $this->config->getString('endpoint');
|
||||
}
|
||||
|
||||
private function getSecret(): string {
|
||||
return $this->config->getString('secret');
|
||||
}
|
||||
|
||||
public function authCheck(string $method, string $token, string $remoteAddr, array $avatars = []): object {
|
||||
$result = $this->callRpc('auth-check', body: [
|
||||
'method' => $method,
|
||||
'token' => $token,
|
||||
'remote_addr' => $remoteAddr,
|
||||
'avatars' => implode(',', $avatars),
|
||||
]);
|
||||
|
||||
if(!str_starts_with($result->name, 'auth:check:'))
|
||||
return new stdClass;
|
||||
|
||||
return $result->attrs;
|
||||
}
|
||||
|
||||
private function callRpc(string $action, array $params = [], array $body = []): object {
|
||||
$time = time();
|
||||
|
||||
$url = sprintf('%s/_hanyuu/%s', $this->getEndpoint(), $action);
|
||||
if(empty($params))
|
||||
$params = '';
|
||||
else {
|
||||
$params = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
|
||||
$url .= sprintf('?%s', $params);
|
||||
}
|
||||
|
||||
$hasBody = !empty($body);
|
||||
$body = $hasBody ? http_build_query($body, '', '&', PHP_QUERY_RFC3986) : '';
|
||||
|
||||
$signature = UriBase64::encode(hash_hmac(
|
||||
'sha256',
|
||||
sprintf('[%s|%s|%s]', $time, $url, $body),
|
||||
$this->getSecret(),
|
||||
true
|
||||
));
|
||||
$headers = [
|
||||
sprintf('X-Hanyuu-Timestamp: %s', $time),
|
||||
sprintf('X-Hanyuu-Signature: %s', $signature),
|
||||
];
|
||||
|
||||
if($hasBody)
|
||||
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
|
||||
|
||||
$req = curl_init($url);
|
||||
try {
|
||||
curl_setopt_array($req, [
|
||||
CURLOPT_AUTOREFERER => false,
|
||||
CURLOPT_FAILONERROR => false,
|
||||
CURLOPT_FOLLOWLOCATION => false,
|
||||
CURLOPT_HEADER => false,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TCP_FASTOPEN => true,
|
||||
CURLOPT_CONNECTTIMEOUT => 2,
|
||||
CURLOPT_MAXREDIRS => 2,
|
||||
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
|
||||
CURLOPT_TIMEOUT => 5,
|
||||
CURLOPT_USERAGENT => 'Hanyuu',
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
]);
|
||||
|
||||
if($hasBody)
|
||||
curl_setopt_array($req, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_POSTFIELDS => $body,
|
||||
]);
|
||||
|
||||
$response = curl_exec($req);
|
||||
if($response === false)
|
||||
throw new RuntimeException(curl_error($req));
|
||||
} finally {
|
||||
curl_close($req);
|
||||
}
|
||||
|
||||
$decoded = json_decode($response);
|
||||
if($decoded === null)
|
||||
throw new RuntimeException($response);
|
||||
|
||||
if(empty($decoded->name) || !isset($decoded->attrs))
|
||||
throw new RuntimeException('Missing name or attrs attribute in response body.');
|
||||
|
||||
if($decoded->name === 'error') {
|
||||
$line = $decoded->attrs->code ?? 'unknown';
|
||||
if(!empty($decoded->attrs->text))
|
||||
$line = sprintf('[%s] %s', $line, $decoded->attrs->text);
|
||||
|
||||
throw new RuntimeException($line);
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
}
|
39
src/MisuzuRpcClient.php
Normal file
39
src/MisuzuRpcClient.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
namespace Hanyuu;
|
||||
|
||||
use stdClass;
|
||||
use RuntimeException;
|
||||
use Aiwass\Client\RpcClient;
|
||||
use Index\UriBase64;
|
||||
use Syokuhou\IConfig;
|
||||
|
||||
class MisuzuRpcClient {
|
||||
private RpcClient $client;
|
||||
|
||||
public function __construct(IConfig $config) {
|
||||
$this->client = RpcClient::createHmac(
|
||||
sprintf('%s/_hanyuu', $config->getString('endpoint')),
|
||||
fn() => $config->getString('secret')
|
||||
);
|
||||
}
|
||||
|
||||
public function getRpcClient(): RpcClient {
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
public function authCheck(string $method, string $token, string $remoteAddr, array $avatars = []): MisuzuAuthInfo {
|
||||
$result = $this->client->procedure('mszhau:authCheck', [
|
||||
'method' => $method,
|
||||
'token' => $token,
|
||||
'remoteAddr' => $remoteAddr,
|
||||
'avatars' => implode(',', $avatars),
|
||||
]);
|
||||
|
||||
if(empty($result['name']))
|
||||
throw new RuntimeException('Unexpected response from Misuzu.');
|
||||
if(!str_starts_with($result['name'], 'auth:check:'))
|
||||
throw new RuntimeException($result['name']);
|
||||
|
||||
return new MisuzuAuthInfo($result['attrs']);
|
||||
}
|
||||
}
|
|
@ -66,10 +66,13 @@ final class OAuth2Routes extends RouteHandler {
|
|||
#[HttpGet('/oauth2/authorise')]
|
||||
public function getAuthorise($response, $request) {
|
||||
$authInfo = ($this->getAuthInfo)();
|
||||
if(!isset($authInfo->user))
|
||||
return $this->templating->render('oauth2/login', ['auth' => $authInfo]);
|
||||
if($authInfo->isFailure())
|
||||
return $this->templating->render('oauth2/login', [
|
||||
'login_url' => $authInfo->getLoginUrl(),
|
||||
'register_url' => $authInfo->getRegisterUrl(),
|
||||
]);
|
||||
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->session->token);
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->getSessionInfo()->getToken());
|
||||
|
||||
return $this->templating->render('oauth2/authorise', [
|
||||
'csrfp_token' => $csrfp->createToken(),
|
||||
|
@ -84,12 +87,12 @@ final class OAuth2Routes extends RouteHandler {
|
|||
// TODO: RATE LIMITING
|
||||
|
||||
$authInfo = ($this->getAuthInfo)();
|
||||
if(!isset($authInfo->user))
|
||||
if($authInfo->isFailure())
|
||||
return ['error' => 'auth'];
|
||||
|
||||
$content = $request->getContent();
|
||||
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->session->token);
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->getSessionInfo()->getToken());
|
||||
if(!$csrfp->verifyToken((string)$content->getParam('_csrfp')))
|
||||
return ['error' => 'csrf'];
|
||||
|
||||
|
@ -145,7 +148,7 @@ final class OAuth2Routes extends RouteHandler {
|
|||
try {
|
||||
$authsInfo = $authsData->createAuthorisation(
|
||||
$appInfo,
|
||||
$authInfo->user->id,
|
||||
$authInfo->getUserInfo()->getId(),
|
||||
$redirectUriId,
|
||||
$codeChallenge,
|
||||
$codeChallengeMethod,
|
||||
|
@ -166,10 +169,11 @@ final class OAuth2Routes extends RouteHandler {
|
|||
// TODO: RATE LIMITING
|
||||
|
||||
$authInfo = ($this->getAuthInfo)();
|
||||
if(!isset($authInfo->user))
|
||||
if($authInfo->isFailure())
|
||||
return ['error' => 'auth'];
|
||||
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->session->token);
|
||||
$sessionInfo = $authInfo->getSessionInfo();
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $sessionInfo->getToken());
|
||||
if(!$csrfp->verifyToken((string)$request->getParam('csrfp')))
|
||||
return ['error' => 'csrf'];
|
||||
|
||||
|
@ -196,6 +200,7 @@ final class OAuth2Routes extends RouteHandler {
|
|||
return ['error' => 'scope'];
|
||||
}
|
||||
|
||||
$userInfo = $authInfo->getUserInfo();
|
||||
$result = [
|
||||
'app' => [
|
||||
'name' => $appInfo->getName(),
|
||||
|
@ -206,21 +211,23 @@ final class OAuth2Routes extends RouteHandler {
|
|||
],
|
||||
],
|
||||
'user' => [
|
||||
'name' => $authInfo->user->name,
|
||||
'colour' => $authInfo->user->colour,
|
||||
'profile_uri' => $authInfo->user->profile_url,
|
||||
'avatar_uri' => $authInfo->user->avatars->x120,
|
||||
'name' => $userInfo->getName(),
|
||||
'colour' => $userInfo->getColour(),
|
||||
'profile_uri' => $userInfo->getProfileUrl(),
|
||||
'avatar_uri' => $userInfo->getAvatar('x120'),
|
||||
],
|
||||
];
|
||||
|
||||
if(isset($authInfo->guise))
|
||||
if($authInfo->isGuise()) {
|
||||
$guiseInfo = $authInfo->getGuiseInfo();
|
||||
$result['user']['guise'] = [
|
||||
'name' => $authInfo->guise->name,
|
||||
'colour' => $authInfo->guise->colour,
|
||||
'profile_uri' => $authInfo->guise->profile_url,
|
||||
'revert_uri' => $authInfo->guise->revert_url,
|
||||
'avatar_uri' => $authInfo->guise->avatars->x60,
|
||||
'name' => $guiseInfo->getName(),
|
||||
'colour' => $guiseInfo->getColour(),
|
||||
'profile_uri' => $guiseInfo->getProfileUrl(),
|
||||
'revert_uri' => $guiseInfo->getRevertUrl(),
|
||||
'avatar_uri' => $guiseInfo->getAvatar('x60'),
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
@ -228,10 +235,13 @@ final class OAuth2Routes extends RouteHandler {
|
|||
#[HttpGet('/oauth2/verify')]
|
||||
public function getVerify($response, $request) {
|
||||
$authInfo = ($this->getAuthInfo)();
|
||||
if(!isset($authInfo->user))
|
||||
return $this->templating->render('oauth2/login', ['auth' => $authInfo]);
|
||||
if($authInfo->isFailure())
|
||||
return $this->templating->render('oauth2/login', [
|
||||
'login_url' => $authInfo->getLoginUrl(),
|
||||
'register_url' => $authInfo->getRegisterUrl(),
|
||||
]);
|
||||
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->session->token);
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->getSessionInfo()->getToken());
|
||||
|
||||
return $this->templating->render('oauth2/verify', [
|
||||
'csrfp_token' => $csrfp->createToken(),
|
||||
|
@ -246,12 +256,12 @@ final class OAuth2Routes extends RouteHandler {
|
|||
// TODO: RATE LIMITING
|
||||
|
||||
$authInfo = ($this->getAuthInfo)();
|
||||
if(!isset($authInfo->user))
|
||||
if($authInfo->isFailure())
|
||||
return ['error' => 'auth'];
|
||||
|
||||
$content = $request->getContent();
|
||||
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->session->token);
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->getSessionInfo()->getToken());
|
||||
if(!$csrfp->verifyToken((string)$content->getParam('_csrfp')))
|
||||
return ['error' => 'csrf'];
|
||||
|
||||
|
@ -270,7 +280,7 @@ final class OAuth2Routes extends RouteHandler {
|
|||
return ['error' => 'invalid'];
|
||||
|
||||
$approved = $approve === 'yes';
|
||||
$devicesData->setDeviceApproval($deviceInfo, $approved, $authInfo->user->id);
|
||||
$devicesData->setDeviceApproval($deviceInfo, $approved, $authInfo->getUserInfo()->getId());
|
||||
|
||||
return [
|
||||
'approval' => $approved ? 'approved' : 'denied',
|
||||
|
@ -282,10 +292,10 @@ final class OAuth2Routes extends RouteHandler {
|
|||
// TODO: RATE LIMITING
|
||||
|
||||
$authInfo = ($this->getAuthInfo)();
|
||||
if(!isset($authInfo->user))
|
||||
if($authInfo->isFailure())
|
||||
return ['error' => 'auth'];
|
||||
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->session->token);
|
||||
$csrfp = new CSRFP(($this->getCSRFPSecret)(), $authInfo->getSessionInfo()->getToken());
|
||||
if(!$csrfp->verifyToken((string)$request->getParam('csrfp')))
|
||||
return ['error' => 'csrf'];
|
||||
|
||||
|
@ -306,6 +316,7 @@ final class OAuth2Routes extends RouteHandler {
|
|||
return ['error' => 'code'];
|
||||
}
|
||||
|
||||
$userInfo = $authInfo->getUserInfo();
|
||||
$result = [
|
||||
'req' => [
|
||||
'code' => $deviceInfo->getUserCode(),
|
||||
|
@ -319,21 +330,23 @@ final class OAuth2Routes extends RouteHandler {
|
|||
],
|
||||
],
|
||||
'user' => [
|
||||
'name' => $authInfo->user->name,
|
||||
'colour' => $authInfo->user->colour,
|
||||
'profile_uri' => $authInfo->user->profile_url,
|
||||
'avatar_uri' => $authInfo->user->avatars->x120,
|
||||
'name' => $userInfo->getName(),
|
||||
'colour' => $userInfo->getColour(),
|
||||
'profile_uri' => $userInfo->getProfileUrl(),
|
||||
'avatar_uri' => $userInfo->getAvatar('x120'),
|
||||
],
|
||||
];
|
||||
|
||||
if(isset($authInfo->guise))
|
||||
if($authInfo->isGuise()) {
|
||||
$guiseInfo = $authInfo->getGuiseInfo();
|
||||
$result['user']['guise'] = [
|
||||
'name' => $authInfo->guise->name,
|
||||
'colour' => $authInfo->guise->colour,
|
||||
'profile_uri' => $authInfo->guise->profile_url,
|
||||
'revert_uri' => $authInfo->guise->revert_url,
|
||||
'avatar_uri' => $authInfo->guise->avatars->x60,
|
||||
'name' => $guiseInfo->getName(),
|
||||
'colour' => $guiseInfo->getColour(),
|
||||
'profile_uri' => $guiseInfo->getProfileUrl(),
|
||||
'revert_uri' => $guiseInfo->getRevertUrl(),
|
||||
'avatar_uri' => $guiseInfo->getAvatar('x60'),
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<p>A third-party application is requesting permission to access your account.</p>
|
||||
{% endif %}
|
||||
|
||||
<p>You must be logged in to authorise applications. <a href="{{ auth.login_url }}" target="_blank">Log in</a> or <a href="{{ auth.register_url }}" target="_blank">create an account</a> and reload this page to try again.</p>
|
||||
<p>You must be logged in to authorise applications. <a href="{{ login_url }}" target="_blank">Log in</a> or <a href="{{ register_url }}" target="_blank">create an account</a> and reload this page to try again.</p>
|
||||
|
||||
{% if app is defined and app.isTrusted %}
|
||||
<p>You will be redirected to the following application after logging in.</p>
|
||||
|
|
Loading…
Reference in a new issue