Add audit log backend stuff.
This commit is contained in:
parent
41109793a7
commit
c32525d489
8 changed files with 178 additions and 11 deletions
66
database/2018_07_17_170102_audit_log_struct.php
Normal file
66
database/2018_07_17_170102_audit_log_struct.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
namespace Misuzu\DatabaseMigrations\AuditLogStruct;
|
||||
|
||||
use PDO;
|
||||
|
||||
function migrate_up(PDO $conn): void
|
||||
{
|
||||
$conn->exec('
|
||||
ALTER TABLE `msz_permissions`
|
||||
RENAME INDEX `user_id` TO `permissions_user_id_unique`,
|
||||
RENAME INDEX `role_id` TO `permissions_role_id_unique`,
|
||||
DROP FOREIGN KEY `role_id_foreign`,
|
||||
DROP FOREIGN KEY `user_id_foreign`,
|
||||
ADD CONSTRAINT `permissions_user_id_foreign`
|
||||
FOREIGN KEY (`user_id`)
|
||||
REFERENCES `msz_users` (`user_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
ADD CONSTRAINT `permissions_role_id_foreign`
|
||||
FOREIGN KEY (`role_id`)
|
||||
REFERENCES `msz_roles` (`role_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
');
|
||||
|
||||
$conn->exec("
|
||||
CREATE TABLE `msz_audit_log` (
|
||||
`log_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` INT(10) UNSIGNED NULL DEFAULT NULL,
|
||||
`log_action` VARCHAR(50) NOT NULL,
|
||||
`log_params` TEXT NOT NULL,
|
||||
`log_created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`log_ip` VARBINARY(16) NULL DEFAULT NULL,
|
||||
PRIMARY KEY (`log_id`),
|
||||
INDEX `audit_log_user_id_foreign` (`user_id`),
|
||||
CONSTRAINT `audit_log_user_id_foreign`
|
||||
FOREIGN KEY (`user_id`)
|
||||
REFERENCES `msz_users` (`user_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
)
|
||||
");
|
||||
}
|
||||
|
||||
function migrate_down(PDO $conn): void
|
||||
{
|
||||
$conn->exec('DROP TABLE `msz_audit_log`');
|
||||
|
||||
$conn->exec('
|
||||
ALTER TABLE `msz_permissions`
|
||||
RENAME INDEX `permissions_user_id_unique` TO `user_id`,
|
||||
RENAME INDEX `permissions_role_id_unique` TO `role_id`,
|
||||
DROP FOREIGN KEY `permissions_user_id_foreign`,
|
||||
DROP FOREIGN KEY `permissions_role_id_foreign`,
|
||||
ADD CONSTRAINT `role_id_foreign`
|
||||
FOREIGN KEY (`user_id`)
|
||||
REFERENCES `msz_users` (`user_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE,
|
||||
ADD CONSTRAINT `user_id_foreign`
|
||||
FOREIGN KEY (`role_id`)
|
||||
REFERENCES `msz_roles` (`role_id`)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
');
|
||||
}
|
|
@ -4,6 +4,7 @@ namespace Misuzu;
|
|||
date_default_timezone_set('UTC');
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
require_once __DIR__ . '/src/audit_log.php';
|
||||
require_once __DIR__ . '/src/changelog.php';
|
||||
require_once __DIR__ . '/src/colour.php';
|
||||
require_once __DIR__ . '/src/comments.php';
|
||||
|
|
|
@ -113,8 +113,12 @@ switch ($_GET['v'] ?? null) {
|
|||
$postChange->execute();
|
||||
|
||||
if ($changeId < 1) {
|
||||
header('Location: ?v=change&c=' . Database::lastInsertId());
|
||||
$changeId = Database::lastInsertId();
|
||||
audit_log('CHANGELOG_ENTRY_CREATE', $app->getUserId(), [$changeId]);
|
||||
header('Location: ?v=change&c=' . $changeId);
|
||||
return;
|
||||
} else {
|
||||
audit_log('CHANGELOG_ENTRY_EDIT', $app->getUserId(), [$changeId]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +126,13 @@ switch ($_GET['v'] ?? null) {
|
|||
$addTag = Database::prepare('REPLACE INTO `msz_changelog_change_tags` VALUES (:change_id, :tag_id)');
|
||||
$addTag->bindValue('change_id', $changeId);
|
||||
$addTag->bindValue('tag_id', $_POST['add_tag']);
|
||||
$addTag->execute();
|
||||
|
||||
if ($addTag->execute()) {
|
||||
audit_log('CHANGELOG_TAG_ADD', $app->getUserId(), [
|
||||
$changeId,
|
||||
$_POST['add_tag']
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($_POST['remove_tag']) && is_numeric($_POST['remove_tag'])) {
|
||||
|
@ -133,7 +143,13 @@ switch ($_GET['v'] ?? null) {
|
|||
');
|
||||
$removeTag->bindValue('change_id', $changeId);
|
||||
$removeTag->bindValue('tag_id', $_POST['remove_tag']);
|
||||
$removeTag->execute();
|
||||
|
||||
if ($removeTag->execute()) {
|
||||
audit_log('CHANGELOG_TAG_REMOVE', $app->getUserId(), [
|
||||
$changeId,
|
||||
$_POST['remove_tag']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,8 +283,12 @@ switch ($_GET['v'] ?? null) {
|
|||
$updateTag->execute();
|
||||
|
||||
if ($tagId < 1) {
|
||||
header('Location: ?v=tag&t=' . Database::lastInsertId());
|
||||
$tagId = Database::lastInsertId();
|
||||
audit_log('CHANGELOG_TAG_EDIT', $app->getUserId(), [$tagId]);
|
||||
header('Location: ?v=tag&t=' . $tagId);
|
||||
return;
|
||||
} else {
|
||||
audit_log('CHANGELOG_TAG_CREATE', $app->getUserId(), [$tagId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -374,8 +394,12 @@ switch ($_GET['v'] ?? null) {
|
|||
$updateAction->execute();
|
||||
|
||||
if ($actionId < 1) {
|
||||
header('Location: ?v=action&a=' . Database::lastInsertId());
|
||||
$actionId = Database::lastInsertId();
|
||||
audit_log('CHANGELOG_ACTION_CREATE', $app->getUserId(), [$actionId]);
|
||||
header('Location: ?v=action&a=' . $actionId);
|
||||
return;
|
||||
} else {
|
||||
audit_log('CHANGELOG_ACTION_EDIT', $app->getUserId(), [$actionId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
<?php
|
||||
require_once __DIR__ . '/../../misuzu.php';
|
||||
|
||||
$templating = $app->getTemplating();
|
||||
$generalPerms = perms_get_user(MSZ_PERMS_GENERAL, $app->getUserId());
|
||||
$tpl = $app->getTemplating();
|
||||
|
||||
switch ($_GET['v'] ?? null) {
|
||||
default:
|
||||
case 'overview':
|
||||
echo $templating->render('@manage.general.overview');
|
||||
echo $tpl->render('@manage.general.overview');
|
||||
break;
|
||||
|
||||
case 'logs':
|
||||
echo 'soon';
|
||||
if (!perms_check($generalPerms, MSZ_GENERAL_PERM_VIEW_LOGS)) {
|
||||
echo render_error(403);
|
||||
break;
|
||||
}
|
||||
|
||||
var_dump(audit_log_list(0, 20));
|
||||
break;
|
||||
|
||||
case 'emoticons':
|
||||
|
|
|
@ -196,6 +196,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
}
|
||||
|
||||
$updateAccountFields['email'] = strtolower($_POST['email']['new']);
|
||||
|
||||
audit_log('PERSONAL_EMAIL_CHANGE', $app->getUserId(), [
|
||||
$updateAccountFields['email'],
|
||||
]);
|
||||
}
|
||||
|
||||
if (!empty($_POST['password']['new'])) {
|
||||
|
@ -213,6 +217,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
}
|
||||
|
||||
$updateAccountFields['password'] = user_password_hash($_POST['password']['new']);
|
||||
|
||||
audit_log('PERSONAL_PASSWORD_CHANGE', $app->getUserId());
|
||||
}
|
||||
|
||||
if (count($updateAccountFields) > 0) {
|
||||
|
@ -311,6 +317,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||
}
|
||||
|
||||
user_session_delete($session['session_id']);
|
||||
audit_log('PERSONAL_SESSION_DESTROY', $app->getUserId(), [
|
||||
$session['session_id'],
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
61
src/audit_log.php
Normal file
61
src/audit_log.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
use Misuzu\Database;
|
||||
use Misuzu\Net\IPAddress;
|
||||
|
||||
function audit_log(
|
||||
string $action,
|
||||
int $userId = 0,
|
||||
array $params = [],
|
||||
IPAddress $ipAddress = null
|
||||
): void {
|
||||
$ipAddress = $ipAddress ?? IPAddress::remote();
|
||||
|
||||
for ($i = 0; $i < count($params); $i++) {
|
||||
if (preg_match('#(-?[0-9]+)#', $params[$i])) {
|
||||
$params[$i] = (int)$params[$i];
|
||||
}
|
||||
}
|
||||
|
||||
$addLog = Database::prepare('
|
||||
INSERT INTO `msz_audit_log`
|
||||
(`log_action`, `user_id`, `log_params`, `log_ip`)
|
||||
VALUES
|
||||
(:action, :user, :params, :log_ip)
|
||||
');
|
||||
$addLog->bindValue('action', $action);
|
||||
$addLog->bindValue('user', $userId < 1 ? null : $userId);
|
||||
$addLog->bindValue('params', json_encode($params));
|
||||
$addLog->bindValue('log_ip', $ipAddress->getRaw());
|
||||
$addLog->execute();
|
||||
}
|
||||
|
||||
function audit_log_list(int $offset, int $take, int $userId = 0): array
|
||||
{
|
||||
$offset = max(0, $offset);
|
||||
$take = max(1, $take);
|
||||
|
||||
$getLogs = Database::prepare(sprintf('
|
||||
SELECT
|
||||
l.`log_id`, l.`log_action`, l.`log_params`, l.`log_created`,
|
||||
u.`user_id`, u.`username`,
|
||||
INET6_NTOA(l.`log_ip`) as `log_ip`,
|
||||
COALESCE(r.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `user_colour`
|
||||
FROM `msz_audit_log` as l
|
||||
LEFT JOIN `msz_users` as u
|
||||
ON u.`user_id` = l.`user_id`
|
||||
LEFT JOIN `msz_roles` as r
|
||||
ON r.`role_id` = u.`display_role`
|
||||
WHERE %s
|
||||
ORDER BY l.`log_id` DESC
|
||||
LIMIT :offset, :take
|
||||
', $userId < 1 ? '1' : 'l.`user_id` = :user_id'));
|
||||
|
||||
if ($userId >= 1) {
|
||||
$getLogs->bindValue('user_id');
|
||||
}
|
||||
|
||||
$getLogs->bindValue('offset', $offset);
|
||||
$getLogs->bindValue('take', $take);
|
||||
|
||||
return $getLogs->execute() ? $getLogs->fetchAll(PDO::FETCH_ASSOC) : [];
|
||||
}
|
|
@ -28,11 +28,11 @@ function manage_get_menu(int $userId): array
|
|||
$menu['General'][] = '_';
|
||||
|
||||
if (perms_check($perms['general'], MSZ_GENERAL_PERM_MANAGE_EMOTICONS)) {
|
||||
$menu['General']['Emoticons'] = '/manage/users.php?v=emoticons';
|
||||
$menu['General']['Emoticons'] = '/manage/index.php?v=emoticons';
|
||||
}
|
||||
|
||||
if (perms_check($perms['general'], MSZ_GENERAL_PERM_MANAGE_SETTINGS)) {
|
||||
$menu['General']['Settings'] = '/manage/users.php?v=settings';
|
||||
$menu['General']['Settings'] = '/manage/index.php?v=settings';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Flashii Broom Closet</title>
|
||||
<title>{{ globals.site_name|default('The') }} Broom Closet</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
|
||||
<link href="/css/manage.css" rel="stylesheet">
|
||||
<link href="/css/libraries.css" rel="stylesheet">
|
||||
|
|
Loading…
Add table
Reference in a new issue