summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-06-08 01:37:19 +0400
committerilotterytea <iltsu@alright.party>2025-06-08 01:37:19 +0400
commit9a58eaae53bdd2a4fcdd66b1eb852c7db7970de9 (patch)
tree8e83f5144674501a7e4c1739f4abc583ef78e065
parent371d863870520da9a4f3383d7c52e1720c074d03 (diff)
feat: moderation system
-rw-r--r--lib/partials.php10
-rw-r--r--lib/utils.php1
-rw-r--r--public/delete.php18
-rw-r--r--public/index.php13
-rw-r--r--public/mod.php159
-rw-r--r--public/static/style.css4
6 files changed, 195 insertions, 10 deletions
diff --git a/lib/partials.php b/lib/partials.php
index c35fe43..afd36d6 100644
--- a/lib/partials.php
+++ b/lib/partials.php
@@ -23,6 +23,11 @@ function html_big_navbar()
<a href="/uploaders.php">
<button>Uploaders</button>
</a>
+ <?php if (isset($_SESSION['is_moderator'])): ?>
+ <a href="/mod.php">
+ <button>Moderation</button>
+ </a>
+ <?php endif; ?>
</div>
</section>
<?php ;
@@ -49,6 +54,11 @@ function html_mini_navbar()
<a href="/uploaders.php">
<button>Uploaders</button>
</a>
+ <?php if (isset($_SESSION['is_moderator'])): ?>
+ <a href="/mod.php">
+ <button>Moderation</button>
+ </a>
+ <?php endif; ?>
</div>
</section>
<?php ;
diff --git a/lib/utils.php b/lib/utils.php
index 31d8778..eb868a2 100644
--- a/lib/utils.php
+++ b/lib/utils.php
@@ -1,5 +1,6 @@
<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/../config.php';
+define('IS_JSON_REQUEST', $_SERVER['HTTP_ACCEPT'] == 'application/json');
function json_response(mixed $data, string|null $message, int $code = 200)
{
diff --git a/public/delete.php b/public/delete.php
index b716796..453e0b3 100644
--- a/public/delete.php
+++ b/public/delete.php
@@ -1,17 +1,20 @@
<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/../config.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/utils.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/file.php';
+
+session_start();
if (!FILE_DELETION) {
json_response(null, 'File deletion is not allowed!', 403);
exit();
}
-$file_id = $_GET['f'] ?: null;
-$password = $_GET['key'] ?: null;
+$file_id = $_GET['f'] ?? null;
+$password = $_GET['key'] ?? null;
-if (!isset($file_id, $password)) {
- json_response(null, "Fields 'f' and 'key' must be set!", 400);
+if (!isset($file_id)) {
+ json_response(null, "File ID must be set!", 400);
exit();
}
@@ -41,7 +44,12 @@ if (!array_key_exists('password', $metadata)) {
exit();
}
-if (!password_verify($password, $metadata['password'])) {
+if (!isset($_SESSION['is_moderator']) && !isset($password)) {
+ json_response(null, "Field 'key' must be set!", 400);
+ exit();
+}
+
+if (!isset($_SESSION['is_moderator']) && !password_verify($password, $metadata['password'])) {
json_response(null, "Bad password", 401);
exit();
}
diff --git a/public/index.php b/public/index.php
index 580a186..7df2ce1 100644
--- a/public/index.php
+++ b/public/index.php
@@ -3,6 +3,8 @@ include_once $_SERVER['DOCUMENT_ROOT'] . '/../config.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/partials.php';
include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/utils.php';
+session_start();
+
if (FILE_CATALOG_RANDOM && isset($_GET['random'])) {
$files = glob(FILE_UPLOAD_DIRECTORY . "/*.*");
$file = $files[random_int(0, count($files) - 1)];
@@ -46,8 +48,6 @@ if (FILE_CATALOG_FANCY_VIEW && $file_id) {
$file = json_decode(file_get_contents($meta_path), true);
if (isset($file['views'])) {
- session_start();
-
$viewed_file_ids = $_SESSION['viewed_file_ids'] ?? [];
if (!in_array($file['id'], $viewed_file_ids)) {
@@ -156,6 +156,11 @@ $privacy_exists = is_file($_SERVER['DOCUMENT_ROOT'] . '/static/PRIVACY.txt');
<?php endif; ?>
</div>
<div class="grow row gap-8 justify-end align-center" id="file-tab-buttons">
+ <?php if (isset($_SESSION['is_moderator'])): ?>
+ <a href="/delete.php?f=<?= $file['id'] ?>.<?= $file['extension'] ?>">
+ <button>Delete</button>
+ </a>
+ <?php endif; ?>
<?php if (FILE_REPORT): ?>
<a href="/report.php?f=<?= $file['id'] ?>.<?= $file['extension'] ?>">
<button>Report</button>
@@ -303,7 +308,7 @@ $privacy_exists = is_file($_SERVER['DOCUMENT_ROOT'] . '/static/PRIVACY.txt');
</main>
</body>
-<?php if ($file): ?>
+<?php if ($file && !isset($_SESSION['is_moderator'])): ?>
<script>
// adding deletion button
const files = JSON.parse(localStorage.getItem('uploaded_files') ?? '[]');
@@ -313,7 +318,7 @@ $privacy_exists = is_file($_SERVER['DOCUMENT_ROOT'] . '/static/PRIVACY.txt');
buttons.innerHTML = `<a href='${file.urls.deletion_url}'><button>Delete</button></a>` + buttons.innerHTML;
}
</script>
-<?php else: ?>
+<?php elseif (!$file): ?>
<script>
const formDetails = document.getElementById('form-upload-options');
diff --git a/public/mod.php b/public/mod.php
new file mode 100644
index 0000000..d0ec00c
--- /dev/null
+++ b/public/mod.php
@@ -0,0 +1,159 @@
+<?php
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/partials.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/utils.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../config.php';
+
+session_start();
+
+if ($_SERVER['REQUEST_METHOD'] == 'POST') {
+ if (!isset($_POST['password'])) {
+ json_response(null, 'No password set', 400);
+ exit();
+ }
+
+ if (!is_file(MOD_FILE) && !file_put_contents(MOD_FILE, '')) {
+ json_response(null, 'Failed to create a file for mod passwords', 500);
+ exit();
+ }
+
+ $password_file = explode('\n', file_get_contents(MOD_FILE));
+
+ $is_authorized = false;
+
+ foreach ($password_file as $p) {
+ $is_authorized = password_verify($_POST['password'], $p);
+ if ($is_authorized) {
+ break;
+ }
+ }
+
+ if (!$is_authorized) {
+ if (IS_JSON_REQUEST) {
+ json_response(null, 'Unauthorized!', 401);
+ } else {
+ header('Location: /mod.php');
+ }
+ exit();
+ }
+
+ $_SESSION['is_moderator'] = $is_authorized;
+
+ if (IS_JSON_REQUEST) {
+ json_response(null, 'Authorized!', 200);
+ } else {
+ header('Location: /mod.php');
+ }
+ exit();
+}
+
+$files = [];
+
+$page = intval($_GET['fp'] ?? '1');
+$max_pages = 0;
+
+if (isset($_SESSION['is_moderator'])) {
+ $quantity = 10;
+
+ $filelist = glob(FILE_UPLOAD_DIRECTORY . '/*.*');
+ usort($filelist, function ($a, $b) {
+ return filemtime($b) - filemtime($a);
+ });
+
+ $selected_files = array_slice($filelist, ($page - 1) * $quantity, $quantity);
+
+ $max_pages = ceil(count($filelist) / $quantity);
+
+ foreach ($selected_files as $f) {
+ $name = basename($f);
+ $id = explode('.', $name);
+ array_push($files, [
+ 'name' => $name,
+ 'id' => $id[0],
+ 'extension' => $id[1]
+ ]);
+ }
+}
+?>
+<html>
+
+<head>
+ <title>Moderation - <?= INSTANCE_NAME ?></title>
+ <link rel="stylesheet" href="/static/style.css">
+ <link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon">
+</head>
+
+<body>
+ <main>
+ <?php html_mini_navbar() ?>
+ <?php if (isset($_SESSION['is_moderator'])): ?>
+ <?php if (!empty($files)): ?>
+ <section class="column gap-8">
+ <h2>Files (Page <?= $page ?> / <?= $max_pages ?>)</h2>
+ <hr>
+ <table class="left">
+ <tr>
+ <?php if (FILE_THUMBNAILS): ?>
+ <th style="width: 10%;"></th>
+ <?php endif; ?>
+ <th>File</th>
+ <th>Age</th>
+ <th>Actions</th>
+ </tr>
+ <?php foreach ($files as $f): ?>
+ <tr>
+ <td>
+ <?php if (FILE_THUMBNAILS): ?>
+ <img src="<?= sprintf('%s/%s.webp', FILE_THUMBNAIL_DIRECTORY_PREFIX, $f['id']) ?>" alt=""
+ height="24">
+ <?php endif; ?>
+ </td>
+ <td>
+ <a href="/<?= $f['name'] ?>" target="_blank"><?= $f['name'] ?></a>
+ </td>
+ <td>
+ <?= format_timestamp(time() - filemtime(sprintf('%s/%s', FILE_UPLOAD_DIRECTORY, $f['name']))) ?>
+ </td>
+ <td>
+ <a href="/delete.php?f=<?= $f['name'] ?>">
+ <button>
+ <img src="/static/img/icons/delete.png" alt="Delete">
+ </button>
+ </a>
+ </td>
+ </tr>
+ <?php endforeach; ?>
+ </table>
+
+ <div class="row gap-8">
+ <?php if ($page - 1 >= 1): ?>
+ <a href="/mod.php?fp=<?= $page - 1 ?>">
+ <button>Previous</button>
+ </a>
+ <?php endif; ?>
+ <?php if ($page + 1 <= $max_pages): ?>
+ <a href="/mod.php?fp=<?= $page + 1 ?>">
+ <button>Next</button>
+ </a>
+ <?php endif; ?>
+ </div>
+ </section>
+ <?php else: ?>
+ <p><i>No files to moderate...</i></p>
+ <?php endif; ?>
+ <?php else: ?>
+ <h1>Log in to the moderation system</h1>
+ <hr>
+ <form action="/mod.php" method="post">
+ <table>
+ <tr>
+ <th>Password:</th>
+ <td><input type="password" name="password" required></td>
+ </tr>
+ </table>
+ <button type="submit">Log in</button>
+ </form>
+ <?php endif; ?>
+ </main>
+</body>
+
+</html> \ No newline at end of file
diff --git a/public/static/style.css b/public/static/style.css
index 1ac9cef..f721a03 100644
--- a/public/static/style.css
+++ b/public/static/style.css
@@ -117,7 +117,9 @@ table.vertical th {
vertical-align: top;
}
-table.vertical.left th {
+table.vertical.left th,
+table.left th,
+table.left td {
text-align: left;
}