mince/src/ClientsRoutes.php

173 lines
5.8 KiB
PHP

<?php
namespace Mince;
use InvalidArgumentException;
use RuntimeException;
use Index\Routing\IRouter;
use Index\Security\CSRFP;
use Ramsey\Uuid\Uuid;
class ClientsRoutes {
public function __construct(
private Templating $templating,
private AccountLinks $accountLinks,
private Authorisations $authorisations,
private Verifications $verifications,
private CSRFP $csrfp,
private object $authInfo
) {}
public function register(IRouter $router): void {
$router->use('/clients', [$this, 'verifyRequest']);
$router->get('/clients', [$this, 'getClients']);
$router->post('/clients/link', [$this, 'postLink']);
$router->post('/clients/unlink', [$this, 'postUnlink']);
$router->post('/clients/authorise', [$this, 'postAuthorise']);
$router->post('/clients/deauthorise', [$this, 'postDeauthorise']);
}
public function verifyRequest($response, $request) {
if(!$this->authInfo->success)
return 403;
if($request->getMethod() === 'POST') {
if(!$request->isFormContent())
return 400;
$body = $request->getContent();
if(!$body->hasParam('csrfp') || !$this->csrfp->verifyToken((string)$body->getParam('csrfp')))
return 403;
}
}
private const CLIENTS_ERRORS = [
'link' => [
'already' => 'You already have a linked Minecraft username, unlink the other one first.',
'format' => 'The Link Code you entered was is not in the correct format, check your input!',
'code' => 'The Link Code you entered is not valid, make sure you typed it correctly!',
],
];
public function getClients($response, $request) {
$errorCode = (string)$request->getParam('error');
if($errorCode !== '') {
$errorCode = explode(':', $errorCode, 2);
if(count($errorCode) === 2
&& array_key_exists($errorCode[0], self::CLIENTS_ERRORS)
&& array_key_exists($errorCode[1], self::CLIENTS_ERRORS[$errorCode[0]]))
$this->templating->addVars([
'error' => [
'section' => $errorCode[0],
'code' => $errorCode[1],
'message' => self::CLIENTS_ERRORS[$errorCode[0]][$errorCode[1]],
],
]);
}
try {
$linkInfo = $this->accountLinks->getLink(userInfo: $this->authInfo->user_id);
$clients = $this->authorisations->getAuthorisations($linkInfo);
$this->templating->addVars([
'link' => $linkInfo,
'clients' => $clients,
]);
} catch(RuntimeException $ex) {}
return $this->templating->render('clients/index');
}
public function postLink($response, $request) {
if($this->accountLinks->checkHasLink($this->authInfo->user_id)) {
$response->redirect('/clients?error=link:already');
return;
}
$body = $request->getContent();
$code = (string)$body->getParam('code');
if(strlen($code) !== 10) {
$response->redirect('/clients?error=link:format');
return;
}
$code = strtr(strtoupper($code), '0189', 'OIBG');
try {
$verifyInfo = $this->verifications->getVerification(code: $code);
} catch(RuntimeException $ex) {
$response->redirect('/clients?error=link:code');
return;
}
$this->verifications->deleteVerification($verifyInfo);
$this->accountLinks->createLink($this->authInfo->user_id, $verifyInfo);
$this->authorisations->createAuthorisation($verifyInfo, grant: true);
$response->redirect('/clients');
}
public function postUnlink($response) {
$this->accountLinks->deleteLink(userInfo: $this->authInfo->user_id);
$response->redirect('/clients');
}
public function postAuthorise($response, $request) {
$body = $request->getContent();
$authId = (string)$body->getParam('auth');
if(empty($authId))
return 404;
try {
$linkInfo = $this->accountLinks->getLink(userInfo: $this->authInfo->user_id);
} catch(RuntimeException $ex) {
return 403;
}
try {
$authInfo = $this->authorisations->getAuthorisation(authId: $authId);
} catch(RuntimeException $ex) {
return 403;
}
if($authInfo->getUUIDRaw() !== $linkInfo->getUUIDRaw())
return 403;
if($authInfo->isGranted())
return 404;
$this->authorisations->setAuthorisationGranted($authInfo);
$response->redirect('/clients');
}
public function postDeauthorise($response, $request) {
$body = $request->getContent();
$authId = (string)$body->getParam('auth');
if(empty($authId))
return 404;
try {
$linkInfo = $this->accountLinks->getLink(userInfo: $this->authInfo->user_id);
} catch(RuntimeException $ex) {
return 403;
}
if($authId === 'all') {
$this->authorisations->deleteAuthorisations(uuid: $linkInfo);
} elseif($authId === 'pending') {
$this->authorisations->deleteAuthorisations(uuid: $linkInfo, pending: true);
} else {
try {
$authInfo = $this->authorisations->getAuthorisation(authId: $authId);
} catch(RuntimeException $ex) {
return 403;
}
if($authInfo->getUUIDRaw() !== $linkInfo->getUUIDRaw())
return 403;
$this->authorisations->deleteAuthorisations(authInfo: $authInfo);
}
$response->redirect('/clients');
}
}