Logging cleanup.

This commit is contained in:
flash 2025-03-28 20:19:54 +00:00
parent d1fad37022
commit 16a7e20441
Signed by: flash
GPG key ID: 2C9C2C574D47FE3E
27 changed files with 220 additions and 213 deletions

View file

@ -71,7 +71,7 @@ while($canResetPassword) {
$msz->usersCtx->passwords->updateUserPassword($userInfo, $passwordNew);
$msz->usersCtx->totps->deleteUserTotp($userInfo);
$msz->createAuditLog('PASSWORD_RESET', [], $userInfo);
$msz->logsCtx->createUserLog($userInfo, 'PASSWORD_RESET');
$msz->authCtx->recoveryTokens->invalidateToken($tokenInfo);

View file

@ -38,7 +38,7 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && !empty($_GET['delete'])) {
Template::throwError(403);
$msz->changelog->deleteChange($changeInfo);
$msz->createAuditLog('CHANGELOG_ENTRY_DELETE', [$changeInfo->id]);
$msz->logsCtx->createAuthedLog('CHANGELOG_ENTRY_DELETE', [$changeInfo->id]);
Tools::redirect($msz->urls->format('manage-changelog-changes'));
return;
}
@ -100,9 +100,9 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
}
}
$msz->createAuditLog(
$msz->logsCtx->createAuthedLog(
$isNew ? 'CHANGELOG_ENTRY_CREATE' : 'CHANGELOG_ENTRY_EDIT',
[$changeInfo->id]
[$changeInfo->id],
);
Tools::redirect($msz->urls->format('manage-changelog-change', ['change' => $changeInfo->id]));

View file

@ -27,7 +27,7 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && !empty($_GET['delete'])) {
Template::throwError(403);
$msz->changelog->deleteTag($tagInfo);
$msz->createAuditLog('CHANGELOG_TAG_DELETE', [$tagInfo->id]);
$msz->logsCtx->createAuthedLog('CHANGELOG_TAG_DELETE', [$tagInfo->id]);
Tools::redirect($msz->urls->format('manage-changelog-tags'));
return;
}
@ -51,9 +51,9 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$msz->changelog->updateTag($tagInfo, $name, $description, $archive);
}
$msz->createAuditLog(
$msz->logsCtx->createAuthedLog(
$isNew ? 'CHANGELOG_TAG_CREATE' : 'CHANGELOG_TAG_EDIT',
[$tagInfo->id]
[$tagInfo->id],
);
if($isNew) {

View file

@ -14,7 +14,7 @@ if($_SERVER['REQUEST_METHOD'] === 'POST') {
$rTopicId = !empty($_POST['topic_redir_id']) && is_scalar($_POST['topic_redir_id']) ? trim((string)$_POST['topic_redir_id']) : '';
$rTopicURL = !empty($_POST['topic_redir_url']) && is_scalar($_POST['topic_redir_url']) ? trim((string)$_POST['topic_redir_url']) : '';
$msz->createAuditLog('FORUM_TOPIC_REDIR_CREATE', [$rTopicId]);
$msz->logsCtx->createAuthedLog('FORUM_TOPIC_REDIR_CREATE', [$rTopicId]);
$msz->forumCtx->topicRedirects->createTopicRedirect($rTopicId, $msz->authInfo->userInfo, $rTopicURL);
Tools::redirect($msz->urls->format('manage-forum-topic-redirs'));
return;
@ -25,7 +25,7 @@ if(!empty($_GET['m']) && $_GET['m'] === 'explode') {
throw new \Exception("Request verification failed.");
$rTopicId = !empty($_GET['t']) && is_scalar($_GET['t']) ? (string)$_GET['t'] : '';
$msz->createAuditLog('FORUM_TOPIC_REDIR_REMOVE', [$rTopicId]);
$msz->logsCtx->createAuthedLog('FORUM_TOPIC_REDIR_REMOVE', [$rTopicId]);
$msz->forumCtx->topicRedirects->deleteTopicRedirect($rTopicId);
Tools::redirect($msz->urls->format('manage-forum-topic-redirs'));
return;

View file

@ -94,9 +94,9 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$sCurrent[] = $string;
}
$msz->createAuditLog(
$msz->logsCtx->createAuthedLog(
$isNew ? 'EMOTICON_CREATE' : 'EMOTICON_EDIT',
[$emoteInfo->id]
[$emoteInfo->id],
);
Tools::redirect($msz->urls->format('manage-general-emoticon', ['emote' => $emoteInfo->id]));

View file

@ -20,20 +20,20 @@ if(CSRF::validateRequest() && !empty($_GET['emote'])) {
if(!empty($_GET['delete'])) {
$msz->emotesCtx->emotes->deleteEmote($emoteInfo);
$msz->createAuditLog('EMOTICON_DELETE', [$emoteInfo->id]);
$msz->logsCtx->createAuthedLog('EMOTICON_DELETE', [$emoteInfo->id]);
} else {
if(isset($_GET['order'])) {
$order = !empty($_GET['order']) && is_scalar($_GET['order']) ? (string)$_GET['order'] : '';
$offset = $order === 'i' ? 10 : ($order === 'd' ? -10 : 0);
$msz->emotesCtx->emotes->updateEmoteOrderOffset($emoteInfo, $offset);
$msz->createAuditLog('EMOTICON_ORDER', [$emoteInfo->id]);
$msz->logsCtx->createAuthedLog('EMOTICON_ORDER', [$emoteInfo->id]);
}
if(isset($_GET['alias'])) {
$alias = !empty($_GET['alias']) && is_scalar($_GET['alias']) ? (string)$_GET['alias'] : '';
if($msz->emotesCtx->emotes->checkEmoteString($alias) === '') {
$msz->emotesCtx->emotes->addEmoteString($emoteInfo, $alias);
$msz->createAuditLog('EMOTICON_ALIAS', [$emoteInfo->id, $alias]);
$msz->logsCtx->createAuthedLog('EMOTICON_ALIAS', [$emoteInfo->id, $alias]);
}
}
}

View file

@ -9,11 +9,11 @@ if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
if(!$msz->authInfo->getPerms('global')->check(Perm::G_LOGS_VIEW))
Template::throwError(403);
$pagination = Pagination::fromInput($msz->auditLog->countLogs(), 50);
$pagination = Pagination::fromInput($msz->logsCtx->logs->countLogs(), 50);
if(!$pagination->validOffset)
Template::throwError(404);
$logs = iterator_to_array($msz->auditLog->getLogs(pagination: $pagination));
$logs = iterator_to_array($msz->logsCtx->logs->getLogs(pagination: $pagination));
$userInfos = [];
$userColours = [];

View file

@ -12,7 +12,7 @@ if($valueInfo === null)
Template::throwError(404);
if($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$msz->createAuditLog('CONFIG_DELETE', [$valueInfo->name]);
$msz->logsCtx->createAuthedLog('CONFIG_DELETE', [$valueInfo->name]);
$msz->config->removeValues($valueInfo->name);
Tools::redirect($msz->urls->format('manage-general-settings'));
return;

View file

@ -74,7 +74,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$applyFunc = $msz->config->setString(...);
}
$msz->createAuditLog($isNew ? 'CONFIG_CREATE' : 'CONFIG_UPDATE', [$sName]);
$msz->logsCtx->createAuthedLog($isNew ? 'CONFIG_CREATE' : 'CONFIG_UPDATE', [$sName]);
$applyFunc($sName, $sValue);
Tools::redirect($msz->urls->format('manage-general-settings'));
return;

View file

@ -27,7 +27,7 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && !empty($_GET['delete'])) {
Template::throwError(403);
$msz->news->deleteCategory($categoryInfo);
$msz->createAuditLog('NEWS_CATEGORY_DELETE', [$categoryInfo->id]);
$msz->logsCtx->createAuthedLog('NEWS_CATEGORY_DELETE', [$categoryInfo->id]);
Tools::redirect($msz->urls->format('manage-news-categories'));
return;
}
@ -51,9 +51,9 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$msz->news->updateCategory($categoryInfo, $name, $description, $hidden);
}
$msz->createAuditLog(
$msz->logsCtx->createAuthedLog(
$isNew ? 'NEWS_CATEGORY_CREATE' : 'NEWS_CATEGORY_EDIT',
[$categoryInfo->id]
[$categoryInfo->id],
);
if($isNew) {

View file

@ -28,7 +28,7 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && !empty($_GET['delete'])) {
Template::throwError(403);
$msz->news->deletePost($postInfo);
$msz->createAuditLog('NEWS_POST_DELETE', [$postInfo->id]);
$msz->logsCtx->createAuthedLog('NEWS_POST_DELETE', [$postInfo->id]);
Tools::redirect($msz->urls->format('manage-news-posts'));
return;
}
@ -55,9 +55,9 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$msz->news->updatePost($postInfo, $category, $title, $body, $featured);
}
$msz->createAuditLog(
$msz->logsCtx->createAuthedLog(
$isNew ? 'NEWS_POST_CREATE' : 'NEWS_POST_EDIT',
[$postInfo->id]
[$postInfo->id],
);
if($isNew && $postInfo->featured) {

View file

@ -22,7 +22,7 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && !empty($_GET['delete'])) {
}
$msz->usersCtx->bans->deleteBans($banInfo);
$msz->createAuditLog('BAN_DELETE', [$banInfo->id, $banInfo->userId]);
$msz->logsCtx->createAuthedLog('BAN_DELETE', [$banInfo->id, $banInfo->userId]);
Tools::redirect($msz->urls->format('manage-users-bans', ['user' => $banInfo->userId]));
return;
}
@ -67,7 +67,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
severity: $severity, modInfo: $modInfo
);
$msz->createAuditLog('BAN_CREATE', [$banInfo->id, $userInfo->id]);
$msz->logsCtx->createAuthedLog('BAN_CREATE', [$banInfo->id, $userInfo->id]);
Tools::redirect($msz->urls->format('manage-users-bans', ['user' => $userInfo->id]));
return;
}

View file

@ -39,7 +39,7 @@ if($hasUserId) {
Template::throwError(403);
$msz->usersCtx->modNotes->deleteNotes($noteInfo);
$msz->createAuditLog('MOD_NOTE_DELETE', [$noteInfo->id, $noteInfo->userId]);
$msz->logsCtx->createAuthedLog('MOD_NOTE_DELETE', [$noteInfo->id, $noteInfo->userId]);
Tools::redirect($msz->urls->format('manage-users-notes', ['user' => $noteInfo->userId]));
return;
}
@ -64,9 +64,9 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$msz->usersCtx->modNotes->updateNote($noteInfo, $title, $body);
}
$msz->createAuditLog(
$msz->logsCtx->createAuthedLog(
$isNew ? 'MOD_NOTE_CREATE' : 'MOD_NOTE_UPDATE',
[$noteInfo->id, $userInfo->id]
[$noteInfo->id, $userInfo->id],
);
// this is easier

View file

@ -148,9 +148,9 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
);
}
$msz->createAuditLog(
$msz->logsCtx->createAuthedLog(
$isNew ? 'ROLE_CREATE' : 'ROLE_UPDATE',
[$roleInfo->id]
[$roleInfo->id],
);
if($canEditPerms) {

View file

@ -62,7 +62,7 @@ if(CSRF::validateRequest() && $canEdit) {
}
if($allowToImpersonate) {
$msz->createAuditLog('USER_IMPERSONATE', [$userInfo->id, $userInfo->name]);
$msz->logsCtx->createAuthedLog('USER_IMPERSONATE', [$userInfo->id, $userInfo->name]);
$tokenBuilder = $msz->authInfo->tokenInfo->toBuilder();
$tokenBuilder->setImpersonatedUserId($userInfo->id);

View file

@ -20,7 +20,7 @@ if($_SERVER['REQUEST_METHOD'] === 'GET' && !empty($_GET['delete'])) {
}
$msz->usersCtx->warnings->deleteWarnings($warnInfo);
$msz->createAuditLog('WARN_DELETE', [$warnInfo->id, $warnInfo->userId]);
$msz->logsCtx->createAuthedLog('WARN_DELETE', [$warnInfo->id, $warnInfo->userId]);
Tools::redirect($msz->urls->format('manage-users-warnings', ['user' => $warnInfo->userId]));
return;
}
@ -41,7 +41,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$userInfo, $body, modInfo: $modInfo
);
$msz->createAuditLog('WARN_CREATE', [$warnInfo->id, $userInfo->id]);
$msz->logsCtx->createAuthedLog('WARN_CREATE', [$warnInfo->id, $userInfo->id]);
Tools::redirect($msz->urls->format('manage-users-warnings', ['user' => $userInfo->id]));
return;
}

