Added logging engine for #61

This commit is contained in:
Marcin Kurczewski 2013-11-16 21:21:43 +01:00
parent 45e9d32f58
commit 04e9bad79e
7 changed files with 145 additions and 4 deletions

View file

@ -9,6 +9,7 @@ thumbsPath=./thumbs/
mediaPath=./public_html/media/ mediaPath=./public_html/media/
title=szurubooru title=szurubooru
salt = "1A2/$_4xVa" salt = "1A2/$_4xVa"
logsPath=./logs/
[misc] [misc]
featuredPostMaxDays=7 featuredPostMaxDays=7

2
logs/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

View file

@ -63,6 +63,7 @@ class CommentController
if (InputHelper::get('sender') != 'preview') if (InputHelper::get('sender') != 'preview')
R::store($comment); R::store($comment);
$this->context->transport->textPreview = $comment->getText(); $this->context->transport->textPreview = $comment->getText();
LogHelper::logEvent('comment-add', '+{user} commented on @{post}', ['post' => $post->id]);
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -78,6 +79,7 @@ class CommentController
$comment = Model_Comment::locate($id); $comment = Model_Comment::locate($id);
R::preload($comment, ['commenter' => 'user']); R::preload($comment, ['commenter' => 'user']);
PrivilegesHelper::confirmWithException(Privilege::DeleteComment, PrivilegesHelper::getIdentitySubPrivilege($comment->commenter)); PrivilegesHelper::confirmWithException(Privilege::DeleteComment, PrivilegesHelper::getIdentitySubPrivilege($comment->commenter));
LogHelper::logEvent('comment-del', '+{user} removed comment from @{post}', ['post' => $comment->post->id]);
R::trash($comment); R::trash($comment);
StatusHelper::success(); StatusHelper::success();
} }

View file

