misuzu/src/Satori/SatoriRoutes.php
flash 383e2ed0e0 Rewrote the user information class.
This one took multiple days and it pretty invasive into the core of Misuzu so issue might (will) arise, there's also some features that have gone temporarily missing in the mean time and some inefficiencies introduced that will be fixed again at a later time.
The old class isn't gone entirely because I still have to figure out what I'm gonna do about validation, but for the most part this knocks out one of the "layers of backwards compatibility", as I've been referring to it, and is moving us closer to a future where Flashii actually gets real updates.
If you run into anything that's broken and you're inhibited from reporting it through the forum, do it through chat or mail me at flashii-issues@flash.moe.
2023-08-02 22:12:47 +00:00

165 lines
6.1 KiB
PHP

<?php
namespace Misuzu\Satori;
use RuntimeException;
use Index\Data\DbTools;
use Index\Data\IDbConnection;
use Index\Http\HttpFx;
use Index\Routing\IRouter;
use Misuzu\Pagination;
use Misuzu\Config\IConfig;
use Misuzu\Profile\ProfileFields;
use Misuzu\Users\Users;
final class SatoriRoutes {
private IDbConnection $dbConn;
private IConfig $config;
private Users $users;
private ProfileFields $profileFields;
public function __construct(
IDbConnection $dbConn,
IConfig $config,
IRouter $router,
Users $users,
ProfileFields $profileFields
) {
$this->dbConn = $dbConn;
$this->config = $config;
$this->users = $users;
$this->profileFields = $profileFields;
// Simplify default error pages
if($router instanceof HttpFx)
$router->use('/_satori', function() use($router) {
$router->addErrorHandler(400, function($response) {
$response->setContent('HTTP 400');
});
$router->addErrorHandler(403, function($response) {
$response->setContent('HTTP 403');
});
$router->addErrorHandler(404, function($response) {
$response->setContent('HTTP 404');
});
$router->addErrorHandler(500, function($response) {
$response->setContent('HTTP 500');
});
$router->addErrorHandler(503, function($response) {
$response->setContent('HTTP 503');
});
});
$router->use('/_satori', [$this, 'verifyRequest']);
$router->get('/_satori/get-profile-field', [$this, 'getProfileField']);
$router->get('/_satori/get-recent-forum-posts', [$this, 'getRecentForumPosts']);
$router->get('/_satori/get-recent-registrations', [$this, 'getRecentRegistrations']);
}
public function verifyRequest($response, $request) {
$secretKey = $this->config->getString('secret');
if(!empty($secretKey)) {
$userTime = (int)$request->getHeaderLine('X-Satori-Time');
$userHash = base64_decode((string)$request->getHeaderLine('X-Satori-Hash'));
$currentTime = time();
if(empty($userHash) || $userTime < $currentTime - 60 || $userTime > $currentTime + 60)
return 403;
$verifyText = (string)$userTime . '#' . $request->getPath() . '?' . $request->getParamString();
$verifyHash = hash_hmac('sha256', $verifyText, $secretKey, true);
if(!hash_equals($verifyHash, $userHash))
return 403;
}
}
public function getProfileField($response, $request): array {
$userId = (string)$request->getParam('user', FILTER_SANITIZE_NUMBER_INT);
$fieldId = (string)$request->getParam('field', FILTER_SANITIZE_NUMBER_INT);
try {
$fieldValue = $this->profileFields->getFieldValue($fieldId, $userId);
} catch(RuntimeException $ex) {
return ['error' => 105];
}
return [
'field_value' => $fieldValue->getValue(),
];
}
public function getRecentForumPosts($response, $request): array {
$categoryIds = $this->config->getArray('forum.categories');
if(empty($categoryIds))
return [];
$batchSize = $this->config->getInteger('forum.batch', 6);
$backlogDays = $this->config->getInteger('forum.backlog', 7);
$startId = (string)$request->getParam('start', FILTER_SANITIZE_NUMBER_INT);
$args = 0;
$stmt = $this->dbConn->prepare(sprintf(
'SELECT fp.post_id, ft.topic_id, ft.topic_title, fc.forum_id, fc.forum_name, u.user_id, u.username,'
. ' COALESCE(u.user_colour, r.role_colour), (SELECT MIN(post_id) = fp.post_id FROM msz_forum_posts WHERE topic_id = fp.topic_id)'
. ' FROM msz_forum_posts AS fp'
. ' LEFT JOIN msz_users AS u ON u.user_id = fp.user_id'
. ' LEFT JOIN msz_roles AS r ON r.role_id = u.display_role'
. ' LEFT JOIN msz_forum_topics AS ft ON ft.topic_id = fp.topic_id'
. ' LEFT JOIN msz_forum_categories AS fc ON fc.forum_id = fp.forum_id'
. ' WHERE post_id > ? AND post_deleted IS NULL AND post_created >= NOW() - INTERVAL ? DAY'
. ' AND fp.forum_id IN (%s)'
. ' ORDER BY post_id LIMIT ?',
DbTools::prepareListString($categoryIds)
));
$stmt->addParameter(++$args, $startId);
$stmt->addParameter(++$args, $backlogDays);
foreach($categoryIds as $categoryId)
$stmt->addParameter(++$args, $categoryId);
$stmt->addParameter(++$args, $batchSize);
$stmt->execute();
$posts = [];
$result = $stmt->getResult();
while($result->next())
$posts[] = [
'post_id' => $result->getInteger(0),
'topic_id' => $result->getInteger(1),
'topic_title' => $result->getString(2),
'forum_id' => $result->getInteger(3),
'forum_name' => $result->getString(4),
'user_id' => $result->getInteger(5),
'username' => $result->getString(6),
'user_colour' => $result->getInteger(7),
'is_opening_post' => $result->getInteger(8),
];
return $posts;
}
public function getRecentRegistrations($response, $request) {
$batchSize = $this->config->getInteger('users.batch', 10);
$backlogDays = $this->config->getInteger('users.backlog', 7);
$startId = (string)$request->getParam('start', FILTER_SANITIZE_NUMBER_INT);
$userInfos = $this->users->getUsers(
after: $startId,
newerThanDays: $backlogDays,
orderBy: 'id',
pagination: new Pagination($batchSize),
deleted: false
);
$users = [];
foreach($userInfos as $userInfo)
$users[] = [
'user_id' => (int)$userInfo->getId(),
'username' => $userInfo->getName(),
];
return $users;
}
}