mirror of
https://github.com/Neetpone/ponepaste.git
synced 2025-03-12 06:30:07 +01:00
chore: move paste actions to paste_action.php to require admin authentication
This commit is contained in:
parent
36abc1725e
commit
265b85d489
9 changed files with 106 additions and 66 deletions
|
@ -7,15 +7,19 @@ class AdminLog extends Model {
|
||||||
public const ACTION_LOGIN = 0;
|
public const ACTION_LOGIN = 0;
|
||||||
public const ACTION_FAIL_LOGIN = 1;
|
public const ACTION_FAIL_LOGIN = 1;
|
||||||
public const ACTION_EDIT_CONFIG = 2;
|
public const ACTION_EDIT_CONFIG = 2;
|
||||||
|
public const ACTION_HIDE_PASTE = 3;
|
||||||
|
public const ACTION_BLANK_PASTE = 4;
|
||||||
|
|
||||||
public const ACTION_NAMES = [
|
public const ACTION_NAMES = [
|
||||||
'Login',
|
'Login',
|
||||||
'Failed Login',
|
'Failed Login',
|
||||||
'Edit Config'
|
'Edit Config',
|
||||||
|
'Hide Paste',
|
||||||
|
'Blank Paste'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $table = 'admin_logs';
|
protected $table = 'admin_logs';
|
||||||
protected $fillable = ['user_id', 'action', 'ip', 'time'];
|
protected $fillable = ['user_id', 'action', 'ip', 'time', 'message'];
|
||||||
|
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
|
|
|
@ -33,12 +33,16 @@ function urlForPage($page = '') : string {
|
||||||
return (isset($_SERVER['HTTPS']) ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/\\') . '/' . $page;
|
return (isset($_SERVER['HTTPS']) ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/\\') . '/' . $page;
|
||||||
}
|
}
|
||||||
|
|
||||||
function urlForPaste(Paste $paste) : string {
|
function urlForPaste(int | Paste $paste) : string {
|
||||||
if (PP_MOD_REWRITE) {
|
if (!is_int($paste)) {
|
||||||
return "/{$paste->id}";
|
$paste = $paste->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "/paste.php?id={$paste->id}";
|
if (PP_MOD_REWRITE) {
|
||||||
|
return "/{$paste}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "/paste.php?id={$paste}";
|
||||||
}
|
}
|
||||||
|
|
||||||
function urlForReport(Paste $paste) : string {
|
function urlForReport(Paste $paste) : string {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use PonePaste\Models\AdminLog;
|
||||||
use PonePaste\Models\Paste;
|
use PonePaste\Models\Paste;
|
||||||
|
use PonePaste\Models\User;
|
||||||
|
|
||||||
function tagsToHtml(array | Collection $tags) : string {
|
function tagsToHtml(array | Collection $tags) : string {
|
||||||
$output = "";
|
$output = "";
|
||||||
|
@ -332,4 +334,15 @@ function pp_setup_pagination() : array {
|
||||||
|
|
||||||
function pp_output_paginator(int $per_page, int $current_page) : void {
|
function pp_output_paginator(int $per_page, int $current_page) : void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateAdminHistory(User $admin, int $action, string $message = null) : void {
|
||||||
|
$log = new AdminLog([
|
||||||
|
'user_id' => $admin->id,
|
||||||
|
'action' => $action,
|
||||||
|
'ip' => $_SERVER['REMOTE_ADDR'],
|
||||||
|
'message' => $message
|
||||||
|
]);
|
||||||
|
|
||||||
|
$log->save();
|
||||||
}
|
}
|
|
@ -5,25 +5,20 @@ if (!defined('IN_PONEPASTE')) {
|
||||||
|
|
||||||
require_once('../../includes/common.php');
|
require_once('../../includes/common.php');
|
||||||
|
|
||||||
use PonePaste\Models\AdminLog;
|
|
||||||
use PonePaste\Models\User;
|
use PonePaste\Models\User;
|
||||||
|
|
||||||
function updateAdminHistory(User $admin, int $action) : void {
|
|
||||||
$log = new AdminLog([
|
|
||||||
'user_id' => $admin->id,
|
|
||||||
'action' => $action,
|
|
||||||
'ip' => $_SERVER['REMOTE_ADDR']
|
|
||||||
]);
|
|
||||||
|
|
||||||
$log->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($current_user === null || $current_user->role < User::ROLE_MODERATOR) {
|
if ($current_user === null || $current_user->role < User::ROLE_MODERATOR) {
|
||||||
header('Location: ..');
|
header('Location: ..');
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($_SESSION['admin_login'])) {
|
if (!isset($_SESSION['admin_login'])) {
|
||||||
|
// this is a hack, paste_id is set when POSTing to admin/paste_action.php, which we can only arrive at from a paste page
|
||||||
|
if (isset($_POST['paste_id'])) {
|
||||||
|
flashError('You must authenticate to perform that action.');
|
||||||
|
$_SESSION['redirect_back'] = urlForPaste($_POST['paste_id']);
|
||||||
|
}
|
||||||
|
|
||||||
header('Location: .');
|
header('Location: .');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,6 +231,7 @@ $is_admin = $current_user->role >= User::ROLE_ADMIN;
|
||||||
<td>Username</td>
|
<td>Username</td>
|
||||||
<td>Date</td>
|
<td>Date</td>
|
||||||
<td>Action</td>
|
<td>Action</td>
|
||||||
|
<td>Information</td>
|
||||||
<td>IP Address</td>
|
<td>IP Address</td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -240,6 +241,7 @@ $is_admin = $current_user->role >= User::ROLE_ADMIN;
|
||||||
<td><?= pp_html_escape($entry->user->username); ?></td>
|
<td><?= pp_html_escape($entry->user->username); ?></td>
|
||||||
<td><?= pp_html_escape($entry->time); ?></td>
|
<td><?= pp_html_escape($entry->time); ?></td>
|
||||||
<td><?= pp_html_escape(AdminLog::ACTION_NAMES[$entry->action]); ?></td>
|
<td><?= pp_html_escape(AdminLog::ACTION_NAMES[$entry->action]); ?></td>
|
||||||
|
<td><?= !empty($entry->message) ? pp_html_escape($entry->message) : '[none]' ?></td>
|
||||||
<td><?= $is_admin ? pp_html_escape($entry->ip) : '[masked]' ?></td>
|
<td><?= $is_admin ? pp_html_escape($entry->ip) : '[masked]' ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
|
@ -5,16 +5,6 @@ require_once(__DIR__ . '/../../includes/common.php');
|
||||||
use PonePaste\Models\User;
|
use PonePaste\Models\User;
|
||||||
use PonePaste\Models\AdminLog;
|
use PonePaste\Models\AdminLog;
|
||||||
|
|
||||||
function updateAdminHistory(User $admin, int $action) : void {
|
|
||||||
$log = new AdminLog([
|
|
||||||
'user_id' => $admin->id,
|
|
||||||
'action' => $action,
|
|
||||||
'ip' => $_SERVER['REMOTE_ADDR']
|
|
||||||
]);
|
|
||||||
|
|
||||||
$log->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($current_user === null || $current_user->role < User::ROLE_MODERATOR) {
|
if ($current_user === null || $current_user->role < User::ROLE_MODERATOR) {
|
||||||
header('Location: ..');
|
header('Location: ..');
|
||||||
die();
|
die();
|
||||||
|
@ -25,11 +15,18 @@ if (isset($_SESSION['admin_login']) && $_SESSION['admin_login']) {
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$flashes = getFlashes();
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
if (pp_password_verify($_POST['password'], $current_user->admin_password_hash)) {
|
if (pp_password_verify($_POST['password'], $current_user->admin_password_hash)) {
|
||||||
updateAdminHistory($current_user, AdminLog::ACTION_LOGIN);
|
updateAdminHistory($current_user, AdminLog::ACTION_LOGIN);
|
||||||
$_SESSION['admin_login'] = true;
|
$_SESSION['admin_login'] = true;
|
||||||
header("Location: dashboard.php");
|
if (isset($_SESSION['redirect_back'])) {
|
||||||
|
flashSuccess('You have been logged in. Please try your action again.');
|
||||||
|
header('Location: ' . $_SESSION['redirect_back']);
|
||||||
|
} else {
|
||||||
|
header("Location: dashboard.php");
|
||||||
|
}
|
||||||
exit();
|
exit();
|
||||||
} else {
|
} else {
|
||||||
updateAdminHistory($current_user, AdminLog::ACTION_FAIL_LOGIN);
|
updateAdminHistory($current_user, AdminLog::ACTION_FAIL_LOGIN);
|
||||||
|
@ -60,6 +57,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||||
echo $msg;
|
echo $msg;
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
<?php outputFlashes($flashes); ?>
|
||||||
<form action="." method="post">
|
<form action="." method="post">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
<h1>PonePaste Admin Authentication</h1>
|
<h1>PonePaste Admin Authentication</h1>
|
||||||
|
|
60
public/admin/paste_action.php
Normal file
60
public/admin/paste_action.php
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
define('IN_PONEPASTE', 1);
|
||||||
|
require_once(__DIR__ . '/common.php');
|
||||||
|
|
||||||
|
use PonePaste\Models\AdminLog;
|
||||||
|
use PonePaste\Models\Paste;
|
||||||
|
|
||||||
|
if (empty($_POST['paste_id'])) {
|
||||||
|
echo "Error: No paste ID specified.";
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
$paste = Paste::find((int) $_POST['paste_id']);
|
||||||
|
|
||||||
|
if (!$paste) {
|
||||||
|
echo "Error: Paste not found.";
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_POST['hide'])) {
|
||||||
|
if (!can('hide', $paste)) {
|
||||||
|
flashError('You do not have permission to hide this paste.');
|
||||||
|
} else {
|
||||||
|
$is_hidden = !$paste->is_hidden;
|
||||||
|
|
||||||
|
if ($is_hidden) {
|
||||||
|
$paste->reports()->update(['open' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$paste->is_hidden = $is_hidden;
|
||||||
|
$paste->save();
|
||||||
|
$redis->del('ajax_pastes'); /* Expire from Redis so it doesn't show up anymore */
|
||||||
|
|
||||||
|
updateAdminHistory($current_user, AdminLog::ACTION_HIDE_PASTE, 'Paste ' . $paste->id . ' ' . ($is_hidden ? 'hidden' : 'unhidden') . '.');
|
||||||
|
flashSuccess('Paste ' . ($is_hidden ? 'hidden' : 'unhidden') . '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ' . urlForPaste($paste));
|
||||||
|
die();
|
||||||
|
} elseif (isset($_POST['blank'])) {
|
||||||
|
if (!can('blank', $paste)) {
|
||||||
|
flashError('You do not have permission to blank this paste.');
|
||||||
|
} else {
|
||||||
|
$paste->content = '';
|
||||||
|
$paste->title = 'Removed by moderator';
|
||||||
|
$paste->tags()->detach();
|
||||||
|
|
||||||
|
$paste->save();
|
||||||
|
$redis->del('ajax_pastes'); /* Expire from Redis so it doesn't show up anymore */
|
||||||
|
updateAdminHistory($current_user, AdminLog::ACTION_BLANK_PASTE, 'Paste ' . $paste->id . 'blanked.');
|
||||||
|
|
||||||
|
flashSuccess('Paste contents blanked.');
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Location: ' . urlForPaste($paste));
|
||||||
|
die();
|
||||||
|
} else {
|
||||||
|
flashError('Internal Error: No action specified.');
|
||||||
|
header('Location: ' . urlForPaste($paste));
|
||||||
|
}
|
|
@ -102,43 +102,6 @@ if (isset($_POST['delete'])) {
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_POST['hide'])) {
|
|
||||||
if (!can('hide', $paste)) {
|
|
||||||
$error = 'You do not have permission to hide this paste.';
|
|
||||||
goto Not_Valid_Paste;
|
|
||||||
}
|
|
||||||
|
|
||||||
$is_hidden = !$paste->is_hidden;
|
|
||||||
|
|
||||||
if ($is_hidden) {
|
|
||||||
$paste->reports()->update(['open' => false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$paste->is_hidden = $is_hidden;
|
|
||||||
$paste->save();
|
|
||||||
$redis->del('ajax_pastes'); /* Expire from Redis so it doesn't show up anymore */
|
|
||||||
flashSuccess('Paste ' . ($is_hidden ? 'hidden' : 'unhidden') . '.');
|
|
||||||
header('Location: ' . urlForPaste($paste));
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_POST['blank'])) {
|
|
||||||
if (!can('blank', $paste)) {
|
|
||||||
$error = 'You do not have permission to blank this paste.';
|
|
||||||
goto Not_Valid_Paste;
|
|
||||||
}
|
|
||||||
|
|
||||||
$paste->content = '';
|
|
||||||
$paste->title = 'Removed by moderator';
|
|
||||||
$paste->tags()->detach();
|
|
||||||
|
|
||||||
$paste->save();
|
|
||||||
$redis->del('ajax_pastes'); /* Expire from Redis so it doesn't show up anymore */
|
|
||||||
flashSuccess('Paste contents blanked.');
|
|
||||||
header('Location: ' . urlForPaste($paste));
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify paste password */
|
/* Verify paste password */
|
||||||
$password_required = $p_password !== null && $p_password !== 'NONE';
|
$password_required = $p_password !== null && $p_password !== 'NONE';
|
||||||
$password_valid = true;
|
$password_valid = true;
|
||||||
|
|
|
@ -149,7 +149,8 @@
|
||||||
<?php if (can('hide', $paste)): ?>
|
<?php if (can('hide', $paste)): ?>
|
||||||
<div class="mod-tools">
|
<div class="mod-tools">
|
||||||
<p>Moderation Tools</p>
|
<p>Moderation Tools</p>
|
||||||
<form method="post">
|
<form action="/admin/paste_action.php" method="post">
|
||||||
|
<input type="hidden" name="paste_id" value="<?= $paste->id ?>" />
|
||||||
<?php if (isset($csrf_token)): ?>
|
<?php if (isset($csrf_token)): ?>
|
||||||
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>"/>
|
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>"/>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
Loading…
Add table
Reference in a new issue