@ -130,9 +130,15 @@ class PostController
$tags = array_map(function($x) { return $x->name; }, $post->sharedTag); $tags = array_map(function($x) { return $x->name; }, $post->sharedTag);
if (in_array($tag, $tags)) if (in_array($tag, $tags))
{
$tags = array_diff($tags, [$tag]); $tags = array_diff($tags, [$tag]);
LogHelper::logEvent('post-tag-del', '+{user} untagged @{post} with #{tag}', ['post' => $post->id, 'tag' => $tag]);
}
else else
{
$tags += [$tag]; $tags += [$tag];
LogHelper::logEvent('post-tag-add', '+{user} tagged @{post} with #{tag}', ['post' => $post->id, 'tag' => $tag]);
}
$dbTags = Model_Tag::insertOrUpdate($tags); $dbTags = Model_Tag::insertOrUpdate($tags);
$post->sharedTag = $dbTags; $post->sharedTag = $dbTags;
@ -339,6 +345,12 @@ class PostController
} }
R::store($dbPost); R::store($dbPost);
LogHelper::logEvent('post-new',
'+{user} added @{post} tagged with '
. join(', ', array_map(function($dbTag) { return '#' . $dbTag->name; }, $dbTags))
. ' marked as ' . PostSafety::toString($dbPost->safety),
['post' => $dbPost->id]);
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -356,14 +368,17 @@ class PostController
if (InputHelper::get('submit')) if (InputHelper::get('submit'))
{ {
LogHelper::bufferChanges();
/* safety */ /* safety */
$suppliedSafety = InputHelper::get('safety'); $suppliedSafety = InputHelper::get('safety');
if ($suppliedSafety !== null) if ($suppliedSafety !== null and $suppliedSafety != $post->safety)
{ {
PrivilegesHelper::confirmWithException(Privilege::EditPostSafety, PrivilegesHelper::getIdentitySubPrivilege($post->uploader)); PrivilegesHelper::confirmWithException(Privilege::EditPostSafety, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
$suppliedSafety = Model_Post::validateSafety($suppliedSafety); $suppliedSafety = Model_Post::validateSafety($suppliedSafety);
$post->safety = $suppliedSafety; $post->safety = $suppliedSafety;
$edited = true; $edited = true;
LogHelper::logEvent('post-edit', '+{user} changed safety for @{post} to {safety}', ['post' => $post->id, 'safety' => PostSafety::toString($post->safety)]);
} }
@ -378,8 +393,15 @@ class PostController
$suppliedTags = Model_Tag::validateTags($suppliedTags); $suppliedTags = Model_Tag::validateTags($suppliedTags);
$dbTags = Model_Tag::insertOrUpdate($suppliedTags); $dbTags = Model_Tag::insertOrUpdate($suppliedTags);
$oldTags = array_map(function($tag) { return $tag->name; }, $post->sharedTag);
$post->sharedTag = $dbTags; $post->sharedTag = $dbTags;
$edited = true; $edited = true;
foreach (array_diff($oldTags, $suppliedTags) as $tag)
LogHelper::logEvent('post-tag-del', '+{user} untagged @{post} with #{tag}', ['post' => $post->id, 'tag' => $tag]);
foreach (array_diff($suppliedTags, $oldTags) as $tag)
LogHelper::logEvent('post-tag-add', '+{user} tagged @{post} with #{tag}', ['post' => $post->id, 'tag' => $tag]);
} }
@ -401,17 +423,19 @@ class PostController
$path = $this->config->main->thumbsPath . DS . $post->name . '.custom'; $path = $this->config->main->thumbsPath . DS . $post->name . '.custom';
move_uploaded_file($suppliedFile['tmp_name'], $path); move_uploaded_file($suppliedFile['tmp_name'], $path);
LogHelper::logEvent('post-edit', '+{user} added custom thumb for @{post}', ['post' => $post->id]);
} }
/* source */ /* source */
$suppliedSource = InputHelper::get('source'); $suppliedSource = InputHelper::get('source');
if ($suppliedSource !== null) if ($suppliedSource !== null and $suppliedSource != $post->sorce)
{ {
PrivilegesHelper::confirmWithException(Privilege::EditPostSource, PrivilegesHelper::getIdentitySubPrivilege($post->uploader)); PrivilegesHelper::confirmWithException(Privilege::EditPostSource, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
$suppliedSource = Model_Post::validateSource($suppliedSource); $suppliedSource = Model_Post::validateSource($suppliedSource);
$post->source = $suppliedSource; $post->source = $suppliedSource;
$edited = true; $edited = true;
LogHelper::logEvent('post-edit', '+{user} changed source for @{post} to {source}', ['post' => $post->id, 'source' => $post->source]);
} }
@ -430,13 +454,20 @@ class PostController
throw new SimpleException('Too many related posts (maximum: ' . $this->config->browsing->maxRelatedPosts . ')'); throw new SimpleException('Too many related posts (maximum: ' . $this->config->browsing->maxRelatedPosts . ')');
$relatedPosts []= Model_Post::locate($relatedId); $relatedPosts []= Model_Post::locate($relatedId);
} }
$oldRelatedIds = array_map(function($post) { return $post->id; }, $post->via('crossref')->sharedPost);
$post->via('crossref')->sharedPost = $relatedPosts; $post->via('crossref')->sharedPost = $relatedPosts;
foreach (array_diff($oldRelatedIds, $relatedIds) as $post2id)
LogHelper::logEvent('post-relation-del', '+{user} removed relation between @{post} and #{post2}', ['post' => $post->id, 'post2' => $post2id]);
foreach (array_diff($relatedIds, $oldRelatedIds) as $post2id)
LogHelper::logEvent('post-relation-add', '+{user} added relation between @{post} and #{post2}', ['post' => $post->id, 'post2' => $post2id]);
} }
R::store($post); R::store($post);
Model_Tag::removeUnused(); Model_Tag::removeUnused();
LogHelper::flush();
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -451,14 +482,19 @@ class PostController
$post = Model_Post::locate($id); $post = Model_Post::locate($id);
R::preload($post, ['uploader' => 'user']); R::preload($post, ['uploader' => 'user']);
PrivilegesHelper::confirmWithException(Privilege::HidePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader)); PrivilegesHelper::confirmWithException(Privilege::HidePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
if (InputHelper::get('submit')) if (InputHelper::get('submit'))
{ {
$post->hidden = true; $post->hidden = true;
R::store($post); R::store($post);
LogHelper::logEvent('post-hide', '+{user} hidden @{post}', ['post' => $post->id]);
StatusHelper::success(); StatusHelper::success();
} }
} }
/** /**
* @route /post/{id}/unhide * @route /post/{id}/unhide
*/ */
@ -467,14 +503,19 @@ class PostController
$post = Model_Post::locate($id); $post = Model_Post::locate($id);
R::preload($post, ['uploader' => 'user']); R::preload($post, ['uploader' => 'user']);
PrivilegesHelper::confirmWithException(Privilege::HidePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader)); PrivilegesHelper::confirmWithException(Privilege::HidePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
if (InputHelper::get('submit')) if (InputHelper::get('submit'))
{ {
$post->hidden = false; $post->hidden = false;
R::store($post); R::store($post);
LogHelper::logEvent('post-unhide', '+{user} unhidden @{post}', ['post' => $post->id]);
StatusHelper::success(); StatusHelper::success();
} }
} }
/** /**
* @route /post/{id}/delete * @route /post/{id}/delete
*/ */
@ -483,6 +524,7 @@ class PostController
$post = Model_Post::locate($id); $post = Model_Post::locate($id);
R::preload($post, ['uploader' => 'user']); R::preload($post, ['uploader' => 'user']);
PrivilegesHelper::confirmWithException(Privilege::DeletePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader)); PrivilegesHelper::confirmWithException(Privilege::DeletePost, PrivilegesHelper::getIdentitySubPrivilege($post->uploader));
if (InputHelper::get('submit')) if (InputHelper::get('submit'))
{ {
//remove stuff from auxiliary tables //remove stuff from auxiliary tables
@ -495,6 +537,8 @@ class PostController
$post->sharedTag = []; $post->sharedTag = [];
R::store($post); R::store($post);
R::trash($post); R::trash($post);
LogHelper::logEvent('post-delete', '+{user} deleted @{post}', ['post' => $id]);
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -597,6 +641,7 @@ class PostController
Model_Property::set(Model_Property::FeaturedPostUserId, $this->context->user->id); Model_Property::set(Model_Property::FeaturedPostUserId, $this->context->user->id);
Model_Property::set(Model_Property::FeaturedPostDate, time()); Model_Property::set(Model_Property::FeaturedPostDate, time());
StatusHelper::success(); StatusHelper::success();
LogHelper::logEvent('post-feature', '+{user} featured @{post} on main page', ['post' => $post->id]);
} }

