From 7cced63c4bcb917bd9884a8947a2e1599acea80c Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Wed, 16 Oct 2024 14:13:20 +0900 Subject: [PATCH] Update the Admin\Backend edit log call with query params and different data compressors All queries uses now Params On load checks for valid write types for edit log write, eg if bzip and lzip compression are avaiable adbEditLog: Also add JSON type encoding for data outside STRING/SERIAL and BINARY/BZIP (bzip compressed) Add ZLIB as altnerative to BZIP Add alert if invalid type was set Auto fallback to JSON if other write types are not available adbLiveQueue: Also convert the live queue query to a params style call --- www/admin/class_test.admin.backend.php | 20 ++- www/lib/CoreLibs/Admin/Backend.php | 222 ++++++++++++++++++------- 2 files changed, 180 insertions(+), 62 deletions(-) diff --git a/www/admin/class_test.admin.backend.php b/www/admin/class_test.admin.backend.php index de776a25..c117aec1 100644 --- a/www/admin/class_test.admin.backend.php +++ b/www/admin/class_test.admin.backend.php @@ -55,7 +55,25 @@ print '

' . $PAGE_NAME . '

'; print "SETACL[]:
"; $backend->setACL(['EMPTY' => 'EMPTY']); print "ADBEDITLOG:
"; -$backend->adbEditLog('CLASSTEST-ADMIN', 'Some info string'); +$backend->adbEditLog('CLASSTEST-ADMIN-BINARY', 'Some info string', 'BINARY'); +$backend->adbEditLog('CLASSTEST-ADMIN-ZLIB', 'Some info string', 'ZLIB'); +$backend->adbEditLog('CLASSTEST-ADMIN-SERIAL', 'Some info string', 'SERIAL'); +$backend->adbEditLog('CLASSTEST-ADMIN-INVALID', 'Some info string', 'INVALID'); +// test with various +$backend->action = 'TEST ACTION'; +$backend->action_id = 'TEST ACTION ID'; +$backend->action_yes = 'TEST ACTION YES'; +$backend->action_flag = 'TEST ACTION FLAG'; +$backend->action_menu = 'TEST ACTION MENU'; +$backend->action_loaded = 'TEST ACTION LOADED'; +$backend->action_value = 'TEST ACTION VALUE'; +$backend->action_type = 'TEST ACTION TYPE'; +$backend->action_error = 'TEST ACTION ERROR'; +$backend->adbEditLog('CLASSTEST-ADMIN-JSON', [ + "_GET" => $_GET, + "_POST" => $_POST, +], 'JSON'); + print "ADBTOPMENU(0): " . Support::printAr($backend->adbTopMenu(CONTENT_PATH)) . "
"; print "ADBMSG:
"; $backend->adbMsg('info', 'Message: %1$d', [1]); diff --git a/www/lib/CoreLibs/Admin/Backend.php b/www/lib/CoreLibs/Admin/Backend.php index e6606631..044930a5 100644 --- a/www/lib/CoreLibs/Admin/Backend.php +++ b/www/lib/CoreLibs/Admin/Backend.php @@ -31,6 +31,8 @@ declare(strict_types=1); namespace CoreLibs\Admin; +use CoreLibs\Convert\Json; + class Backend { // page name @@ -42,7 +44,7 @@ class Backend /** @var array */ public array $action_list = [ 'action', 'action_id', 'action_sub_id', 'action_yes', 'action_flag', - 'action_menu', 'action_value', 'action_error', 'action_loaded' + 'action_menu', 'action_value', 'action_type', 'action_error', 'action_loaded' ]; /** @var string */ public string $action; @@ -61,20 +63,31 @@ class Backend /** @var string */ public string $action_value; /** @var string */ + public string $action_type; + /** @var string */ public string $action_error; + // ACL array variable if we want to set acl data from outisde /** @var array */ public array $acl = []; /** @var int */ public int $default_acl; + // queue key /** @var string */ public string $queue_key; + + /** @var array list of allowed types for edit log write */ + private const WRITE_TYPES = ['BINARY', 'BZIP2', 'LZIP', 'STRING', 'SERIAL', 'JSON']; + /** @var array list of available write types for log */ + private array $write_types_available = []; + // the current active edit access id /** @var int|null */ public int|null $edit_access_id; /** @var string */ public string $page_name; + // error/warning/info messages /** @var array */ public array $messages = []; @@ -84,6 +97,7 @@ class Backend public bool $warning = false; /** @var bool */ public bool $info = false; + // internal lang & encoding vars /** @var string */ public string $lang_dir = ''; @@ -95,6 +109,7 @@ class Backend public string $domain; /** @var string */ public string $encoding; + /** @var \CoreLibs\Logging\Logging logger */ public \CoreLibs\Logging\Logging $log; /** @var \CoreLibs\DB\IO database */ @@ -103,6 +118,7 @@ class Backend public \CoreLibs\Language\L10n $l; /** @var \CoreLibs\Create\Session session class */ public \CoreLibs\Create\Session $session; + // smarty publics [end processing in smarty class] /** @var array */ public array $DATA = []; @@ -175,6 +191,9 @@ class Backend if (preg_match("/^(add|save|delete|remove|move|up|down|push_live)$/", $this->action ?? '')) { $this->queue_key = \CoreLibs\Create\RandomKey::randomKeyGen(3); } + + // check what edit log data write types are allowed + $this->adbSetEditLogWriteTypeAvailable(); } /** @@ -185,7 +204,26 @@ class Backend // NO OP } - // PUBLIC METHODS |=================================================> + // MARK: PRIVATE METHODS + + /** + * set the write types that are allowed + * + * @return void + */ + private function adbSetEditLogWriteTypeAvailable() + { + // check what edit log data write types are allowed + $this->write_types_available = self::WRITE_TYPES; + if (!function_exists('bzcompress')) { + $this->write_types_available = array_diff($this->write_types_available, ['BINARY', 'BZIP']); + } + if (!function_exists('gzcompress')) { + $this->write_types_available = array_diff($this->write_types_available, ['LZIP']); + } + } + + // MARK: PUBLIC METHODS |=================================================> /** * set internal ACL from login ACL @@ -223,27 +261,57 @@ class Backend /** * writes all action vars plus other info into edit_log table * - * @param string $event any kind of event description, - * @param string|array $data any kind of data related to that event - * @param string $write_type write type can bei STRING or BINARY - * @param string|null $db_schema override target schema + * @param string $event [default=''] any kind of event description, + * @param string|array $data [default=''] any kind of data related to that event + * @param string $write_type [default=JSON] write type can be + * JSON, STRING/SERIEAL, BINARY/BZIP or ZLIB + * @param string|null $db_schema [default=null] override target schema * @return void */ public function adbEditLog( string $event = '', string|array $data = '', - string $write_type = 'STRING', + string $write_type = 'JSON', ?string $db_schema = null ): void { $data_binary = ''; $data_write = ''; - if ($write_type == 'BINARY') { - $data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data))); - $data_write = 'see bzip compressed data_binary field'; + // check if write type is valid, if not fallback to JSON + if (!in_array($write_type, $this->write_types_available)) { + $this->log->warning('Write type not in allowed array, fallback to JSON', context:[ + "write_type" => $write_type, + "write_list" => $this->write_types_available, + ]); + $write_type = 'JSON'; } - if ($write_type == 'STRING') { - $data_binary = ''; - $data_write = $this->db->dbEscapeString(serialize($data)); + switch ($write_type) { + case 'BINARY': + case 'BZIP': + $data_binary = $this->db->dbEscapeBytea((string)bzcompress(serialize($data))); + $data_write = 'see bzip compressed data_binary field'; + break; + case 'ZLIB': + $data_binary = $this->db->dbEscapeBytea((string)gzcompress(serialize($data))); + $data_write = 'see zlib compressed data_binary field'; + break; + case 'STRING': + case 'SERIAL': + $data_binary = ''; + $data_write = serialize($data); + break; + case 'JSON': + $data_binary = ''; + // must be converted to array + if (!is_array($data)) { + $data = ["data" => $data]; + } + $data_write = Json::jsonConvertArrayTo($data); + break; + default: + $this->log->alert('Invalid type for data compression was set', context:[ + "write_type" => $write_type + ]); + break; } /** @var string $DB_SCHEMA check schema */ @@ -253,44 +321,62 @@ class Backend } elseif (!empty($this->db->dbGetSchema())) { $DB_SCHEMA = $this->db->dbGetSchema(); } - $q = "INSERT INTO " . $DB_SCHEMA . ".edit_log " - . "(euid, event_date, event, data, data_binary, page, " - . "ip, user_agent, referer, script_name, query_string, server_name, http_host, " - . "http_accept, http_accept_charset, http_accept_encoding, session_id, " - . "action, action_id, action_yes, action_flag, action_menu, action_loaded, action_value, action_error) " - . "VALUES " - . "(" . $this->db->dbEscapeString(isset($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ? - $_SESSION['EUID'] : - 'NULL') - . ", " - . "NOW(), " - . "'" . $this->db->dbEscapeString((string)$event) . "', " - . "'" . $data_write . "', " - . "'" . $data_binary . "', " - . "'" . $this->db->dbEscapeString((string)$this->page_name) . "', " - . "'" . ($_SERVER["REMOTE_ADDR"] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['HTTP_USER_AGENT'] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['HTTP_REFERER'] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['SCRIPT_FILENAME'] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['QUERY_STRING'] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['SERVER_NAME'] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['HTTP_HOST'] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT'] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT_CHARSET'] ?? '') . "', " - . "'" . $this->db->dbEscapeString($_SERVER['HTTP_ACCEPT_ENCODING'] ?? '') . "', " - . ($this->session->getSessionId() === false ? - "NULL" : - "'" . $this->session->getSessionId() . "'") - . ", " - . "'" . $this->db->dbEscapeString($this->action ?? '') . "', " - . "'" . $this->db->dbEscapeString($this->action_id ?? '') . "', " - . "'" . $this->db->dbEscapeString($this->action_yes ?? '') . "', " - . "'" . $this->db->dbEscapeString($this->action_flag ?? '') . "', " - . "'" . $this->db->dbEscapeString($this->action_menu ?? '') . "', " - . "'" . $this->db->dbEscapeString($this->action_loaded ?? '') . "', " - . "'" . $this->db->dbEscapeString($this->action_value ?? '') . "', " - . "'" . $this->db->dbEscapeString($this->action_error ?? '') . "')"; - $this->db->dbExec($q, 'NULL'); + $q = <<db->dbExecParams( + str_replace( + ['{DB_SCHEMA}'], + [$DB_SCHEMA], + $q + ), + [ + // row 1 + isset($_SESSION['EUID']) && is_numeric($_SESSION['EUID']) ? + $_SESSION['EUID'] : null, + (string)$event, + $data_write, + $data_binary, + (string)$this->page_name, + // row 2 + $_SERVER["REMOTE_ADDR"] ?? '', + $_SERVER['HTTP_USER_AGENT'] ?? '', + $_SERVER['HTTP_REFERER'] ?? '', + $_SERVER['SCRIPT_FILENAME'] ?? '', + $_SERVER['QUERY_STRING'] ?? '', + $_SERVER['SERVER_NAME'] ?? '', + $_SERVER['HTTP_HOST'] ?? '', + // row 3 + $_SERVER['HTTP_ACCEPT'] ?? '', + $_SERVER['HTTP_ACCEPT_CHARSET'] ?? '', + $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '', + $this->session->getSessionId() !== false ? + $this->session->getSessionId() : null, + // row 4 + $this->action ?? '', + $this->action_id ?? '', + $this->action_yes ?? '', + $this->action_flag ?? '', + $this->action_menu ?? '', + $this->action_loaded ?? '', + $this->action_value ?? '', + $this->action_type ?? '', + $this->action_error ?? '', + ], + 'NULL' + ); } /** @@ -540,16 +626,30 @@ class Backend } elseif (!empty($this->db->dbGetSchema())) { $DB_SCHEMA = $this->db->dbGetSchema(); } - $q = "INSERT INTO " . $DB_SCHEMA . ".live_queue (" - . "queue_key, key_value, key_name, type, target, data, group_key, action, associate, file" - . ") VALUES (" - . "'" . $this->db->dbEscapeString($queue_key) . "', '" . $this->db->dbEscapeString($key_value) . "', " - . "'" . $this->db->dbEscapeString($key_name) . "', '" . $this->db->dbEscapeString($type) . "', " - . "'" . $this->db->dbEscapeString($target) . "', '" . $this->db->dbEscapeString($data) . "', " - . "'" . $this->queue_key . "', '" . $this->action . "', " - . "'" . $this->db->dbEscapeString((string)$associate) . "', " - . "'" . $this->db->dbEscapeString((string)$file) . "')"; - $this->db->dbExec($q); + $q = <<db->dbExec($q); + $this->db->dbExecParams( + str_replace( + ['{DB_SCHEMA}'], + [$DB_SCHEMA], + $q + ), + [ + $queue_key, $key_value, + $key_name, $type, + $target, $data, + $this->queue_key, $this->action, + (string)$associate, (string)$file + ] + ); } /**