mirror of
https://github.com/Neetpone/ponepaste.git
synced 2025-03-11 14:10:06 +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_FAIL_LOGIN = 1;
|
||||
public const ACTION_EDIT_CONFIG = 2;
|
||||
public const ACTION_HIDE_PASTE = 3;
|
||||
public const ACTION_BLANK_PASTE = 4;
|
||||
|
||||
public const ACTION_NAMES = [
|
||||
'Login',
|
||||
'Failed Login',
|
||||
'Edit Config'
|
||||
'Edit Config',
|
||||
'Hide Paste',
|
||||
'Blank Paste'
|
||||
];
|
||||
|
||||
protected $table = 'admin_logs';
|
||||
protected $fillable = ['user_id', 'action', 'ip', 'time'];
|
||||
protected $fillable = ['user_id', 'action', 'ip', 'time', 'message'];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function urlForPaste(Paste $paste) : string {
|
||||
if (PP_MOD_REWRITE) {
|
||||
return "/{$paste->id}";
|
||||
function urlForPaste(int | Paste $paste) : string {
|
||||
if (!is_int($paste)) {
|
||||
$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 {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use PonePaste\Models\AdminLog;
|
||||
use PonePaste\Models\Paste;
|
||||
use PonePaste\Models\User;
|
||||
|
||||
function tagsToHtml(array | Collection $tags) : string {
|
||||
$output = "";
|
||||
|
@ -332,4 +334,15 @@ function pp_setup_pagination() : array {
|
|||
|
||||
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');
|
||||
|
||||
use PonePaste\Models\AdminLog;
|
||||
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) {
|
||||
header('Location: ..');
|
||||
die();
|
||||
}
|
||||
|
||||
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: .');
|
||||
exit();
|
||||
}
|
||||
|
|
|
@ -231,6 +231,7 @@ $is_admin = $current_user->role >= User::ROLE_ADMIN;
|
|||
<td>Username</td>
|
||||
<td>Date</td>
|
||||
<td>Action</td>
|
||||
<td>Information</td>
|
||||
<td>IP Address</td>
|
||||
</tr>
|
||||
</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->time); ?></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>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
|
|
@ -5,16 +5,6 @@ require_once(__DIR__ . '/../../includes/common.php');
|
|||
use PonePaste\Models\User;
|
||||
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) {
|
||||
header('Location: ..');
|
||||
die();
|
||||
|
@ -25,11 +15,18 @@ if (isset($_SESSION['admin_login']) && $_SESSION['admin_login']) {
|
|||
exit();
|
||||
}
|
||||
|
||||
$flashes = getFlashes();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
if (pp_password_verify($_POST['password'], $current_user->admin_password_hash)) {
|
||||
updateAdminHistory($current_user, AdminLog::ACTION_LOGIN);
|
||||
$_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();
|
||||
} else {
|
||||
updateAdminHistory($current_user, AdminLog::ACTION_FAIL_LOGIN);
|
||||
|
@ -60,6 +57,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
|||
echo $msg;
|
||||
}
|
||||
?>
|
||||
<?php outputFlashes($flashes); ?>
|
||||
<form action="." method="post">
|
||||
<div class="top">
|
||||
<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();
|
||||
}
|
||||
|
||||
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 */
|
||||
$password_required = $p_password !== null && $p_password !== 'NONE';
|
||||
$password_valid = true;
|
||||
|
|
|
@ -149,7 +149,8 @@
|
|||
<?php if (can('hide', $paste)): ?>
|
||||
<div class="mod-tools">
|
||||
<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)): ?>
|
||||
<input type="hidden" name="csrf_token" value="<?= $csrf_token ?>"/>
|
||||
<?php endif; ?>
|
||||
|
|
Loading…
Add table
Reference in a new issue