diff --git a/ajax.php b/ajax.php index f1c6dcb2..2a251862 100644 --- a/ajax.php +++ b/ajax.php @@ -71,7 +71,7 @@ if (isset($_GET['certificate_get_json_details'])) { * Looks up info for a given domain ID from the database, used to dynamically populate modal fields */ if (isset($_GET['domain_get_json_details'])) { - validateTechRole(); + enforceUserPermission('module_support'); $domain_id = intval($_GET['domain_id']); $client_id = intval($_GET['client_id']); @@ -88,6 +88,24 @@ if (isset($_GET['domain_get_json_details'])) { $response['vendors'][] = $row; } + // Get domain history + $history_sql = mysqli_query($mysqli, "SELECT * FROM domain_history WHERE domain_history_domain_id = $domain_id"); + $history_html = ""; + $history_html .= ""; + while ($row = mysqli_fetch_array($history_sql)) { + // Fetch data from the query and create table rows + $history_html .= ""; + $history_html .= ""; + $history_html .= ""; + $history_html .= ""; + $history_html .= ""; + $history_html .= ""; + } + $history_html .= "
DateColumnOld ValueNew Value
" . htmlspecialchars(date('Y-m-d', strtotime($row['domain_history_modified_at']))) . "" . htmlspecialchars($row['domain_history_column']) . "" . htmlspecialchars($row['domain_history_old_value']) . "" . htmlspecialchars($row['domain_history_new_value']) . "
"; + + // Return the HTML content to JavaScript + $response['history'] = $history_html; + echo json_encode($response); } diff --git a/client_domains.php b/client_domains.php index 04b47b74..d782cc2b 100644 --- a/client_domains.php +++ b/client_domains.php @@ -154,7 +154,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); $domain_expire = nullable_htmlentities($row['domain_expire']); $domain_expire_ago = timeAgo($domain_expire); // Convert the expiry date to a timestamp - $domain_expire_timestamp = strtotime($row['domain_expire']); + $domain_expire_timestamp = strtotime($row['domain_expire'] ?? ''); $current_timestamp = time(); // Get current timestamp // Calculate the difference in days @@ -228,12 +228,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); Unarchive - Delete - diff --git a/database_updates.php b/database_updates.php index 97e1426b..90022fc8 100644 --- a/database_updates.php +++ b/database_updates.php @@ -2411,16 +2411,23 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) { } if (CURRENT_DATABASE_VERSION == '1.7.6') { - // Create a field to show connected interfae of a foreign asset + // Create a field to show connected interface of a foreign asset mysqli_query($mysqli, "ALTER TABLE `asset_interfaces` ADD `interface_connected_asset_interface` INT(11) NOT NULL DEFAULT 0 AFTER `interface_network_id`"); mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.7.7'"); } - // if (CURRENT_DATABASE_VERSION == '1.7.7') { - // // Insert queries here required to update to DB version 1.7.8 + if (CURRENT_DATABASE_VERSION == '1.7.7') { + // Domain history + mysqli_query($mysqli, "CREATE TABLE `domain_history` (`domain_history_id` INT(11) NOT NULL AUTO_INCREMENT , `domain_history_column` VARCHAR(200) NOT NULL , `domain_history_old_value` TEXT NOT NULL , `domain_history_new_value` TEXT NOT NULL , `domain_history_domain_id` INT(11) NOT NULL , `domain_history_modified_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP , PRIMARY KEY (`domain_history_id`)) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;"); + + mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.7.8'"); + } + + // if (CURRENT_DATABASE_VERSION == '1.7.8') { + // // Insert queries here required to update to DB version 1.7.9 // // Then, update the database to the next sequential version - // mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.7.8'"); + // mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.7.9'"); // } } else { diff --git a/database_version.php b/database_version.php index a8c18cc4..7da0754e 100644 --- a/database_version.php +++ b/database_version.php @@ -5,4 +5,4 @@ * It is used in conjunction with database_updates.php */ -DEFINE("LATEST_DATABASE_VERSION", "1.7.7"); +DEFINE("LATEST_DATABASE_VERSION", "1.7.8"); diff --git a/db.sql b/db.sql index fef58f46..c8f49536 100644 --- a/db.sql +++ b/db.sql @@ -682,6 +682,24 @@ CREATE TABLE `domains` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `domain_history` +-- + +DROP TABLE IF EXISTS `domain_history`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `domain_history` ( + `domain_history_id` int(11) NOT NULL AUTO_INCREMENT, + `domain_history_column` varchar(200) NOT NULL, + `domain_history_old_value` text NOT NULL, + `domain_history_new_value` text NOT NULL, + `domain_history_domain_id` int(11) NOT NULL, + `domain_history_modified_at` datetime NOT NULL DEFAULT current_timestamp(), +PRIMARY KEY (`domain_history_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `email_queue` -- diff --git a/functions.php b/functions.php index 881d2359..225e3128 100644 --- a/functions.php +++ b/functions.php @@ -404,7 +404,6 @@ function apiEncryptLoginEntry(#[\SensitiveParameter]$credential_cleartext, $api_ // Get domain general info (whois + NS/A/MX records) function getDomainRecords($name) { - $records = array(); // Only run if we think the domain is valid @@ -417,11 +416,53 @@ function getDomainRecords($name) } $domain = escapeshellarg(str_replace('www.', '', $name)); - $records['a'] = substr(trim(strip_tags(shell_exec("dig +short $domain"))), 0, 254); - $records['ns'] = substr(trim(strip_tags(shell_exec("dig +short NS $domain"))), 0, 254); - $records['mx'] = substr(trim(strip_tags(shell_exec("dig +short MX $domain"))), 0, 254); - $records['txt'] = substr(trim(strip_tags(shell_exec("dig +short TXT $domain"))), 0, 254); - $records['whois'] = substr(trim(strip_tags(shell_exec("whois -H $domain | sed 's/ //g' | head -30"))), 0, 254); + + // Get A, NS, MX, TXT, and WHOIS records + $records['a'] = trim(strip_tags(shell_exec("dig +short $domain"))); + $records['ns'] = trim(strip_tags(shell_exec("dig +short NS $domain"))); + $records['mx'] = trim(strip_tags(shell_exec("dig +short MX $domain"))); + $records['txt'] = trim(strip_tags(shell_exec("dig +short TXT $domain"))); + $records['whois'] = substr(trim(strip_tags(shell_exec("whois -H $domain | sed 's/ //g' | head -30"))), 0, 255); + + // Sort A records (if multiple records exist) + if (!empty($records['a'])) { + $aRecords = explode("\n", $records['a']); + array_walk($aRecords, function(&$record) { + $record = trim($record); + }); + sort($aRecords); + $records['a'] = implode("\n", $aRecords); + } + + // Sort NS records (if multiple records exist) + if (!empty($records['ns'])) { + $nsRecords = explode("\n", $records['ns']); + array_walk($nsRecords, function(&$record) { + $record = trim($record); + }); + sort($nsRecords); + $records['ns'] = implode("\n", $nsRecords); + } + + // Sort MX records (if multiple records exist) + if (!empty($records['mx'])) { + $mxRecords = explode("\n", $records['mx']); + array_walk($mxRecords, function(&$record) { + $record = trim($record); + }); + sort($mxRecords); + $records['mx'] = implode("\n", $mxRecords); + } + + // Sort TXT records (if multiple records exist) + if (!empty($records['txt'])) { + $txtRecords = explode("\n", $records['txt']); + array_walk($txtRecords, function(&$record) { + $record = trim($record); + }); + sort($txtRecords); + $records['txt'] = implode("\n", $txtRecords); + } return $records; } diff --git a/js/domain_edit_modal.js b/js/domain_edit_modal.js index a0206b33..d8642d63 100644 --- a/js/domain_edit_modal.js +++ b/js/domain_edit_modal.js @@ -12,6 +12,7 @@ function populateDomainEditModal(client_id, domain_id) { // Access the domain info (one), registrars (multiple) and webhosts (multiple) const domain = response.domain[0]; const vendors = response.vendors; + const history = response.history; // Populate the domain modal fields document.getElementById("editDomainHeader").innerText = domain.domain_name; @@ -112,6 +113,9 @@ function populateDomainEditModal(client_id, domain_id) { } }); + // Domain History + document.getElementById('editDomainHistoryContainer').innerHTML = history; + } ); } diff --git a/modals/client_domain_edit_modal.php b/modals/client_domain_edit_modal.php index fae8f9e8..9c7c0af4 100644 --- a/modals/client_domain_edit_modal.php +++ b/modals/client_domain_edit_modal.php @@ -22,6 +22,9 @@ +
@@ -166,6 +169,14 @@ +
+
+
+
+
+
+
+ diff --git a/post/user/domain.php b/post/user/domain.php index 4a8c7b08..38484e49 100644 --- a/post/user/domain.php +++ b/post/user/domain.php @@ -77,8 +77,8 @@ if (isset($_POST['edit_domain'])) { // Set/check/lookup expiry date if (strtotime($expire) && (new DateTime($expire)) > (new DateTime())) { $expire = "'" . $expire . "'"; - } - else { + + } else { $expire = getDomainExpirationDate($name); if (strtotime($expire)) { $expire = "'" . $expire . "'"; @@ -97,8 +97,53 @@ if (isset($_POST['edit_domain'])) { $txt = sanitizeInput($records['txt']); $whois = sanitizeInput($records['whois']); + // Current domain info + $original_domain_info = mysqli_fetch_assoc(mysqli_query($mysqli," + SELECT + domains.*, + registrar.vendor_name AS registrar_name, + dnshost.vendor_name AS dnshost_name, + mailhost.vendor_name AS mailhost_name, + webhost.vendor_name AS webhost_name + FROM domains + LEFT JOIN vendors AS registrar ON domains.domain_registrar = registrar.vendor_id + LEFT JOIN vendors AS dnshost ON domains.domain_dnshost = dnshost.vendor_id + LEFT JOIN vendors AS mailhost ON domains.domain_mailhost = mailhost.vendor_id + LEFT JOIN vendors AS webhost ON domains.domain_webhost = webhost.vendor_id + WHERE domain_id = $domain_id + ")); + + // Update domain mysqli_query($mysqli,"UPDATE domains SET domain_name = '$name', domain_description = '$description', domain_registrar = $registrar, domain_webhost = $webhost, domain_dnshost = $dnshost, domain_mailhost = $mailhost, domain_expire = $expire, domain_ip = '$a', domain_name_servers = '$ns', domain_mail_servers = '$mx', domain_txt = '$txt', domain_raw_whois = '$whois', domain_notes = '$notes' WHERE domain_id = $domain_id"); + // Fetch updated info + $new_domain_info = mysqli_fetch_assoc(mysqli_query($mysqli," + SELECT + domains.*, + registrar.vendor_name AS registrar_name, + dnshost.vendor_name AS dnshost_name, + mailhost.vendor_name AS mailhost_name, + webhost.vendor_name AS webhost_name + FROM domains + LEFT JOIN vendors AS registrar ON domains.domain_registrar = registrar.vendor_id + LEFT JOIN vendors AS dnshost ON domains.domain_dnshost = dnshost.vendor_id + LEFT JOIN vendors AS mailhost ON domains.domain_mailhost = mailhost.vendor_id + LEFT JOIN vendors AS webhost ON domains.domain_webhost = webhost.vendor_id + WHERE domain_id = $domain_id + ")); + + // Compare/log changes + $ignored_columns = ["domain_updated_at", "domain_accessed_at", "domain_registrar", "domain_webhost", "domain_dnshost", "domain_mailhost"]; + foreach ($original_domain_info as $column => $old_value) { + $new_value = $new_domain_info[$column]; + if ($old_value != $new_value && !in_array($column, $ignored_columns)) { + $column = sanitizeInput($column); + $old_value = sanitizeInput($old_value); + $new_value = sanitizeInput($new_value); + mysqli_query($mysqli,"INSERT INTO domain_history SET domain_history_column = '$column', domain_history_old_value = '$old_value', domain_history_new_value = '$new_value', domain_history_domain_id = $domain_id"); + } + } + // Logging logAction("Domain", "Edit", "$session_name edited domain $name", $client_id, $domain_id); @@ -167,6 +212,8 @@ if (isset($_GET['delete_domain'])) { mysqli_query($mysqli,"DELETE FROM domains WHERE domain_id = $domain_id"); + mysqli_query($mysqli, "DELETE FROM domain_history WHERE domain_history_domain_id = $domain_id");# + // Logging logAction("Domain", "Delete", "$session_name deleted domain $domain_name", $client_id); diff --git a/scripts/cron.php b/scripts/cron.php index e36d94ed..dbb3e0f6 100644 --- a/scripts/cron.php +++ b/scripts/cron.php @@ -145,6 +145,23 @@ mysqli_query($mysqli, "DELETE FROM app_logs WHERE app_log_created_at < CURDATE() // Cleanup old auth logs mysqli_query($mysqli, "DELETE FROM auth_logs WHERE auth_log_created_at < CURDATE() - INTERVAL $config_log_retention DAY"); +// CLeanup old domain history +$sql = mysqli_query($mysqli, "SELECT domain_id FROM domains"); +while ($row = mysqli_fetch_array($sql)) { + $domain_id = intval($row['domain_id']); + mysqli_query($mysqli, " + DELETE FROM domain_history + WHERE domain_history_id NOT IN ( + SELECT domain_history_id FROM ( + SELECT domain_history_id FROM domain_history + WHERE domain_history_domain_id = $domain_id + ORDER BY domain_history_modified_at DESC + LIMIT 25 + ) AS recent_entries + ) AND domain_history_domain_id = $domain_id + "); +} + // Logging // logAction("Cron", "Task", "Cron cleaned up old data");