From 5df4c5d521251f03552d8b09cfc1add62cab308c Mon Sep 17 00:00:00 2001 From: Antonio Date: Thu, 25 Jul 2024 19:22:33 +0200 Subject: [PATCH] Tarea #1275 - agregar modelo LogAudit --- Core/Lib/ExtendedController/LogAuditTrait.php | 2 +- Core/Model/Asiento.php | 6 +- Core/Model/Base/BusinessDocument.php | 4 +- Core/Model/Base/TransformerDocument.php | 4 +- Core/Model/LogAudit.php | 139 ++++++++++++++++++ Core/Table/logs_audit.xml | 59 ++++++++ Test/Core/Model/LogAuditTest.php | 58 ++++++++ Test/Traits/LogErrorsTrait.php | 12 +- 8 files changed, 272 insertions(+), 12 deletions(-) create mode 100644 Core/Model/LogAudit.php create mode 100644 Core/Table/logs_audit.xml create mode 100644 Test/Core/Model/LogAuditTest.php diff --git a/Core/Lib/ExtendedController/LogAuditTrait.php b/Core/Lib/ExtendedController/LogAuditTrait.php index c81fd9de3d..f25c64c9d5 100644 --- a/Core/Lib/ExtendedController/LogAuditTrait.php +++ b/Core/Lib/ExtendedController/LogAuditTrait.php @@ -25,7 +25,7 @@ trait LogAuditTrait { public function createViewLogAudit(string $viewName = 'ListLogMessage') { - $this->addListView($viewName, 'LogMessage', 'history', 'fas fa-history'); + $this->addListView($viewName, 'LogAudit', 'history', 'fas fa-history'); $this->views[$viewName]->addOrderBy(['time'], 'date', 2); $this->views[$viewName]->addSearchFields(['context', 'message']); diff --git a/Core/Model/Asiento.php b/Core/Model/Asiento.php index bbd784de0f..51d9d8f989 100644 --- a/Core/Model/Asiento.php +++ b/Core/Model/Asiento.php @@ -169,7 +169,8 @@ public function delete(): bool } // add audit log - Tools::log(self::AUDIT_CHANNEL)->warning('deleted-model', [ + $logAudit = new LogAudit(); + $logAudit->warning('deleted-model', [ '%model%' => $this->modelClassName(), '%key%' => $this->primaryColumnValue(), '%desc%' => $this->primaryDescription(), @@ -337,7 +338,8 @@ public function save(): bool } // add audit log - Tools::log(self::AUDIT_CHANNEL)->info('updated-model', [ + $logAudit = new LogAudit(); + $logAudit->info('updated-model', [ '%model%' => $this->modelClassName(), '%key%' => $this->primaryColumnValue(), '%desc%' => $this->primaryDescription(), diff --git a/Core/Model/Base/BusinessDocument.php b/Core/Model/Base/BusinessDocument.php index 3c5aab4172..bb992e1de3 100644 --- a/Core/Model/Base/BusinessDocument.php +++ b/Core/Model/Base/BusinessDocument.php @@ -22,6 +22,7 @@ use FacturaScripts\Core\Base\DataBase\DataBaseWhere; use FacturaScripts\Core\Base\Utils; use FacturaScripts\Core\DataSrc\Almacenes; +use FacturaScripts\Core\Model\LogAudit; use FacturaScripts\Core\Tools; use FacturaScripts\Dinamic\Lib\BusinessDocumentCode; use FacturaScripts\Dinamic\Model\Almacen; @@ -506,7 +507,8 @@ protected function saveUpdate(array $values = []): bool } // add audit log - Tools::log(self::AUDIT_CHANNEL)->info('updated-model', [ + $logAudit = new LogAudit(); + $logAudit->info('updated-model', [ '%model%' => $this->modelClassName(), '%key%' => $this->primaryColumnValue(), '%desc%' => $this->primaryDescription(), diff --git a/Core/Model/Base/TransformerDocument.php b/Core/Model/Base/TransformerDocument.php index dd060beacc..6bc78ff8fb 100644 --- a/Core/Model/Base/TransformerDocument.php +++ b/Core/Model/Base/TransformerDocument.php @@ -20,6 +20,7 @@ namespace FacturaScripts\Core\Model\Base; use FacturaScripts\Core\Base\DataBase\DataBaseWhere; +use FacturaScripts\Core\Model\LogAudit; use FacturaScripts\Core\Tools; use FacturaScripts\Dinamic\Lib\BusinessDocumentGenerator; use FacturaScripts\Dinamic\Model\DocTransformation; @@ -167,7 +168,8 @@ public function delete(): bool } // add audit log - Tools::log(self::AUDIT_CHANNEL)->warning('deleted-model', [ + $logAudit = new LogAudit(); + $logAudit->warning('deleted-model', [ '%model%' => $this->modelClassName(), '%key%' => $this->primaryColumnValue(), '%desc%' => $this->primaryDescription(), diff --git a/Core/Model/LogAudit.php b/Core/Model/LogAudit.php new file mode 100644 index 0000000000..ea860b49ca --- /dev/null +++ b/Core/Model/LogAudit.php @@ -0,0 +1,139 @@ +time = Tools::dateTime(); + } + + /** + * Returns the saved context as array. + * + * @return array + */ + public function context(): array + { + return json_decode(Tools::fixHtml($this->context), true); + } + + public function delete(): bool + { + Tools::log()->warning('cant-delete-audit-log'); + return false; + } + + public static function primaryColumn(): string + { + return 'id'; + } + + public static function tableName(): string + { + return 'logs_audit'; + } + + public function test(): bool + { + $this->channel = Tools::noHtml($this->channel); + $this->context = Tools::noHtml($this->context); + $this->message = Tools::noHtml($this->message); + if (strlen($this->message) > static::MAX_MESSAGE_LEN) { + $this->message = substr($this->message, 0, static::MAX_MESSAGE_LEN); + } + + $this->model = Tools::noHtml($this->model); + $this->modelcode = Tools::noHtml((string)$this->modelcode); + $this->uri = Tools::noHtml($this->uri); + + return parent::test(); + } + + /** + * @param string $message + * @param array $context + */ + public function warning(string $message, array $context = []): void + { + $this->level = 'warning'; + $this->log($message, $context); + } + + public function info(string $message, array $context = []): void + { + $this->level = 'info'; + $this->log($message, $context); + } + + private function log(string $message, array $context = []): void + { + $this->channel = self::AUDIT_CHANNEL; + $this->context = $this->getContext($context); + $this->idcontacto = $context['idcontacto'] ?? null; + $this->ip = Session::getClientIp(); + $this->message = Tools::lang()->trans($message, $context); + $this->model = $context['model-class'] ?? null; + $this->modelcode = $context['model-code'] ?? null; + $this->nick = $context['nick'] ?? Session::user()->nick; + $this->time = isset($context['time']) ? date('d-m-Y H:i:s', (int)$context['time']) : date('d-m-Y H:i:s'); + $this->uri = $context['uri'] ?? Session::get('uri'); + $this->save(); + } + + protected function saveUpdate(array $values = []): bool + { + Tools::log()->warning('cant-update-audit-log'); + return false; + } + + private function getContext(array $context) + { + return json_encode($context); + } +} diff --git a/Core/Table/logs_audit.xml b/Core/Table/logs_audit.xml new file mode 100644 index 0000000000..e0c8e9297e --- /dev/null +++ b/Core/Table/logs_audit.xml @@ -0,0 +1,59 @@ + + + + channel + character varying(40) + + + context + text + + + id + serial + NO + + + idcontacto + integer + + + ip + character varying(40) + + + level + character varying(15) + NO + + + message + text + NO + + + model + character varying(30) + + + modelcode + character varying(40) + + + nick + character varying(50) + + + time + timestamp + NO + + + uri + character varying(200) + + + logs_pkey + PRIMARY KEY (id) + +
\ No newline at end of file diff --git a/Test/Core/Model/LogAuditTest.php b/Test/Core/Model/LogAuditTest.php new file mode 100644 index 0000000000..5fc25e220e --- /dev/null +++ b/Test/Core/Model/LogAuditTest.php @@ -0,0 +1,58 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +namespace FacturaScripts\Test\Core\Model; + +use FacturaScripts\Core\Model\Base\ModelCore; +use FacturaScripts\Core\Model\LogAudit; +use FacturaScripts\Test\Traits\LogErrorsTrait; +use PHPUnit\Framework\TestCase; + +class LogAuditTest extends TestCase +{ + use LogErrorsTrait; + + public function testCanNotDeleteAuditLogs() + { + $item = new LogAudit(); + $item->channel = ModelCore::AUDIT_CHANNEL; + $item->level = 'info'; + $item->message = 'test-audit-to-delete'; + $this->assertTrue($item->save(), 'cant-save-model'); + $this->assertTrue($item->exists(), 'item-not-found-in-db'); + $this->assertFalse($item->delete(), 'can-delete-audit-log'); + } + + public function testCanNotUpdateAuditLogs() + { + $item = new LogAudit(); + $item->channel = ModelCore::AUDIT_CHANNEL; + $item->level = 'info'; + $item->message = 'test-audit-to-update'; + $this->assertTrue($item->save(), 'cant-save-model'); + + $item->message = 'test-audit-to-update-2'; + $this->assertFalse($item->save(), 'can-update-audit-log'); + } + + protected function tearDown(): void + { + $this->logErrors(); + } +} diff --git a/Test/Traits/LogErrorsTrait.php b/Test/Traits/LogErrorsTrait.php index b3a636b0e5..fe32192ac8 100644 --- a/Test/Traits/LogErrorsTrait.php +++ b/Test/Traits/LogErrorsTrait.php @@ -20,6 +20,7 @@ namespace FacturaScripts\Test\Traits; use FacturaScripts\Core\Base\MiniLog; +use FacturaScripts\Core\Model\LogAudit; trait LogErrorsTrait { @@ -36,12 +37,9 @@ protected function logErrors() protected function searchAuditLog(string $modelClass, string $modelCode): bool { - foreach (MiniLog::read('audit') as $log) { - if ($log['context']['model-class'] === $modelClass && $log['context']['model-code'] === $modelCode) { - return true; - } - } - - return false; + return LogAudit::table() + ->whereEq('model', $modelClass) + ->whereEq('modelcode', $modelCode) + ->count() === 1; } }