View file

@ -90,7 +90,7 @@ if($isVerifiedRequest && !empty($_POST['current_password'])) {
$errors[] = $msz->usersCtx->users->validateEMailAddressText($checkMail);
} else {
$msz->usersCtx->users->updateUser(userInfo: $userInfo, emailAddr: $_POST['email']['new']);
$msz->createAuditLog('PERSONAL_EMAIL_CHANGE', [$_POST['email']['new']]);
$msz->logsCtx->createAuthedLog('PERSONAL_EMAIL_CHANGE', [$_POST['email']['new']]);
}
}
}
@ -106,7 +106,7 @@ if($isVerifiedRequest && !empty($_POST['current_password'])) {
$errors[] = UserPasswordsData::validateUserPasswordText($checkPassword);
} else {
$msz->usersCtx->passwords->updateUserPassword($userInfo, $_POST['password']['new']);
$msz->createAuditLog('PERSONAL_PASSWORD_CHANGE');
$msz->logsCtx->createAuthedLog('PERSONAL_PASSWORD_CHANGE');
}
}
}

View file

@ -116,7 +116,7 @@ if(isset($_POST['action']) && is_string($_POST['action'])) {
&& ($msz->usersCtx->passwords->getUserPassword($userInfo)?->verifyPassword($_POST['password'] ?? ''))) {
switch($_POST['action']) {
case 'data':
$msz->createAuditLog('PERSONAL_DATA_DOWNLOAD');
$msz->logsCtx->createAuthedLog('PERSONAL_DATA_DOWNLOAD');
$timeStamp = floor(time() / 3600) * 3600;
$fileName = sprintf('msz-user-data-%d-%d.zip', $userInfo->id, $timeStamp);

View file

@ -11,10 +11,10 @@ if($currentUser === null)
Template::throwError(401);
$loginHistoryPagination = Pagination::fromInput($msz->authCtx->loginAttempts->countAttempts(userInfo: $currentUser), 5, 'hp');
$accountLogPagination = Pagination::fromInput($msz->auditLog->countLogs(userInfo: $currentUser), 10, 'ap');
$accountLogPagination = Pagination::fromInput($msz->logsCtx->logs->countLogs(userInfo: $currentUser), 10, 'ap');
$loginHistory = iterator_to_array($msz->authCtx->loginAttempts->getAttempts(userInfo: $currentUser, pagination: $loginHistoryPagination));
$auditLogs = iterator_to_array($msz->auditLog->getLogs(userInfo: $currentUser, pagination: $accountLogPagination));
$auditLogs = iterator_to_array($msz->logsCtx->logs->getLogs(userInfo: $currentUser, pagination: $accountLogPagination));
Template::render('settings.logs', [
'login_history_list' => $loginHistory,

View file

@ -20,7 +20,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
if($sessionId === 'all') {
$activeSessionKilled = true;
$msz->authCtx->sessions->deleteSessions(userInfos: $currentUser);
$msz->createAuditLog('PERSONAL_SESSION_DESTROY_ALL');
$msz->logsCtx->createAuthedLog('PERSONAL_SESSION_DESTROY_ALL');
} else {
try {
$sessionInfo = $msz->authCtx->sessions->getSession(sessionId: $sessionId);
@ -33,7 +33,7 @@ while($_SERVER['REQUEST_METHOD'] === 'POST' && CSRF::validateRequest()) {
$activeSessionKilled = $sessionInfo->id === $activeSessionId;
$msz->authCtx->sessions->deleteSessions(sessionInfos: $sessionInfo);
$msz->createAuditLog('PERSONAL_SESSION_DESTROY', [$sessionInfo->id]);
$msz->logsCtx->createAuthedLog('PERSONAL_SESSION_DESTROY', [$sessionInfo->id]);
}
if($activeSessionKilled) {

View file

@ -5,6 +5,8 @@ use RuntimeException;
use Index\MediaType;
use Index\Http\Content\MultipartFormContent;
use Index\Http\Content\Multipart\ValueMultipartFormData;
use Index\Http\Routing\Router;
use Index\Http\Routing\Routes\RouteInfo;
use Misuzu\Auth\{AuthTokenBuilder,AuthTokenCookie,AuthTokenInfo};
require_once __DIR__ . '/../misuzu.php';
@ -115,51 +117,6 @@ $router = $msz->createRouting($request);
$msz->startTemplating();
if($msz->domainRoles->hasRole($request->getHeaderLine('Host'), 'main')) {
// Reconstruct $_POST since PHP no longer makes it for us
if($request->getBody()->isReadable() && empty($_POST)) {
$mszRequestContent = (function($contentType, $stream) {
if($contentType->equals('application/x-www-form-urlencoded')) {
parse_str((string)$stream, $postVars);
return $postVars;
}
if($contentType->equals('multipart/form-data'))
try {
return MultipartFormContent::parseStream($stream, $contentType->boundary);
} catch(RuntimeException $ex) {}
return null;
})(MediaType::parse($request->getHeaderLine('Content-Type')), $request->getBody());
$_POST = (function($requestContent) {
if(is_array($requestContent))
return $requestContent;
if($requestContent instanceof MultipartFormContent) {
$postVars = [];
foreach($requestContent->params as $name => $values) {
if(count($values) === 0)
$postVars[$name] = '';
elseif(count($values) === 1)
$postVars[$name] = $values[0] instanceof ValueMultipartFormData ? (string)$values[0] : '';
else {
$postVar = [];
foreach($values as $value)
$postVars[] = $value instanceof ValueMultipartFormData ? (string)$value : '';
$postVars[$name] = $postVar;
}
}
return $postVars;
}
return [];
})($mszRequestContent);
$_REQUEST = array_merge($_GET, $_POST);
}
$mszRequestPath = substr($request->requestTarget, 1);
$mszLegacyPathPrefix = Misuzu::PATH_PUBLIC_LEGACY . '/';
$mszLegacyPath = $mszLegacyPathPrefix . $mszRequestPath;
@ -167,6 +124,14 @@ if($msz->domainRoles->hasRole($request->getHeaderLine('Host'), 'main')) {
if(str_starts_with($mszLegacyPath, $mszLegacyPathPrefix)) {
$mszLegacyPathReal = realpath($mszLegacyPath);
if($mszLegacyPath === $mszLegacyPathReal || $mszLegacyPath === $mszLegacyPathReal . '/') {
// this is here so filters can run...
$router->router->route(RouteInfo::exact($request->method, $request->requestTarget, function() {}));
$response = $router->router->handle($request);
if($response->getBody()->getSize() > 0) {
Router::output($response);
exit;
}
if(str_starts_with($mszRequestPath, 'manage') && !$msz->hasManageAccess())
Template::throwError(403);
@ -174,6 +139,51 @@ if($msz->domainRoles->hasRole($request->getHeaderLine('Host'), 'main')) {
$mszLegacyPath .= '/index.php';
if(is_file($mszLegacyPath)) {
// Reconstruct $_POST since PHP no longer makes it for us
if($request->getBody()->isReadable() && empty($_POST)) {
$mszRequestContent = (function($contentType, $stream) {
if($contentType->equals('application/x-www-form-urlencoded')) {
parse_str((string)$stream, $postVars);
return $postVars;
}
if($contentType->equals('multipart/form-data'))
try {
return MultipartFormContent::parseStream($stream, $contentType->boundary);
} catch(RuntimeException $ex) {}
return null;
})(MediaType::parse($request->getHeaderLine('Content-Type')), $request->getBody());
$_POST = (function($requestContent) {
if(is_array($requestContent))
return $requestContent;
if($requestContent instanceof MultipartFormContent) {
$postVars = [];
foreach($requestContent->params as $name => $values) {
if(count($values) === 0)
$postVars[$name] = '';
elseif(count($values) === 1)
$postVars[$name] = $values[0] instanceof ValueMultipartFormData ? (string)$values[0] : '';
else {
$postVar = [];
foreach($values as $value)
$postVars[] = $value instanceof ValueMultipartFormData ? (string)$value : '';
$postVars[$name] = $postVar;
}
}
return $postVars;
}
return [];
})($mszRequestContent);
$_REQUEST = array_merge($_GET, $_POST);
}
require_once $mszLegacyPath;
return;
}

View file

@ -7,8 +7,8 @@ use Index\Http\Routing\{RouteHandler,RouteHandlerCommon};
use Index\Http\Routing\Routes\PatternRoute;
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
use Misuzu\{CSRF,Perm};
use Misuzu\AuditLog\AuditLogData;
use Misuzu\Auth\AuthInfo;
use Misuzu\Logs\LogsContext;
use Misuzu\Users\UsersContext;
class ForumPostsRoutes implements RouteHandler, UrlSource {
@ -16,9 +16,9 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
public function __construct(
private UrlRegistry $urls,
private ForumContext $forum,
private ForumContext $forumCtx,
private UsersContext $usersCtx,
private AuditLogData $auditLog,
private LogsContext $logsCtx,
private AuthInfo $authInfo,
) {}
@ -26,7 +26,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
#[UrlFormat('forum-post', '/forum/posts/<post>')]
public function getPost(HttpResponseBuilder $response, HttpRequest $request, string $postId): mixed {
try {
$post = $this->forum->posts->getPost(postId: $postId);
$post = $this->forumCtx->posts->getPost(postId: $postId);
} catch(RuntimeException $ex) {
return 404;
}
@ -39,7 +39,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
if($post->deleted && !$canDeleteAny)
return 404;
$postsCount = $this->forum->posts->countPosts(
$postsCount = $this->forumCtx->posts->countPosts(
topicInfo: $post->topicId,
upToPostInfo: $post,
deleted: $canDeleteAny ? null : false
@ -76,7 +76,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
try {
$post = $this->forum->posts->getPost(
$post = $this->forumCtx->posts->getPost(
postId: $postId,
deleted: false,
);
@ -102,7 +102,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
if(!$perms->check(Perm::F_POST_DELETE_ANY)) {
$topic = $this->forum->topics->getTopic(postInfo: $post);
$topic = $this->forumCtx->topics->getTopic(postInfo: $post);
if($topic->deleted) {
$response->statusCode = 404;
return [
@ -156,7 +156,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
}
$originalPost = $this->forum->posts->getPost(topicInfo: $post->topicId);
$originalPost = $this->forumCtx->posts->getPost(topicInfo: $post->topicId);
if($originalPost->id === $post->id) {
$response->statusCode = 403;
return [
@ -167,7 +167,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
];
}
$category = $this->forum->categories->getCategory(postInfo: $post);
$category = $this->forumCtx->categories->getCategory(postInfo: $post);
if($category->archived) {
$response->statusCode = 400;
return [
@ -178,14 +178,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
];
}
$this->forum->posts->deletePost($post);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_POST_DELETE',
[$post->id],
$request->remoteAddress,
$request->countryCode
);
$this->forumCtx->posts->deletePost($post);
$this->logsCtx->createAuthedLog('FORUM_POST_DELETE', [$post->id]);
return 204;
}
@ -211,7 +205,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
try {
$post = $this->forum->posts->getPost(
$post = $this->forumCtx->posts->getPost(
postId: $postId,
deleted: true,
);
@ -247,7 +241,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
];
}
$category = $this->forum->categories->getCategory(postInfo: $post);
$category = $this->forumCtx->categories->getCategory(postInfo: $post);
if($category->archived) {
$response->statusCode = 400;
return [
@ -258,14 +252,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
];
}
$this->forum->posts->nukePost($post);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_POST_NUKE',
[$post->id],
$request->remoteAddress,
$request->countryCode
);
$this->forumCtx->posts->nukePost($post);
$this->logsCtx->createAuthedLog('FORUM_POST_NUKE', [$post->id]);
return 204;
}
@ -291,7 +279,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
}
try {
$post = $this->forum->posts->getPost(
$post = $this->forumCtx->posts->getPost(
postId: $postId,
deleted: true,
);
@ -327,7 +315,7 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
];
}
$category = $this->forum->categories->getCategory(postInfo: $post);
$category = $this->forumCtx->categories->getCategory(postInfo: $post);
if($category->archived) {
$response->statusCode = 400;
return [
@ -338,14 +326,8 @@ class ForumPostsRoutes implements RouteHandler, UrlSource {
];
}
$this->forum->posts->restorePost($post);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_POST_RESTORE',
[$post->id],
$request->remoteAddress,
$request->countryCode
);
$this->forumCtx->posts->restorePost($post);
$this->logsCtx->createAuthedLog('FORUM_POST_RESTORE', [$post->id]);
return 204;
}

View file

@ -9,8 +9,8 @@ use Index\Http\Routing\{RouteHandler,RouteHandlerCommon};
use Index\Http\Routing\Routes\PatternRoute;
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
use Misuzu\{CSRF,Pagination,Perm,Template};
use Misuzu\AuditLog\AuditLogData;
use Misuzu\Auth\AuthInfo;
use Misuzu\Logs\LogsContext;
use Misuzu\Users\UsersContext;
class ForumTopicsRoutes implements RouteHandler, UrlSource {
@ -19,7 +19,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
public function __construct(
private ForumContext $forumCtx,
private UsersContext $usersCtx,
private AuditLogData $auditLog,
private LogsContext $logsCtx,
private AuthInfo $authInfo,
) {}
@ -263,13 +263,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
$this->forumCtx->topics->deleteTopic($topic);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_TOPIC_DELETE',
[$topic->id],
$request->remoteAddress,
$request->countryCode
);
$this->logsCtx->createAuthedLog('FORUM_TOPIC_DELETE', [$topic->id]);
return 204;
}
@ -343,13 +337,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
$this->forumCtx->topics->restoreTopic($topic);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_TOPIC_RESTORE',
[$topic->id],
$request->remoteAddress,
$request->countryCode
);
$this->logsCtx->createAuthedLog('FORUM_TOPIC_RESTORE', [$topic->id]);
return 204;
}
@ -423,13 +411,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
$this->forumCtx->topics->nukeTopic($topic);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_TOPIC_NUKE',
[$topic->id],
$request->remoteAddress,
$request->countryCode
);
$this->logsCtx->createAuthedLog('FORUM_TOPIC_NUKE', [$topic->id]);
return 204;
}
@ -503,13 +485,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
$this->forumCtx->topics->bumpTopic($topic);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_TOPIC_BUMP',
[$topic->id],
$request->remoteAddress,
$request->countryCode
);
$this->logsCtx->createAuthedLog('FORUM_TOPIC_BUMP', [$topic->id]);
return 204;
}
@ -593,13 +569,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
$this->forumCtx->topics->lockTopic($topic);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_TOPIC_LOCK',
[$topic->id],
$request->remoteAddress,
$request->countryCode
);
$this->logsCtx->createAuthedLog('FORUM_TOPIC_LOCK', [$topic->id]);
return 204;
}
@ -683,13 +653,7 @@ class ForumTopicsRoutes implements RouteHandler, UrlSource {
}
$this->forumCtx->topics->unlockTopic($topic);
$this->auditLog->createLog(
$this->authInfo->userInfo,
'FORUM_TOPIC_UNLOCK',
[$topic->id],
$request->remoteAddress,
$request->countryCode
);
$this->logsCtx->createAuthedLog('FORUM_TOPIC_UNLOCK', [$topic->id]);
return 204;
}

View file

@ -1,11 +1,11 @@
<?php
namespace Misuzu\AuditLog;
namespace Misuzu\Logs;
use ValueError;
use Carbon\CarbonImmutable;
use Index\Db\DbResult;
class AuditLogInfo {
class LogInfo {
/** @param scalar[] $params */
public function __construct(
public private(set) string $id,
@ -17,8 +17,8 @@ class AuditLogInfo {
public private(set) string $countryCode,
) {}
public static function fromResult(DbResult $result): AuditLogInfo {
return new AuditLogInfo(
public static function fromResult(DbResult $result): LogInfo {
return new LogInfo(
id: $result->getString(0),
userId: $result->getStringOrNull(1),
action: $result->getString(2),

60
src/Logs/LogsContext.php Normal file
View file

@ -0,0 +1,60 @@
<?php
namespace Misuzu\Logs;
use Index\Db\DbConnection;
use Index\Http\HttpRequest;
use Index\Http\Routing\{RouteHandler,RouteHandlerCommon};
use Index\Http\Routing\Filters\PrefixFilter;
use Misuzu\Auth\AuthInfo;
use Misuzu\Users\UserInfo;
class LogsContext implements RouteHandler {
use RouteHandlerCommon;
public private(set) LogsData $logs;
private ?HttpRequest $request = null;
public function __construct(
DbConnection $dbConn,
private AuthInfo $authInfo,
) {
$this->logs = new LogsData($dbConn);
}
#[PrefixFilter('/')]
public function filterRequest(HttpRequest $request): void {
$this->request = $request;
}
/** @param mixed[] $params */
public function createSystemLog(string $action, array $params = []): void {
$this->logs->createLog(null, $action, $params, null, 'XS');
}
/** @param mixed[] $params */
public function createAuthedLog(string $action, array $params = []): void {
$this->logs->createLog(
$this->authInfo->userInfo,
$action,
$params,
$this->request?->remoteAddress,
$this->request->countryCode ?? 'XX',
);
}
/** @param mixed[] $params */
public function createUserLog(
UserInfo|string|null $userInfo,
string $action,
array $params = [],
): void {
$this->logs->createLog(
$userInfo,
$action,
$params,
$this->request?->remoteAddress,
$this->request->countryCode ?? 'XX',
);
}
}

View file

@ -1,12 +1,12 @@
<?php
namespace Misuzu\AuditLog;
namespace Misuzu\Logs;
use InvalidArgumentException;
use Index\Db\{DbConnection,DbStatementCache};
use Misuzu\Pagination;
use Misuzu\Users\UserInfo;
class AuditLogData {
class LogsData {
private DbStatementCache $cache;
public function __construct(DbConnection $dbConn) {
@ -15,13 +15,13 @@ class AuditLogData {
public function countLogs(
UserInfo|string|null $userInfo = null,
?string $remoteAddr = null
string|null|false $remoteAddress = false,
): int {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->id;
$hasUserInfo = $userInfo !== null;
$hasRemoteAddr = $remoteAddr !== null;
$hasRemoteAddr = $remoteAddress !== false;
$args = 0;
$query = 'SELECT COUNT(*) FROM msz_audit_log';
@ -29,17 +29,19 @@ class AuditLogData {
++$args;
$query .= ' WHERE user_id = ?';
}
if($hasRemoteAddr) {
$query .= (++$args > 1 ? ' AND' : ' WHERE');
$query .= ' log_remote_addr = INET6_ATON(?)';
}
if($remoteAddress !== false)
$query .= sprintf(
' %s log_remote_addr %s',
++$args > 1 ? ' AND' : ' WHERE',
$remoteAddress === null ? 'IS NULL' : '= INET6_ATON(?)'
);
$stmt = $this->cache->get($query);
if($hasUserInfo)
$stmt->nextParameter($userInfo);
if($hasRemoteAddr)
$stmt->nextParameter($remoteAddr);
if(is_string($remoteAddress))
$stmt->nextParameter($remoteAddress);
$stmt->execute();
$result = $stmt->getResult();
@ -51,17 +53,16 @@ class AuditLogData {
return $count;
}
/** @return \Iterator<int, AuditLogInfo> */
/** @return \Iterator<int, LogInfo> */
public function getLogs(
UserInfo|string|null $userInfo = null,
?string $remoteAddr = null,
string|null|false $remoteAddress = false,
?Pagination $pagination = null
): iterable {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->id;
$hasUserInfo = $userInfo !== null;
$hasRemoteAddr = $remoteAddr !== null;
$hasPagination = $pagination !== null;
$args = 0;
@ -76,10 +77,12 @@ class AuditLogData {
++$args;
$query .= ' WHERE user_id = ?';
}
if($hasRemoteAddr) {
$query .= (++$args > 1 ? ' AND' : ' WHERE');
$query .= ' log_remote_addr = INET6_ATON(?)';
}
if($remoteAddress !== false)
$query .= sprintf(
' %s log_remote_addr %s',
++$args > 1 ? ' AND' : ' WHERE',
$remoteAddress === null ? 'IS NULL' : '= INET6_ATON(?)'
);
$query .= ' ORDER BY log_created DESC';
if($hasPagination)
$query .= ' LIMIT ? OFFSET ?';
@ -88,14 +91,14 @@ class AuditLogData {
if($hasUserInfo)
$stmt->nextParameter($userInfo);
if($hasRemoteAddr)
$stmt->nextParameter($remoteAddr);
if(is_string($remoteAddress))
$stmt->nextParameter($remoteAddress);
if($hasPagination)
$pagination->addToStatement($stmt);
$stmt->execute();
return $stmt->getResultIterator(AuditLogInfo::fromResult(...));
return $stmt->getResultIterator(LogInfo::fromResult(...));
}
/** @param mixed[] $params */
@ -103,9 +106,9 @@ class AuditLogData {
UserInfo|string|null $userInfo,
string $action,
array $params = [],
string $remoteAddr = '::1',
string $countryCode = 'XX'
): void {
?string $remoteAddress = null,
string $countryCode = 'XX',
): string {
if($userInfo instanceof UserInfo)
$userInfo = $userInfo->id;
@ -131,8 +134,10 @@ class AuditLogData {
$stmt->nextParameter($userInfo);
$stmt->nextParameter($action);
$stmt->nextParameter($params);
$stmt->nextParameter($remoteAddr);
$stmt->nextParameter($remoteAddress);
$stmt->nextParameter($countryCode);
$stmt->execute();
return (string)$stmt->lastInsertId;
}
}

View file

@ -24,10 +24,8 @@ class MisuzuContext {
public private(set) BinarySnowflake $sfBinary;
public private(set) RandomSnowflake $sfRandom;
public private(set) AuditLog\AuditLogData $auditLog;
public private(set) Counters\CountersData $counters;
public private(set) Changelog\ChangelogData $changelog;
public private(set) Counters\CountersData $counters;
public private(set) News\NewsData $news;
public private(set) DatabaseContext $dbCtx;
@ -37,6 +35,7 @@ class MisuzuContext {
public private(set) Comments\CommentsContext $commentsCtx;
public private(set) Emoticons\EmotesContext $emotesCtx;
public private(set) Forum\ForumContext $forumCtx;
public private(set) Logs\LogsContext $logsCtx;
public private(set) Messages\MessagesContext $messagesCtx;
public private(set) OAuth2\OAuth2Context $oauth2Ctx;
public private(set) Profile\ProfileContext $profileCtx;
@ -101,6 +100,7 @@ class MisuzuContext {
Forum\ForumContext::class,
config: $this->config->scopeTo('forum'),
));
$this->deps->register($this->logsCtx = $this->deps->constructLazy(Logs\LogsContext::class));
$this->deps->register($this->messagesCtx = $this->deps->constructLazy(
Messages\MessagesContext::class,
config: $this->config->scopeTo('messages'),
@ -116,7 +116,6 @@ class MisuzuContext {
config: $this->config->scopeTo('redirects'),
));
$this->deps->register($this->auditLog = $this->deps->constructLazy(AuditLog\AuditLogData::class));
$this->deps->register($this->changelog = $this->deps->constructLazy(Changelog\ChangelogData::class));
$this->deps->register($this->counters = $this->deps->constructLazy(Counters\CountersData::class));
$this->deps->register($this->news = $this->deps->constructLazy(News\NewsData::class));
@ -132,20 +131,6 @@ class MisuzuContext {
Mailer::init($this->config->scopeTo('mail'));
}
/** @param mixed[] $params */
public function createAuditLog(string $action, array $params = [], UserInfo|string|null $userInfo = null): void {
if($userInfo === null && $this->authInfo->loggedIn)
$userInfo = $this->authInfo->userInfo;
$this->auditLog->createLog(
$userInfo,
$action,
$params,
$_SERVER['REMOTE_ADDR'] ?? '::1',
$_SERVER['COUNTRY_CODE'] ?? 'XX'
);
}
private ?bool $hasManageAccess = null;
public function hasManageAccess(): bool {
$this->hasManageAccess ??= $this->authInfo->loggedIn
@ -190,6 +175,7 @@ class MisuzuContext {
$routingCtx = $this->deps->construct(RoutingContext::class);
$this->deps->register($this->urls = $routingCtx->urls);
$routingCtx->register($this->logsCtx);
if(in_array('main', $roles))
$this->registerMainRoutes($routingCtx);