Update for logs

This commit is contained in:
Visman 2021-02-22 21:32:38 +07:00
parent 620dba2974
commit 7196007c21
8 changed files with 257 additions and 46 deletions

View file

@ -700,6 +700,12 @@ class Routing
'AdminLogs:info',
'AdminLogs'
);
$r->add(
$r::DUO,
'/admin/logs/{action:\w+}/{hash}/{token}',
'AdminLogs:action',
'AdminLogsAction'
);
}
$uri = $_SERVER['REQUEST_URI'];

View file

@ -112,6 +112,26 @@ class LogViewer
return $this->fileList;
}
/**
* Возвращает путь к логу по его хэшу
*/
public function getPath(string $hash): ?string
{
return $this->hashList[$hash] ?? null;
}
/**
* Возвращает имя лога
*/
public function getName(string $path): string
{
if (! \preg_match('%[\\\/]([^\\\/]++)$%D', $path, $matches)) {
throw new RuntimeException("Can't extract filename from path '{$path}'");
}
return $matches[1];
}
/**
* Возвращает общую информацию по логам
* и генерирует кеш
@ -153,12 +173,8 @@ class LogViewer
protected function generateInfo(string $file): array
{
if (! \preg_match('%[\\\/]([^\\\/]++)$%D', $file, $matches)) {
throw new RuntimeException("Can't extract filename from path '{$file}'");
}
$result = [
'log_name' => $matches[1],
'log_name' => $this->getName($file),
'emergency' => 0,
'alert' => 0,
'critical' => 0,

View file

@ -12,6 +12,8 @@ namespace ForkBB\Models\Pages\Admin;
use ForkBB\Models\Page;
use ForkBB\Models\Pages\Admin;
use Throwable;
use function \ForkBB\__;
class Logs extends Admin
{
@ -22,11 +24,143 @@ class Logs extends Admin
{
$this->c->Lang->load('admin_logs');
$logsFiles = $this->c->LogViewer->files();
$info = $this->c->LogViewer->info($logsFiles);
foreach ($info as $hash => &$cur) {
$cur['linkView'] = $this->c->Router->link(
'AdminLogsAction',
[
'action' => 'view',
'hash' => $hash,
]
);
$cur['linkDownload'] = $this->c->Router->link(
'AdminLogsAction',
[
'action' => 'download',
'hash' => $hash,
]
);
$cur['linkDelete'] = $this->c->Router->link(
'AdminLogsAction',
[
'action' => 'delete',
'hash' => $hash,
]
);
}
unset($cur);
$this->nameTpl = 'admin/logs';
$this->aIndex = 'logs';
$logsFiles = $this->c->LogViewer->files();
$this->logsInfo = $this->c->LogViewer->info($logsFiles);
$this->logsInfo = $info;
return $this;
}
public function action(array $args, string $method): Page
{
if (! $this->c->Csrf->verify($args['token'], 'AdminLogsAction', $args)) {
return $this->c->Message->message($this->c->Csrf->getError());
}
$path = $this->c->LogViewer->getPath($args['hash']);
if (
null === $path
|| ! \is_file($path)
) {
return $this->c->Message->message('Not Found', true, 404);
}
$this->c->Lang->load('admin_logs');
$this->aIndex = 'logs';
switch ($args['action']) {
case 'view':
return $this->view($path, $args, $method);
case 'delete':
return $this->delete($path, $args, $method);
case 'download':
return $this->download($path, $args, $method);
default:
return $this->c->Message->message('Not Found', true, 404);
}
}
protected function download(string $path, array $args, string $method): Page
{
$this->c->DEBUG = 0;
$this->nameTpl = 'layouts/plain_raw';
$this->plainRaw = \trim(\file_get_contents($path)); // ???? возможности XSendFile/Nginx использовать?
$this->header('Content-type', 'application/octet-stream')
->header('Content-Transfer-Encoding', 'binary')
->header('Content-Disposition', 'attachment; filename=' . $this->c->LogViewer->getName($path));
return $this;
}
protected function delete(string $path, array $args, string $method): Page
{
if ('POST' === $method) {
$v = $this->c->Validator->reset()
->addRules([
'delete' => 'string',
])->addAliases([
])->addArguments([
]);
try {
if (
$v->validation($_POST)
&& \unlink($path)
) {
return $this->c->Redirect->page('AdminLogs')->message('Log deleted redirect');
}
} catch (Throwable $e) { // ???? будет работать или нет?
$this->c->Log->error('Delete log: failed', [
'exception' => $e,
'headers' => false,
]);
}
return $this->c->Redirect->page('AdminLogs')->message('Failed to delete log redirect');
}
$this->nameTpl = 'admin/form';
$this->titleForm = 'Delete log head';
$this->classForm = 'logdel';
$this->form = $this->formDelete($path, $args);
$this->aCrumbs[] = [
$this->c->Router->link('AdminLogsAction', $args),
__('Delete log head'),
];
return $this;
}
protected function formDelete(string $path, array $args): array
{
$form = [
'action' => $this->c->Router->link('AdminLogsAction', $args),
'hidden' => [], // токен в url передается для всех действий с логами
'sets' => [],
'btns' => [
'delete' => [
'type' => 'submit',
'value' => __('Delete log %s', $this->c->LogViewer->getName($path)),
],
'cancel' => [
'type' => 'btn',
'value' => __('Cancel'),
'link' => $this->c->Router->link('AdminLogs'),
],
],
];
return $form;
}
}

View file

@ -39,11 +39,23 @@ msgstr "Info"
msgid "Level debug"
msgstr "Debug"
msgid "View log"
msgstr "View"
msgid "View log %s"
msgstr "View %s"
msgid "Download log"
msgstr "Download"
msgid "Delete log"
msgstr "Delete"
msgid "Delete log head"
msgstr "Delete log"
msgid "Delete log %s"
msgstr "Delete log %s"
msgid "Log deleted redirect"
msgstr "Log deleted."
msgid "Failed to delete log redirect"
msgstr "Failed to delete log."

View file

@ -39,11 +39,23 @@ msgstr "Info"
msgid "Level debug"
msgstr "Debug"
msgid "View log"
msgstr "Открыть"
msgid "View log %s"
msgstr "Открыть %s"
msgid "Download log"
msgstr "Скачать"
msgid "Delete log"
msgstr "Удалить"
msgid "Delete log head"
msgstr "Удалить лог"
msgid "Delete log %s"
msgstr "Удалить лог %s"
msgid "Log deleted redirect"
msgstr "Лог удален."
msgid "Failed to delete log redirect"
msgstr "Лог не удалось удалить."

View file

@ -4,23 +4,35 @@
<h2>{!! __('Logs') !!}</h2>
<div>
<fieldset>
<p></p>
<p class="f-lgp f-lgli">
<span class="f-lgname"><span>{!! __('Log name') !!}</span></span>
<span class="f-llv f-llvem"><span>{!! __('Level emergency') !!}</span></span>
<span class="f-llv f-llval"><span>{!! __('Level alert') !!}</span></span>
<span class="f-llv f-llvcr"><span>{!! __('Level critical') !!}</span></span>
<span class="f-llv f-llver"><span>{!! __('Level error') !!}</span></span>
<span class="f-llv f-llvwa"><span>{!! __('Level warning') !!}</span></span>
<span class="f-llv f-llvno"><span>{!! __('Level notice') !!}</span></span>
<span class="f-llv f-llvin"><span>{!! __('Level info') !!}</span></span>
<span class="f-llv f-llvde"><span>{!! __('Level debug') !!}</span></span>
<span class="f-logbt"></span>
</p>
<ul>
@foreach ($p->logsInfo as $hash => $cur)
<li class="f-lgli">
<span class="f-lgname" title="{!! __('Log name') !!}">{{ $cur['log_name'] }}</span>
<span class="f-llv f-llvem" title="{!! __('Level emergency') !!}">{{ num($cur['emergency']) }}</span>
<span class="f-llv f-llval" title="{!! __('Level alert') !!}">{{ num($cur['alert']) }}</span>
<span class="f-llv f-llvcr" title="{!! __('Level critical') !!}">{{ num($cur['critical']) }}</span>
<span class="f-llv f-llver" title="{!! __('Level error') !!}">{{ num($cur['error']) }}</span>
<span class="f-llv f-llvwa" title="{!! __('Level warning') !!}">{{ num($cur['warning']) }}</span>
<span class="f-llv f-llvno" title="{!! __('Level notice') !!}">{{ num($cur['notice']) }}</span>
<span class="f-llv f-llvin" title="{!! __('Level info') !!}">{{ num($cur['info']) }}</span>
<span class="f-llv f-llvde" title="{!! __('Level debug') !!}">{{ num($cur['debug']) }}</span>
<span class="f-lgname f-lgsname">
<a class="f-lganame" href="{{ $cur['linkView'] }}" title="{!! __('View log %s', $cur['log_name']) !!}">{{ $cur['log_name'] }}</a>
</span>
<span class="f-llv @if ($cur['emergency']) f-llvem @endif" title="{!! __('Level emergency') !!}"><span>{{ num($cur['emergency']) }}</span></span>
<span class="f-llv @if ($cur['alert']) f-llval @endif" title="{!! __('Level alert') !!}"><span>{{ num($cur['alert']) }}</span></span>
<span class="f-llv @if ($cur['critical']) f-llvcr @endif" title="{!! __('Level critical') !!}"><span>{{ num($cur['critical']) }}</span></span>
<span class="f-llv @if ($cur['error']) f-llver @endif" title="{!! __('Level error') !!}"><span>{{ num($cur['error']) }}</span></span>
<span class="f-llv @if ($cur['warning']) f-llvwa @endif" title="{!! __('Level warning') !!}"><span>{{ num($cur['warning']) }}</span></span>
<span class="f-llv @if ($cur['notice']) f-llvno @endif" title="{!! __('Level notice') !!}"><span>{{ num($cur['notice']) }}</span></span>
<span class="f-llv @if ($cur['info']) f-llvin @endif" title="{!! __('Level info') !!}"><span>{{ num($cur['info']) }}</span></span>
<span class="f-llv @if ($cur['debug']) f-llvde @endif" title="{!! __('Level debug') !!}"><span>{{ num($cur['debug']) }}</span></span>
<span class="f-logbt">
<a class="f-btn f-lga f-lgaview" href="" title="{!! __('View log') !!}"><span class="f-lgs">{!! __('View log') !!}</span></a>
<a class="f-btn f-lga f-lgadown" href="" title="{!! __('Download log') !!}"><span class="f-lgs">{!! __('Download log') !!}</span></a>
<a class="f-btn f-lga f-lgadel" href="" title="{!! __('Delete log') !!}"><span class="f-lgs">{!! __('Delete log') !!}</span></a>
<a class="f-btn f-lga f-lgadown" href="{{ $cur['linkDownload'] }}" title="{!! __('Download log') !!}"><span class="f-lgs">{!! __('Download log') !!}</span></a>
<a class="f-btn f-lga f-lgadel" href="{{ $cur['linkDelete'] }}" title="{!! __('Delete log') !!}"><span class="f-lgs">{!! __('Delete log') !!}</span></a>
</span>
</li>
@endforeach

View file

@ -0,0 +1 @@
{!! $p->plainRaw !!}

View file

@ -3303,36 +3303,53 @@ html[lang="ru"] #fork details[open] > summary::after {
display: flex;
}
#forka .f-llvem {
color: #B71C1C;
#forka .f-lgp {
border-top: 0.0625rem dotted #AA7939;
}
#forka .f-llval {
color: #D32F2F;
#forka .f-llv > span {
margin: 0.125rem 0.1875rem;
display: block;
}
#forka .f-llvcr {
color: #F44336;
#forka .f-llvem > span {
color: #F8F4E3;
background-color: #B71C1C;
}
#forka .f-llver {
color: #FF5722;
#forka .f-llval > span {
color: #F8F4E3;
background-color: #D32F2F;
}
#forka .f-llvwa {
color: #FF9100;
#forka .f-llvcr > span {
color: #F8F4E3;
background-color: #F44336;
}
#forka .f-llvno {
color: #4CAF50;
#forka .f-llver > span {
color: #F8F4E3;
background-color: #FF5722;
}
#forka .f-llvin {
color: #1976D2;
#forka .f-llvwa > span {
color: #F8F4E3;
background-color: #FF9100;
}
#forka .f-llvde {
color: #90CAF9;
#forka .f-llvno > span {
color: #F8F4E3;
background-color: #4CAF50;
}
#forka .f-llvin > span {
color: #F8F4E3;
background-color: #1976D2;
}
#forka .f-llvde > span {
color: #F8F4E3;
background-color: #90CAF9;
}
#forka .f-lgname {
@ -3340,12 +3357,12 @@ html[lang="ru"] #fork details[open] > summary::after {
}
#forka .f-logbt {
width: 5rem;
width: 3.25rem;
text-align: right;
}
#forka .f-llv {
width: calc( (100% - 13rem) / 8 );
width: calc( (100% - 11.25rem) / 8 );
text-align: center;
}
@ -3358,10 +3375,6 @@ html[lang="ru"] #fork details[open] > summary::after {
font-weight: 900;
}
#forka .f-lgaview:before {
content: "\f002";
}
#forka .f-lgadown:before {
content: "\f019";
}
@ -3374,6 +3387,11 @@ html[lang="ru"] #fork details[open] > summary::after {
display: none;
}
#forka .f-logdel-form .f-fbtn {
display: inline-block;
width: auto;
}
/****************************************/
@media screen and (min-width: 81rem) {
#fork.f-with-nav {