View file

@ -69,7 +69,9 @@ class TagController
R::store($post); R::store($post);
} }
R::trash($sourceTag); R::trash($sourceTag);
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('tag', 'list')); \Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('tag', 'list'));
LogHelper::logEvent('tag-merge', '+{user} merged #{source} with #{target}', ['source' => $suppliedSourceTag, 'target' => $suppliedTargetTag]);
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -101,6 +103,7 @@ class TagController
R::store($sourceTag); R::store($sourceTag);
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('tag', 'list')); \Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('tag', 'list'));
LogHelper::logEvent('tag-rename', '+{user} renamed #{source} to #{target}', ['source' => $suppliedSourceTag, 'target' => $suppliedTargetTag]);
StatusHelper::success(); StatusHelper::success();
} }
} }

View file

@ -49,6 +49,8 @@ class UserController
$headers []= sprintf('X-Originating-IP: %s', $_SERVER['SERVER_ADDR']); $headers []= sprintf('X-Originating-IP: %s', $_SERVER['SERVER_ADDR']);
$subject = '=?UTF-8?B?' . base64_encode($subject) . '?='; $subject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
mail($recipientEmail, $subject, $body, implode("\r\n", $headers), '-f' . $senderEmail); mail($recipientEmail, $subject, $body, implode("\r\n", $headers), '-f' . $senderEmail);
LogHelper::logEvent('mail', 'Sending e-mail with subject "' . $subject . '" to ' . $recipientEmail);
} }
private static function sendEmailChangeConfirmation($user) private static function sendEmailChangeConfirmation($user)
@ -147,6 +149,7 @@ class UserController
{ {
$user->banned = true; $user->banned = true;
R::store($user); R::store($user);
LogHelper::logEvent('ban', '+{user} banned +{subject}', ['subject' => $user->name]);
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -163,6 +166,7 @@ class UserController
{ {
$user->banned = false; $user->banned = false;
R::store($user); R::store($user);
LogHelper::logEvent('unban', '+{user} unbanned +{subject}', ['subject' => $user->name]);
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -179,6 +183,7 @@ class UserController
{ {
$user->staff_confirmed = true; $user->staff_confirmed = true;
R::store($user); R::store($user);
LogHelper::logEvent('reg-accept', '+{user} confirmed account for +{subject}', ['subject' => $user->name]);
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -207,6 +212,7 @@ class UserController
if (InputHelper::get('submit')) if (InputHelper::get('submit'))
{ {
$name = $user->name;
if ($this->context->user->id == $user->id) if ($this->context->user->id == $user->id)
{ {
$suppliedPasswordHash = Model_User::hashPassword($suppliedCurrentPassword, $user->pass_salt); $suppliedPasswordHash = Model_User::hashPassword($suppliedCurrentPassword, $user->pass_salt);
@ -228,7 +234,9 @@ class UserController
AuthController::doLogOut(); AuthController::doLogOut();
R::store($user); R::store($user);
R::trash($user); R::trash($user);
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('index', 'index')); \Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('index', 'index'));
LogHelper::logEvent('user-del', '+{user} removed account for +{subject}', ['subject' => $name]);
StatusHelper::success(); StatusHelper::success();
} }
} }
@ -303,12 +311,15 @@ class UserController
if (InputHelper::get('submit')) if (InputHelper::get('submit'))
{ {
$confirmMail = false; $confirmMail = false;
LogHelper::bufferChanges();
if ($suppliedName != '' and $suppliedName != $user->name) if ($suppliedName != '' and $suppliedName != $user->name)
{ {
PrivilegesHelper::confirmWithException(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($user)); PrivilegesHelper::confirmWithException(Privilege::ChangeUserName, PrivilegesHelper::getIdentitySubPrivilege($user));
$suppliedName = Model_User::validateUserName($suppliedName); $suppliedName = Model_User::validateUserName($suppliedName);
$oldName = $user->name;
$user->name = $suppliedName; $user->name = $suppliedName;
LogHelper::logEvent('user-edit', '+{user} renamed +{old} to +{new}', ['old' => $oldName, 'new' => $suppliedName]);
} }
if ($suppliedPassword1 != '') if ($suppliedPassword1 != '')
@ -318,6 +329,7 @@ class UserController
throw new SimpleException('Specified passwords must be the same'); throw new SimpleException('Specified passwords must be the same');
$suppliedPassword = Model_User::validatePassword($suppliedPassword1); $suppliedPassword = Model_User::validatePassword($suppliedPassword1);
$user->pass_hash = Model_User::hashPassword($suppliedPassword, $user->pass_salt); $user->pass_hash = Model_User::hashPassword($suppliedPassword, $user->pass_salt);
LogHelper::logEvent('user-edit', '+{user} changed password for +{subject}', ['subject' => $user->name]);
} }
if ($suppliedEmail != '' and $suppliedEmail != $user->email_confirmed) if ($suppliedEmail != '' and $suppliedEmail != $user->email_confirmed)
@ -329,11 +341,13 @@ class UserController
$user->email_unconfirmed = $suppliedEmail; $user->email_unconfirmed = $suppliedEmail;
if (!empty($user->email_unconfirmed)) if (!empty($user->email_unconfirmed))
$confirmMail = true; $confirmMail = true;
LogHelper::logEvent('user-edit', '+{user} changed e-mail to {mail}', ['mail' => $suppliedEmail]);
} }
else else
{ {
$user->email_unconfirmed = null; $user->email_unconfirmed = null;
$user->email_confirmed = $suppliedEmail; $user->email_confirmed = $suppliedEmail;
LogHelper::logEvent('user-edit', '+{user} changed e-mail for +{subject} to {mail}', ['subject' => $user->name, 'mail' => $suppliedEmail]);
} }
} }
@ -342,6 +356,7 @@ class UserController
PrivilegesHelper::confirmWithException(Privilege::ChangeUserAccessRank, PrivilegesHelper::getIdentitySubPrivilege($user)); PrivilegesHelper::confirmWithException(Privilege::ChangeUserAccessRank, PrivilegesHelper::getIdentitySubPrivilege($user));
$suppliedAccessRank = Model_User::validateAccessRank($suppliedAccessRank); $suppliedAccessRank = Model_User::validateAccessRank($suppliedAccessRank);
$user->access_rank = $suppliedAccessRank; $user->access_rank = $suppliedAccessRank;
LogHelper::logEvent('user-edit', '+{user} changed access rank for +{subject} to {rank}', ['subject' => $user->name, 'rank' => AccessRank::toString($suppliedAccessRank)]);
} }
if ($this->context->user->id == $user->id) if ($this->context->user->id == $user->id)
@ -355,9 +370,10 @@ class UserController
if ($confirmMail) if ($confirmMail)
self::sendEmailChangeConfirmation($user); self::sendEmailChangeConfirmation($user);
LogHelper::flush();
$message = 'Account settings updated!'; $message = 'Account settings updated!';
if ($confirmMail) if ($confirmMail)
$message .= ' You wlil be sent an e-mail address confirmation message soon.'; $message .= ' You will be sent an e-mail address confirmation message soon.';
StatusHelper::success($message); StatusHelper::success($message);
} }
} }
@ -519,6 +535,7 @@ class UserController
elseif ($this->config->registration->staffActivation) elseif ($this->config->registration->staffActivation)
$message .= ' Your registration must be now confirmed by staff.'; $message .= ' Your registration must be now confirmed by staff.';
LogHelper::logEvent('user-reg', '+{subject} just signed up', ['subject' => $dbUser->name]);
StatusHelper::success($message); StatusHelper::success($message);
if (!$this->config->registration->needEmailForRegistering and !$this->config->registration->staffActivation) if (!$this->config->registration->needEmailForRegistering and !$this->config->registration->staffActivation)
@ -548,6 +565,7 @@ class UserController
R::store($dbToken); R::store($dbToken);
R::store($dbUser); R::store($dbUser);
LogHelper::logEvent('user-activation', '+{subject} just activated account', ['subject' => $dbUser->name]);
$message = 'Activation completed successfully.'; $message = 'Activation completed successfully.';
if ($this->config->registration->staffActivation) if ($this->config->registration->staffActivation)
$message .= ' However, your account still must be confirmed by staff.'; $message .= ' However, your account still must be confirmed by staff.';
@ -584,6 +602,7 @@ class UserController
R::store($dbToken); R::store($dbToken);
R::store($dbUser); R::store($dbUser);
LogHelper::logEvent('user-pass-reset', '+{subject} just reset password', ['subject' => $dbUser->name]);
$message = 'Password reset successfuly. Your new password is **' . $randomPassword . '**.'; $message = 'Password reset successfuly. Your new password is **' . $randomPassword . '**.';
StatusHelper::success($message); StatusHelper::success($message);

69
src/Helpers/LogHelper.php Normal file
View file

@ -0,0 +1,69 @@
<?php
class LogHelper
{
static $path;
static $context;
static $config;
static $autoFlush;
static $content;
public static function init()
{
self::$config = \Chibi\Registry::getConfig();
self::$context = \Chibi\Registry::getContext();
self::$path = self::$config->main->logsPath . date('Y-m') . '.log';
self::$autoFlush = true;
self::$content = '';
}
public static function bufferChanges()
{
self::$autoFlush = false;
}
public static function flush()
{
$fh = fopen(self::getLogPath(), 'ab');
if (!$fh)
throw new SimpleException('Cannot write to log files');
if (flock($fh, LOCK_EX))
{
fwrite($fh, self::$content);
fflush($fh);
flock($fh, LOCK_UN);
fclose($fh);
}
self::$content = '';
self::$autoFlush = true;
}
public static function getLogPath()
{
return self::$path;
}
public static function log($text, array $tokens = [])
{
if (isset(self::$context->user))
$tokens['user'] = self::$context->user->name;
$text = TextHelper::replaceTokens($text, $tokens);
$timestamp = date('Y-m-d H:i:s');
$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
$line = sprintf('[%s] %s: %s' . PHP_EOL, $timestamp, $ip, $text);
self::$content .= $line;
if (self::$autoFlush)
self::flush();
}
public static function logEvent($event, $text, array $tokens = [])
{
return self::log(sprintf('[%s] %s', $event, $text), $tokens);
}
}
LogHelper::init();