Files
itflow/agent/post/asset.php
johnnyq a33f98ffa5 Licenses: rebuilt the license list with Renewing soon, Expired, Over seats and No seats assigned tabs, a seat bar (used against bought, red when over) and colour-coded renewal on each row, license type and renewal filters, optional key, purchase and order reference columns, search by vendor, order reference and individual keys, and bulk Renew, Archive, Restore and Delete; new license page (license.php) with renewal and over-seats status in the header, License and Vendor cards (key, order ref, purchase date, vendor account number, phone, email, website, hours, SLA, all copyable), notes that save on blur, and tabs for Seats (each device and user with the key they were given), Keys, Credentials, Documents, Files and History from the audit log; new license quick look used everywhere a license is shown; New and Edit share one tabbed form (Details, License, Seats, Notes) with device and user pickers, a live seat counter, renewal shortcuts and a template picker that replaces the separate Create from Template modal; Renew modal for one license or a bulk selection that moves the renewal date by a term or to a set date, previews the new date for each license and records a new order reference; Manage Seats modal; individual keys pasted one per line and handed out to devices and users, which gives them a seat, with the key returned to the pool when they come off the license; Renewal Ticket opens New Ticket with the subject and details filled in; New Document and Upload from a license link the result to it; devices, users, credentials and files now link to licenses through the shared link modal, which shows the seats left on each license and offers every license type, not just Device; the asset and contact pages and quick looks list licenses with their seats, renewal and the key to install, and get New License; the client overview gets a Licenses over seats card under Needs attention, starred licenses under Favorites and renewals that open the license page; global search finds licenses by name, vendor, order reference or key; the vendor quick look lists that vendor's licenses; the dashboard card opens the Renewing tab; the export gains seats used, individual keys, vendor, order reference and client columns; admin license templates share the license type list and show type icons. Uses the existing software_keys, key assignment, software_credentials and software_files tables. Fixes editing a Subscription or Open Source license clearing its license type, archiving a license removing all of its seats (seats are now kept, matching the API), license forms and seat handlers accepting another client's assets, contacts or vendor, a 500 on duplicate seat links and on forms missing fields, and an extra query per row in the export; license deletes now respect the destructive deletes setting. No DB change
2026-10-14 21:31:30 -04:00

1977 lines
72 KiB
PHP

<?php
/*
* ITFlow - GET/POST request handler for client assets
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
require_once 'asset_model.php';
$client_id = intval($_POST['client_id']);
enforceClientAccess();
// The picks have to be this client's own
$location = assetClientOwnedId('location', $location, $client_id);
$contact = assetClientOwnedId('contact', $contact, $client_id);
$vendor = assetClientOwnedId('vendor', $vendor, $client_id);
$network = assetClientOwnedId('network', $network, $client_id);
// Only the two credential fields this handler writes - name/description/uri here
// belong to the asset, not the credential, and have their own column widths.
// Checked before the asset is created, so an overlong credential can't leave a
// half-built asset behind. Form maxlength doesn't reach a hand-rolled POST.
if ($credential_field_too_long = checkCredentialLengths([
'username' => $_POST['username'] ?? null,
'password' => $_POST['password'] ?? null,
])) {
flashAlert("Credential <strong>$credential_field_too_long</strong> is too long to store", 'error');
redirect();
exit;
}
$alert_extended = "";
mysqli_query($mysqli,"INSERT INTO assets SET asset_name = '$name', asset_description = '$description', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_uri = '$uri', asset_uri_2 = '$uri_2', asset_uri_client = '$uri_client', asset_location_id = $location, asset_vendor_id = $vendor, asset_contact_id = $contact, asset_status = '$status', asset_purchase_reference = '$purchase_reference', asset_purchase_date = $purchase_date, asset_warranty_expire = $warranty_expire, asset_install_date = $install_date, asset_physical_location = '$physical_location', asset_notes = '$notes', asset_favorite = $favorite, asset_client_id = $client_id");
$asset_id = mysqli_insert_id($mysqli);
// Add Tags
if (isset($_POST['tags'])) {
foreach($_POST['tags'] as $tag) {
$tag = intval($tag);
mysqli_query($mysqli, "INSERT INTO asset_tags SET asset_tag_asset_id = $asset_id, asset_tag_tag_id = $tag");
}
}
// Add Photo
if (isset($_FILES['file']['tmp_name'])) {
if ($new_file_name = checkFileUpload($_FILES['file'], array('jpg', 'jpeg', 'gif', 'png', 'webp'))) {
$file_tmp_path = $_FILES['file']['tmp_name'];
// directory in which the uploaded file will be moved
if (!file_exists("../uploads/clients/$client_id")) {
mkdir("../uploads/clients/$client_id");
}
$upload_file_dir = "../uploads/clients/$client_id/";
$dest_path = $upload_file_dir . $new_file_name;
move_uploaded_file($file_tmp_path, $dest_path);
mysqli_query($mysqli,"UPDATE assets SET asset_photo = '$new_file_name' WHERE asset_id = $asset_id");
}
}
// Add Primary Interface
mysqli_query($mysqli,"INSERT INTO asset_interfaces SET interface_name = '01', interface_mac = '$mac', interface_ip = '$ip', interface_nat_ip = '$nat_ip', interface_ipv6 = '$ipv6', interface_primary = 1, interface_network_id = $network, interface_asset_id = $asset_id");
if (!empty($_POST['password'])) {
$username = trim(mysqli_real_escape_string($mysqli, encryptCredentialEntry($_POST['username'])));
$password = trim(mysqli_real_escape_string($mysqli, encryptCredentialEntry($_POST['password'])));
mysqli_query($mysqli,"INSERT INTO credentials SET credential_name = '$name', credential_username = '$username', credential_password = '$password', credential_asset_id = $asset_id, credential_client_id = $client_id");
$credential_id = mysqli_insert_id($mysqli);
logAudit("Credential", "Create", "$session_name created login credential for asset $name", $client_id, $credential_id);
$alert_extended = " along with login credentials";
}
// Add to History
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = '$status', asset_history_description = '$session_name created $name', asset_history_asset_id = $asset_id");
logAudit("Asset", "Create", "$session_name created asset $name", $client_id, $asset_id);
flashAlert("Asset <strong>$name</strong> created $alert_extended");
redirect();
}
if (isset($_POST['edit_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
require_once 'asset_model.php';
$asset_id = intval($_POST['asset_id']);
// Get Existing Photo and assigned client_id
$sql = mysqli_query($mysqli,"SELECT asset_photo, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$existing_file_name = $row['asset_photo'] ?? '';
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
// The picks have to be this client's own
$location = assetClientOwnedId('location', $location, $client_id);
$contact = assetClientOwnedId('contact', $contact, $client_id);
$vendor = assetClientOwnedId('vendor', $vendor, $client_id);
$network = assetClientOwnedId('network', $network, $client_id);
mysqli_query($mysqli,"UPDATE assets SET asset_name = '$name', asset_description = '$description', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_uri = '$uri', asset_uri_2 = '$uri_2', asset_uri_client = '$uri_client', asset_location_id = $location, asset_vendor_id = $vendor, asset_contact_id = $contact, asset_status = '$status', asset_purchase_reference = '$purchase_reference', asset_purchase_date = $purchase_date, asset_warranty_expire = $warranty_expire, asset_install_date = $install_date, asset_physical_location = '$physical_location', asset_notes = '$notes', asset_favorite = $favorite WHERE asset_id = $asset_id");
$sql_interfaces = mysqli_query($mysqli, "SELECT 1 FROM asset_interfaces WHERE interface_asset_id = $asset_id AND interface_primary = 1");
if(mysqli_num_rows($sql_interfaces) == 0 ) {
// Add Primary Interface
mysqli_query($mysqli,"INSERT INTO asset_interfaces SET interface_name = '01', interface_mac = '$mac', interface_ip = '$ip', interface_nat_ip = '$nat_ip', interface_ipv6 = '$ipv6', interface_primary = 1, interface_network_id = $network, interface_asset_id = $asset_id");
} else {
// Update Primary Interface
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_mac = '$mac', interface_ip = '$ip', interface_nat_ip = '$nat_ip', interface_ipv6 = '$ipv6', interface_network_id = $network WHERE interface_asset_id = $asset_id AND interface_primary = 1");
}
// Photo - a new upload replaces the old file; Remove only counts when nothing new came in
$existing_photo_path = $existing_file_name !== '' ? "../uploads/clients/$client_id/" . basename($existing_file_name) : '';
if (isset($_FILES['file']) && $new_file_name = checkFileUpload($_FILES['file'], array('jpg', 'jpeg', 'gif', 'png', 'webp'))) {
if (!is_dir("../uploads/clients/$client_id")) {
mkdir("../uploads/clients/$client_id", 0755, true);
}
move_uploaded_file($_FILES['file']['tmp_name'], "../uploads/clients/$client_id/$new_file_name");
if ($existing_photo_path && is_file($existing_photo_path)) {
unlink($existing_photo_path);
}
mysqli_query($mysqli,"UPDATE assets SET asset_photo = '$new_file_name' WHERE asset_id = $asset_id");
} elseif (!empty($_POST['remove_photo']) && $existing_photo_path) {
if (is_file($existing_photo_path)) {
unlink($existing_photo_path);
}
mysqli_query($mysqli,"UPDATE assets SET asset_photo = NULL WHERE asset_id = $asset_id");
}
// Tags
// Delete existing tags
mysqli_query($mysqli, "DELETE FROM asset_tags WHERE asset_tag_asset_id = $asset_id");
// Add new tags
if (isset($_POST['tags'])) {
foreach($_POST['tags'] as $tag) {
$tag = intval($tag);
mysqli_query($mysqli, "INSERT INTO asset_tags SET asset_tag_asset_id = $asset_id, asset_tag_tag_id = $tag");
}
}
// Add to History
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = '$status', asset_history_description = '$session_name updated $name', asset_history_asset_id = $asset_id");
logAudit("Asset", "Edit", "$session_name edited asset $name", $client_id, $asset_id);
flashAlert("Asset <strong>$name</strong> edited");
redirect();
}
if (isset($_GET['archive_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_id = intval($_GET['archive_asset']);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE assets SET asset_archived_at = NOW() WHERE asset_id = $asset_id");
// Add to History
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = 'Archived', asset_history_description = '$session_name archived $asset_name', asset_history_asset_id = $asset_id");
logAudit("Asset", "Archive", "$session_name archived asset $asset_name", $client_id, $asset_id);
flashAlert("Asset <strong>$asset_name</strong> archived", 'error');
redirect();
}
if (isset($_GET['restore_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_id = intval($_GET['restore_asset']);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE assets SET asset_archived_at = NULL WHERE asset_id = $asset_id");
// Add to History
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = 'Restored', asset_history_description = '$session_name restored $asset_name', asset_history_asset_id = $asset_id");
logAudit("Asset", "Restore", "$session_name restored asset $asset_name", $client_id, $asset_id);
flashAlert("Asset <strong>$asset_name</strong> Restored");
redirect();
}
if (isset($_GET['delete_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 3);
$asset_id = intval($_GET['delete_asset']);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"DELETE FROM assets WHERE asset_id = $asset_id");
// Out of whatever rack it was in - an item pointing at a deleted asset draws as nothing
mysqli_query($mysqli,"DELETE FROM rack_units WHERE unit_asset_id = $asset_id");
logAudit("Asset", "Delete", "$session_name deleted asset $asset_name", $client_id);
flashAlert("Asset <strong>$asset_name</strong> deleted");
redirect();
}
if (isset($_POST['add_asset_note'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_id = intval($_POST['asset_id']);
$type = escapeSql($_POST['type']);
$note = escapeSql($_POST['note']);
// Get Asset details for logging and alerting
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli, "INSERT INTO asset_notes SET asset_note_type = '$type', asset_note = '$note', asset_note_created_by = $session_user_id, asset_note_asset_id = $asset_id");
$asset_note_id = mysqli_insert_id($mysqli);
//Logging
logAudit("Asset", "Edit", "$session_name created a $type note for asset $asset_name", $client_id, $asset_id);
$_SESSION['alert_message'] = "Note <strong>$type</strong> created for <strong>$asset_name</strong>";
redirect();
}
if (isset($_GET['archive_asset_note'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_note_id = intval($_GET['archive_asset_note']);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_note_type, asset_id, asset_name, asset_client_id FROM asset_notes LEFT JOIN assets ON asset_id = asset_note_asset_id WHERE asset_note_id = $asset_note_id");
$row = mysqli_fetch_assoc($sql);
$asset_note_type = escapeSql($row['asset_note_type']);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
$asset_id = intval($row['asset_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE asset_notes SET asset_note_archived_at = NOW() WHERE asset_note_id = $asset_note_id");
logAudit("Asset", "Edit", "$session_name archived note $asset_note_type for $asset_name", $client_id, $asset_id);
flashAlert("Note <strong>$asset_note_type</strong> archived", 'error');
redirect();
}
if (isset($_GET['restore_asset_note'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_note_id = intval($_GET['restore_asset_note']);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_note_type, asset_id, asset_name, asset_client_id FROM asset_notes LEFT JOIN assets ON asset_id = asset_note_asset_id WHERE asset_note_id = $asset_note_id");
$row = mysqli_fetch_assoc($sql);
$asset_note_type = escapeSql($row['asset_note_type']);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
$asset_id = intval($row['asset_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE asset_notes SET asset_note_archived_at = NULL WHERE asset_note_id = $asset_note_id");
logAudit("Asset", "Edit", "$session_name restored note $asset_note_type for $asset_name", $client_id, $asset_id);
flashAlert("Note <strong>$asset_note_type</strong> restored");
redirect();
}
if (isset($_GET['delete_asset_note'])) {
validateCSRFToken();
enforceUserPermission('module_support', 3);
$asset_note_id = intval($_GET['delete_asset_note']);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_note_type, asset_id, asset_name, asset_client_id FROM asset_notes LEFT JOIN assets ON asset_id = asset_note_asset_id WHERE asset_note_id = $asset_note_id");
$row = mysqli_fetch_assoc($sql);
$asset_note_type = escapeSql($row['asset_note_type']);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
$asset_id = intval($row['asset_id']);
enforceClientAccess();
mysqli_query($mysqli,"DELETE FROM asset_notes WHERE asset_note_id = $asset_note_id");
logAudit("Asset", "Edit", "$session_name deleted $asset_note_type note for $asset_name", $client_id, $asset_id);
flashAlert("Note <strong>$asset_note_type</strong> deleted.", 'error');
redirect();
}
if (isset($_POST['bulk_assign_asset_location'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$location_id = intval($_POST['bulk_location_id']);
// Get Location name and client id for logging and alert
$sql = mysqli_query($mysqli,"SELECT location_name, location_client_id FROM locations WHERE location_id = $location_id");
$row = mysqli_fetch_assoc($sql);
$location_name = escapeSql($row['location_name']);
$client_id = intval($row['location_client_id']);
$location_client_id = $client_id;
enforceClientAccess();
// Assign Location to Selected Assets
if (isset($_POST['asset_ids'])) {
// Only the assets of the location's client are moved
$asset_count = 0;
foreach($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Details for Logging
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name'] ?? '');
$client_id = intval($row['asset_client_id'] ?? 0);
if (!$row || $client_id !== $location_client_id) {
continue;
}
enforceClientAccess();
$asset_count++;
mysqli_query($mysqli,"UPDATE assets SET asset_location_id = $location_id WHERE asset_id = $asset_id");
logAudit("Asset", "Edit", "$session_name assigned asset $asset_name to location $location_name", $client_id, $asset_id);
} // End Assign Location Loop
logAudit("Asset", "Bulk Edit", "$session_name assigned $asset_count assets to location $location_name", $location_client_id);
flashAlert("You assigned <strong>$asset_count</strong> assets to location <strong>$location_name</strong>");
}
redirect();
}
if (isset($_POST['bulk_assign_asset_physical_location'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$physical_location = escapeSql($_POST['physical_location']);
// Assign Physical Location to Selected Assets
if (isset($_POST['asset_ids'])) {
// Get Selected Assets Count
$asset_count = count($_POST['asset_ids']);
foreach($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Details for Logging
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE assets SET asset_physical_location = '$physical_location' WHERE asset_id = $asset_id");
logAudit("Asset", "Edit", "$session_name set asset $asset_name to physical location $physical_location", $client_id, $asset_id);
} // End Assign Location Loop
logAudit("Asset", "Bulk Edit", "$session_name set $asset_count assets to physical location $physical_location", $client_id);
flashAlert("You moved <strong>$asset_count</strong> assets to location <strong>$physical_location</strong>");
}
redirect();
}
if (isset($_POST['bulk_transfer_client_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$new_client_id = intval($_POST['bulk_client_id']);
enforceClientAccess($new_client_id);
// Transfer selected asset to new client
if (isset($_POST['asset_ids'])) {
// Get Count
$asset_count = count($_POST['asset_ids']);
foreach($_POST['asset_ids'] as $current_asset_id) {
$current_asset_id = intval($current_asset_id);
// Get Asset details and current client ID/Name for logging
$row = mysqli_fetch_assoc(mysqli_query($mysqli,"SELECT asset_name, asset_notes, asset_client_id, client_name
FROM assets
LEFT JOIN clients ON client_id = asset_client_id
WHERE asset_id = $current_asset_id")
);
$asset_name = escapeSql($row['asset_name']);
$asset_notes = escapeSql($row['asset_notes']);
$current_client_id = intval($row['asset_client_id']);
$current_client_name = escapeSql($row['client_name']);
enforceClientAccess($current_client_id);
// Get new client name for logging
$new_client_name = escapeSql(getFieldById('clients', $new_client_id, 'client_name'));
// Create new asset
mysqli_query($mysqli, "
INSERT INTO assets (asset_type, asset_name, asset_description, asset_make, asset_model, asset_serial, asset_os, asset_status, asset_purchase_date, asset_warranty_expire, asset_install_date, asset_notes, asset_favorite)
SELECT asset_type, asset_name, asset_description, asset_make, asset_model, asset_serial, asset_os, asset_status, asset_purchase_date, asset_warranty_expire, asset_install_date, asset_notes, asset_favorite
FROM assets
WHERE asset_id = $current_asset_id
");
$new_asset_id = mysqli_insert_id($mysqli);
// Transfer all Interfaces over too
$sql_interfaces = mysqli_query($mysqli, "SELECT interface_mac, interface_name, interface_primary FROM asset_interfaces WHERE interface_asset_id = $current_asset_id");
while ($row = mysqli_fetch_assoc($sql_interfaces)) {
$interface_name = escapeSql($row['interface_name']);
$interface_mac = escapeSql($row['interface_mac']);
$interface_primary = intval($row['interface_primary']);
mysqli_query($mysqli,"INSERT INTO asset_interfaces SET interface_name = '$interface_name', interface_mac = '$interface_mac', interface_primary = $interface_primary, interface_asset_id = $new_asset_id");
}
mysqli_query($mysqli, "UPDATE assets SET asset_client_id = $new_client_id WHERE asset_id = $new_asset_id");
// Archive/log the current asset
$notes = $asset_notes . "\r\n\r\n---\r\n* " . date('Y-m-d H:i:s') . ": Transferred asset $asset_name (old asset ID: $current_asset_id) from $current_client_name to $new_client_name (new asset ID: $new_asset_id)";
mysqli_query($mysqli,"UPDATE assets SET asset_archived_at = NOW() WHERE asset_id = $current_asset_id");
// It belongs to another client now, so it is no longer in this client's rack
mysqli_query($mysqli,"DELETE FROM rack_units WHERE unit_asset_id = $current_asset_id");
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = 'Transferred', asset_history_description = '$session_name transferred $asset_name to $new_client_name', asset_history_asset_id = $current_asset_id");
// Log Archive
logAudit("Asset", "Archive", "$session_name archived asset $asset_name (via transfer)", $current_client_id, $current_asset_id);
// Log Transfer
logAudit("Asset", "Transfer", "$session_name Transferred asset $asset_name (old asset ID: $current_asset_id) from $current_client_name to $new_client_name (new asset ID: $new_asset_id)", $current_client_id, $current_asset_id);
mysqli_query($mysqli, "UPDATE assets SET asset_notes = '$notes' WHERE asset_id = $current_asset_id");
// Log the new asset
$notes = $asset_notes . "\r\n\r\n---\r\n* " . date('Y-m-d H:i:s') . ": Transferred asset $asset_name (old asset ID: $current_asset_id) from $current_client_name to $new_client_name (new asset ID: $new_asset_id)";
logAudit("Asset", "Create", "$session_name created asset $name (via transfer)", $new_client_id, $new_asset_id);
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = 'Transferred', asset_history_description = '$session_name created asset via transfer from $current_client_name', asset_history_asset_id = $new_asset_id");
logAudit("Asset", "Transfer", "$session_name Transferred asset $asset_name (old asset ID: $current_asset_id) from $current_client_name to $new_client_name (new asset ID: $new_asset_id)", $new_client_id, $new_asset_id);
mysqli_query($mysqli, "UPDATE assets SET asset_notes = '$notes' WHERE asset_id = $new_asset_id");
} // End Transfer to Client Loop
logAudit("Asset", "Bulk Transfer", "$session_name transferred $asset_count assets to $new_client_name", $new_client_id);
flashAlert("Transferred <strong>$asset_count</strong> assets to <strong>$new_client_name</strong>.");
}
redirect();
}
if (isset($_POST['bulk_assign_asset_contact'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$contact_id = intval($_POST['bulk_contact_id']);
// Get Contact name and client id for logging and Notification
$sql = mysqli_query($mysqli,"SELECT contact_name, contact_client_id FROM contacts WHERE contact_id = $contact_id");
$row = mysqli_fetch_assoc($sql);
$contact_name = escapeSql($row['contact_name']);
$client_id = intval($row['contact_client_id']);
enforceClientAccess();
// Assign Contact to Selected Assets
if (isset($_POST['asset_ids'])) {
// Only the assets of the contact's client are assigned
$asset_count = 0;
foreach($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Details for Logging
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name'] ?? '');
if (!$row || intval($row['asset_client_id']) !== $client_id) {
continue;
}
$asset_count++;
mysqli_query($mysqli,"UPDATE assets SET asset_contact_id = $contact_id WHERE asset_id = $asset_id");
logAudit("Asset", "Edit", "$session_name assigned asset $asset_name to contact $contact_name", $client_id, $asset_id);
} // End Assign Contact Loop
logAudit("Asset", "Bulk Edit", "$session_name assigned $asset_count assets to contact $contact_name", $client_id);
flashAlert("You assigned <strong>$asset_count</strong> assets to contact <strong>$contact_name</strong>");
}
redirect();
}
if (isset($_POST['bulk_edit_asset_status'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$status = escapeSql($_POST['bulk_status']);
if (isset($_POST['asset_ids'])) {
$asset_count = count($_POST['asset_ids']);
foreach($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Details for Logging
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE assets SET asset_status = '$status' WHERE asset_id = $asset_id");
logAudit("Asset", "Edit", "$session_name set status to $status on $asset_name", $client_id, $asset_id);
// Add to History
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = '$status', asset_history_description = '$session_name updated $asset_name', asset_history_asset_id = $asset_id");
}
logAudit("Asset", "Bulk Edit", "$session_name set status to $status on $asset_count assets", $client_id);
flashAlert("You set the status <strong>$status</strong> on <strong>$asset_count</strong> assets.");
}
redirect();
}
if (isset($_POST['bulk_favorite_assets'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
if (isset($_POST['asset_ids'])) {
$count = count($_POST['asset_ids']);
foreach ($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE assets SET asset_favorite = 1 WHERE asset_id = $asset_id");
logAudit("Asset", "Edit", "$session_name marked asset $asset_name a favorite", $client_id, $asset_id);
}
logAudit("Asset", "Bulk Edit", "$session_name favorited $count assets", $client_id);
flashAlert("Favorited <strong>$count</strong> asset(s)");
}
redirect();
}
if (isset($_POST['bulk_unfavorite_assets'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
if (isset($_POST['asset_ids'])) {
$count = count($_POST['asset_ids']);
foreach ($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE assets SET asset_favorite = 0 WHERE asset_id = $asset_id");
logAudit("Asset", "Edit", "$session_name unfavorited asset $asset_name", $client_id, $asset_id);
}
logAudit("Asset", "Bulk Edit", "$session_name unfavorited $count assets", $client_id);
flashAlert("Unfavorited <strong>$count</strong> asset(s)");
}
redirect();
}
if (isset($_POST['bulk_archive_assets'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
if (isset($_POST['asset_ids'])) {
$count = count($_POST['asset_ids']);
foreach ($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE assets SET asset_archived_at = NOW() WHERE asset_id = $asset_id");
logAudit("Asset", "Archive", "$session_name archived asset $asset_name", $client_id, $asset_id);
// Add to History
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = 'Archived', asset_history_description = '$session_name archived $asset_name', asset_history_asset_id = $asset_id");
}
logAudit("Asset", "Bulk Archive", "$session_name archived $count assets", $client_id);
flashAlert("Archived <strong>$count</strong> asset(s)", 'error');
}
redirect();
}
if (isset($_POST['bulk_restore_assets'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
if (isset($_POST['asset_ids'])) {
$count = count($_POST['asset_ids']);
foreach ($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"UPDATE assets SET asset_archived_at = NULL WHERE asset_id = $asset_id");
// Individual Asset logging
logAudit("Asset", "Restore", "$session_name restored asset $asset_name", $client_id, $asset_id);
// Add to History
mysqli_query($mysqli,"INSERT INTO asset_history SET asset_history_status = 'Restored', asset_history_description = '$session_name restored $asset_name', asset_history_asset_id = $asset_id");
}
logAudit("Asset", "Bulk Restore", "$session_name restored $count assets");
flashAlert("Restored $count asset(s)");
}
redirect();
}
if (isset($_POST['bulk_delete_assets'])) {
validateCSRFToken();
enforceUserPermission('module_support', 3);
if (isset($_POST['asset_ids'])) {
$count = count($_POST['asset_ids']);
foreach ($_POST['asset_ids'] as $asset_id) {
$asset_id = intval($asset_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli,"DELETE FROM assets WHERE asset_id = $asset_id");
mysqli_query($mysqli,"DELETE FROM rack_units WHERE unit_asset_id = $asset_id");
logAudit("Asset", "Delete", "$session_name deleted asset $asset_name", $client_id, $asset_id);
}
logAudit("Asset", "Bulk Delete", "$session_name deleted $count assets");
flashAlert("Deleted <strong>$count</strong> asset(s)", 'error');
}
redirect();
}
// BEGIN LINKING
// Licenses are linked in post/link.php (link_software_to_asset)
// Right now 1 login and have many assets but not many to many
if (isset($_POST['link_asset_to_credential'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$credential_id = intval($_POST['credential_id']);
$asset_id = intval($_POST['asset_id']);
// Get credential Name and Client ID for logging
$sql_credential = mysqli_query($mysqli,"SELECT credential_name, credential_client_id FROM credentials WHERE credential_id = $credential_id");
$row = mysqli_fetch_assoc($sql_credential);
$credential_name = escapeSql($row['credential_name']);
$client_id = intval($row['credential_client_id']);
enforceClientAccess();
// Get Asset Name for logging
$asset_name = escapeSql(getFieldById('assets', $asset_id, 'asset_name'));
mysqli_query($mysqli,"UPDATE credentials SET credential_asset_id = $asset_id WHERE credential_id = $credential_id");
logAudit("Credential", "Link", "$session_name linked credential $credential_name to asset $asset_name", $client_id, $credential_id);
flashAlert("Asset <strong>$asset_name</strong> linked with credential <strong>$credential_name</strong>");
redirect();
}
if (isset($_GET['unlink_credential_from_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_id = intval($_GET['asset_id']);
$credential_id = intval($_GET['credential_id']);
// Get credential Name and Client ID for logging
$sql_credential = mysqli_query($mysqli,"SELECT credential_name, credential_client_id FROM credentials WHERE credential_id = $credential_id");
$row = mysqli_fetch_assoc($sql_credential);
$credential_name = escapeSql($row['credential_name']);
$client_id = intval($row['credential_client_id']);
enforceClientAccess();
// Get Asset Name for logging
$asset_name = escapeSql(getFieldById('assets', $asset_id, 'asset_name'));
mysqli_query($mysqli,"UPDATE credentials SET credential_asset_id = 0 WHERE credential_id = $credential_id");
logAudit("Credential", "Unlink", "$session_name unlinked asset $asset_name from credential $credential_name", $client_id, $credential_id);
flashAlert("Credential <strong>$credential_name</strong> unlinked from Asset <strong>$asset_name</strong>", 'errpr');
redirect();
}
if (isset($_POST['link_service_to_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$service_id = intval($_POST['service_id']);
$asset_id = intval($_POST['asset_id']);
// Get service Name and Client ID for logging
$sql_service = mysqli_query($mysqli,"SELECT service_name, service_client_id FROM services WHERE service_id = $service_id");
$row = mysqli_fetch_assoc($sql_service);
$service_name = escapeSql($row['service_name']);
$client_id = intval($row['service_client_id']);
enforceClientAccess();
// Get Asset Name for logging
$asset_name = escapeSql(getFieldById('assets', $asset_id, 'asset_name'));
mysqli_query($mysqli,"INSERT INTO service_assets SET asset_id = $asset_id, service_id = $service_id");
logAudit("Service", "Link", "$session_name linked asset $asset_name to service $service_name", $client_id, $service_id);
flashAlert("Service <strong>$service_name</strong> linked with asset <strong>$asset_name</strong>");
redirect();
}
if (isset($_GET['unlink_service_from_asset'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_id = intval($_GET['asset_id']);
$service_id = intval($_GET['service_id']);
// Get service Name and Client ID for logging
$sql_service = mysqli_query($mysqli,"SELECT service_name, service_client_id FROM services WHERE service_id = $service_id");
$row = mysqli_fetch_assoc($sql_service);
$service_name = escapeSql($row['service_name']);
$client_id = intval($row['service_client_id']);
enforceClientAccess();
// Get Asset Name for logging
$asset_name = escapeSql(getFieldById('assets', $asset_id, 'asset_name'));
mysqli_query($mysqli,"DELETE FROM service_assets WHERE asset_id = $asset_id AND service_id = $service_id");
logAudit("Service", "Unlink", "$session_name unlinked asset $asset_name from service $service_name", $client_id, $service_id);
flashAlert("Asset <strong>$asset_name</strong> unlinked from service <strong>$service_name</strong>", 'error');
redirect();
}
// END LINKING
if (isset($_POST["import_assets_csv"])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$client_id = intval($_POST['client_id']);
enforceClientAccess();
$file_name = $_FILES["file"]["tmp_name"];
$error = false;
if (!empty($_FILES["file"]["tmp_name"])) {
$file_name = $_FILES["file"]["tmp_name"];
} else {
flashAlert("Please select a file to upload.", 'error');
redirect();
}
//Check file is CSV
$file_extension = strtolower(end(explode('.',$_FILES['file']['name'])));
$allowed_file_extensions = array('csv');
if (in_array($file_extension,$allowed_file_extensions) === false) {
$error = true;
flashAlert("Bad file extension", 'error');
}
//Check file isn't empty
elseif ($_FILES["file"]["size"] < 1) {
$error = true;
flashAlert("Bad file size (empty?)", 'error');
}
//(Else)Check column count (name, desc, type, make, model, serial, os, purchase date, assigned to, location, notes)
$f = fopen($file_name, "r");
$f_columns = fgetcsv($f, 1000, ",");
if (!$error & count($f_columns) != 12) {
$error = true;
flashAlert("Invalid column count.", 'error');
}
//Else, parse the file
if (!$error) {
$file = fopen($file_name, "r");
fgetcsv($file, 1000, ","); // Skip first line
$row_count = 0;
$duplicate_count = 0;
while(($column = fgetcsv($file, 1000, ",")) !== false) {
// Default variables (if undefined)
$description = $type = $make = $model = $serial = $os = '';
$contact_id = $location_id = 0;
$purchase_date = '0000-00-00';
$duplicate_detect = 0;
// Name
if (isset($column[0])) {
$name = escapeSql($column[0]);
if (mysqli_num_rows(mysqli_query($mysqli,"SELECT 1 FROM assets WHERE asset_name = '$name' AND asset_client_id = $client_id")) > 0) {
$duplicate_detect = 1;
}
}
// Desc
if (!empty($column[1])) {
$description = escapeSql($column[1]);
}
// Type
if (!empty($column[2])) {
$type = escapeSql($column[2]);
}
// Make
if (!empty($column[3])) {
$make = escapeSql($column[3]);
}
// Model
if (!empty($column[4])) {
$model = escapeSql($column[4]);
}
// Serial
if (!empty($column[5])) {
$serial = escapeSql($column[5]);
}
// OS
if (!empty($column[6])) {
$os = escapeSql($column[6]);
}
// Purchase date
if (!empty($column[7])) {
$purchase_date = escapeSql($column[7]);
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $purchase_date) || empty($purchase_date)) {
$purchase_date = "NULL";
} else {
$purchase_date = "'" . $purchase_date . "'";
}
}
// Assigned to (contact)
if (!empty($column[8])) {
$contact = escapeSql($column[8]);
if ($contact) {
$sql_contact = mysqli_query($mysqli,"SELECT contact_id FROM contacts WHERE contact_name = '$contact' AND contact_client_id = $client_id");
$row = mysqli_fetch_assoc($sql_contact);
$contact_id = intval($row['contact_id']);
}
}
// Location (lookup)
if (!empty($column[9])) {
$location = escapeSql($column[9]);
if ($location) {
$sql_location = mysqli_query($mysqli,"SELECT location_id FROM locations WHERE location_name = '$location' AND location_client_id = $client_id");
$row = mysqli_fetch_assoc($sql_location);
$location_id = intval($row['location_id']);
}
}
// Physical location (varchar)
if (!empty($column[10])) {
$physical_location = escapeSql($column[10]);
}
// Notes (varchar)
if (!empty($column[11])) {
$notes = escapeSql($column[11]);
}
// Check if duplicate was detected
if ($duplicate_detect == 0) {
//Add
mysqli_query($mysqli,"INSERT INTO assets SET asset_name = '$name', asset_description = '$description', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_purchase_date = $purchase_date, asset_physical_location = '$physical_location', asset_notes = '$notes', asset_contact_id = $contact_id, asset_location_id = $location_id, asset_client_id = $client_id");
$asset_id = mysqli_insert_id($mysqli);
// Add Primary Interface
mysqli_query($mysqli,"INSERT INTO asset_interfaces SET interface_name = '1', interface_primary = 1, interface_asset_id = $asset_id");
$row_count = $row_count + 1;
} else {
$duplicate_count = $duplicate_count + 1;
}
}
fclose($file);
logAudit("Asset", "Import", "$session_name imported $row_count asset(s) via CSV file", $client_id);
flashAlert("$row_count Asset(s) added, $duplicate_count duplicate(s) detected");
redirect();
}
//Check for any errors, if there are notify user and redirect
if ($error) {
redirect();
}
}
if (isset($_GET['download_assets_csv_template'])) {
$client_id = intval($_GET['download_assets_csv_template']);
//get records from database
$sql = mysqli_query($mysqli,"SELECT client_name FROM clients WHERE client_id = $client_id");
$row = mysqli_fetch_assoc($sql);
$client_name = $row['client_name'];
$delimiter = ",";
$enclosure = '"';
$escape = '\\';
$filename = toAlphanumeric($client_name) . "-Assets-Template.csv";
//create a file pointer
$f = fopen('php://memory', 'w');
//set column headers
$fields = array('Name', 'Description', 'Type', 'Make', 'Model', 'Serial', 'OS', 'Purchase Date', 'Assigned To', 'Location', 'Physical Location', 'Notes');
fputcsv($f, $fields, $delimiter, $enclosure, $escape);
//move back to beginning of file
fseek($f, 0);
//set headers to download file rather than displayed
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '";');
//output all remaining data on a file pointer
fpassthru($f);
exit;
}
if (isExportRequest('export_assets')) {
validateCSRFToken();
enforceUserPermission('module_support');
$format = resolveExportFormat($_POST['export_assets']);
// Filters inherited from the assets page - mirrors agent/assets.php
$filter_summary = [];
if (!empty($_POST['client_id'])) {
$client_id = intval($_POST['client_id']);
$client_query = "AND asset_client_id = $client_id";
$client_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT client_name FROM clients WHERE client_id = $client_id"));
$client_name = $client_row['client_name'];
$file_name_prepend = "$client_name-";
$filter_summary['Client'] = $client_name;
enforceClientAccess();
} else {
$client_query = '';
$client_id = 0; // for Logging
$file_name_prepend = "$session_company_name-";
// Client Filter
if (!empty($_POST['client'])) {
$filter_client_id = intval($_POST['client']);
$client_query = "AND (asset_client_id = $filter_client_id)";
$client_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT client_name FROM clients WHERE client_id = $filter_client_id"));
$filter_summary['Client'] = $client_row['client_name'] ?? '';
}
}
// Archived Filter
if (isset($_POST['archived']) && $_POST['archived'] == 1) {
$archive_query = $client_id ? "asset_archived_at IS NOT NULL" : "(client_archived_at IS NOT NULL OR asset_archived_at IS NOT NULL)";
$filter_summary['Archived'] = 'Archived only';
} else {
$archive_query = $client_id ? "asset_archived_at IS NULL" : "(client_archived_at IS NULL AND asset_archived_at IS NULL)";
}
// Type Filter
$type = $_POST['type'] ?? '';
if ($type == 'workstation') {
$type_query = "asset_type = 'desktop' OR asset_type = 'laptop'";
} elseif ($type == 'server') {
$type_query = "asset_type = 'server'";
} elseif ($type == 'virtual') {
$type_query = "asset_type = 'Virtual Machine'";
} elseif ($type == 'network') {
$type_query = "asset_type = 'Firewall/Router' OR asset_type = 'Switch' OR asset_type = 'Access Point'";
} elseif ($type == 'printer') {
$type_query = "asset_type = 'Printer'";
} elseif ($type == 'other') {
$type_query = "asset_type NOT LIKE 'laptop' AND asset_type NOT LIKE 'desktop' AND asset_type NOT LIKE 'server' AND asset_type NOT LIKE 'virtual machine' AND asset_type NOT LIKE 'firewall/router' AND asset_type NOT LIKE 'switch' AND asset_type NOT LIKE 'access point' AND asset_type NOT LIKE 'printer'";
} else {
// Default - any
$type = '';
$type_query = "asset_type LIKE '%'";
}
if ($type) {
$filter_summary['Type'] = ucwords($type);
}
// Location Filter
if (!empty($_POST['location'])) {
$filter_location_id = intval($_POST['location']);
$location_query = "AND (asset_location_id = $filter_location_id)";
$location_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT location_name FROM locations WHERE location_id = $filter_location_id"));
$filter_summary['Location'] = $location_row['location_name'] ?? '';
} else {
// Default - any
$location_query = '';
}
// Tags Filter
if (isset($_POST['tags']) && is_array($_POST['tags']) && !empty($_POST['tags'])) {
$tag_filter = implode(",", array_map('intval', $_POST['tags']));
$tag_query = "AND tag_id IN ($tag_filter)";
$tag_names = [];
$sql_tags = mysqli_query($mysqli, "SELECT tag_name FROM tags WHERE tag_id IN ($tag_filter) ORDER BY tag_name ASC");
while ($tag_row = mysqli_fetch_assoc($sql_tags)) {
$tag_names[] = $tag_row['tag_name'];
}
$filter_summary['Tags'] = implode(', ', $tag_names);
} else {
// Default - any
$tag_query = '';
}
// Expiring In Filter
if (!empty($_POST['expire_days'])) {
if ($_POST['expire_days'] == "expired") {
$expire_query = "AND (asset_warranty_expire IS NOT NULL AND asset_warranty_expire != '0000-00-00' AND asset_warranty_expire < CURDATE())";
$filter_summary['Warranty'] = 'Expired';
} else {
$expire_days = intval($_POST['expire_days']);
$expire_query = "AND (asset_warranty_expire IS NOT NULL AND asset_warranty_expire != '0000-00-00' AND asset_warranty_expire BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL $expire_days DAY))";
$filter_summary['Warranty'] = "Expiring within $expire_days days";
}
} else {
// Default - any
$expire_query = '';
}
// Search Filter
$q = escapeSql($_POST['q'] ?? '');
if (!empty($q)) {
$filter_summary['Search'] = $_POST['q'];
}
// Get records from database - same shape as the assets page list query
$sql = mysqli_query(
$mysqli,
"SELECT * FROM assets
LEFT JOIN clients ON asset_client_id = client_id
LEFT JOIN contacts ON asset_contact_id = contact_id
LEFT JOIN locations ON asset_location_id = location_id
LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1
LEFT JOIN asset_tags ON asset_tag_asset_id = asset_id
LEFT JOIN tags ON tag_id = asset_tag_tag_id
WHERE $archive_query
$tag_query
AND (asset_name LIKE '%$q%' OR asset_description LIKE '%$q%' OR asset_type LIKE '%$q%' OR interface_ip LIKE '%$q%' OR interface_ipv6 LIKE '%$q%' OR interface_mac LIKE '%$q%' OR asset_make LIKE '%$q%' OR asset_model LIKE '%$q%' OR asset_serial LIKE '%$q%' OR asset_os LIKE '%$q%' OR contact_name LIKE '%$q%' OR location_name LIKE '%$q%' OR client_name LIKE '%$q%' OR tag_name LIKE '%$q%')
AND ($type_query)
" . clientScopeSql('asset_client_id') . "
$location_query
$expire_query
$client_query
GROUP BY asset_id
ORDER BY asset_name ASC"
);
$num_rows = mysqli_num_rows($sql);
if ($num_rows > 0) {
guardExportPdfRowCount($format, $num_rows);
$export = beginExport('assets', $format, $file_name_prepend . 'Assets', 'Assets', summarizeExportFilters($filter_summary));
while ($row = mysqli_fetch_assoc($sql)) {
addExportRow($export, $row);
}
finishExport($export);
}
logAudit("Asset", "Export", "$session_name exported $num_rows asset(s) to a " . strtoupper($format) . " file", $client_id);
exit;
}
if (isset($_POST['add_asset_interface'])) {
// 1) Permissions & CSRF
validateCSRFToken();
enforceUserPermission('module_support', 2);
// 2) Gather posted values
$interface_id = intval($_POST['interface_id']);
$asset_id = intval($_POST['asset_id']);
// Defines $name, $mac, $ip, $ipv6, $port, $notes, $network, $connected_to, etc.
require_once 'asset_interface_model.php';
// 3) Fetch asset info for logging and alert
$sql = mysqli_query($mysqli, "
SELECT asset_name, asset_client_id
FROM assets
WHERE asset_id = $asset_id
");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
// 4) Insert new interface into asset_interfaces (using SET syntax)
$sql_insert = "
INSERT INTO asset_interfaces SET
interface_name = '$name',
interface_description= '$description',
interface_type = '$type',
interface_mac = '$mac',
interface_ip = '$ip',
interface_nat_ip = '$nat_ip',
interface_ipv6 = '$ipv6',
interface_notes = '$notes',
interface_network_id = $network,
interface_asset_id = $asset_id
";
mysqli_query($mysqli, $sql_insert);
$new_interface_id = mysqli_insert_id($mysqli);
// If Primary Interface Checked set all interfaces primary to 0 then set the new interface as primary with a 1
if ($primary_interface) {
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_primary = 0 WHERE interface_asset_id = $asset_id");
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_primary = 1 WHERE interface_id = $new_interface_id");
}
// 5) If user selected a connected interface, insert row in asset_interface_links
if (!empty($connected_to) && intval($connected_to) > 0) {
$sql_link = "
INSERT INTO asset_interface_links SET
interface_a_id = $new_interface_id,
interface_b_id = $connected_to
";
mysqli_query($mysqli, $sql_link);
}
// 6) Logging
logAudit(
"Asset Interface",
"Create",
"$session_name created interface $name for asset $asset_name",
$client_id,
$asset_id
);
// 7) Alert message + redirect
flashAlert("Interface <strong>$name</strong> created");
redirect();
}
if (isset($_POST['add_asset_multiple_interfaces'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_id = intval($_POST['asset_id']);
$interface_start = intval($_POST['interface_start']);
$interfaces = intval($_POST['interfaces']);
$type = escapeSql($_POST['type']);
$name_prefix = escapeSql($_POST['name_prefix']);
$network = intval($_POST['network']);
$notes = escapeSql($_POST['notes']);
$sql = mysqli_query($mysqli, "SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
for ($interface_number = $interface_start; $interface_number < $interface_start + $interfaces; $interface_number++) {
// Format $interface_number as a 2-digit number
$formatted_interface_number = str_pad($interface_number, 2, '0', STR_PAD_LEFT);
$sql_insert = "
INSERT INTO asset_interfaces SET
interface_name = '$name_prefix$formatted_interface_number',
interface_type = '$type',
interface_notes = '$notes',
interface_network_id = $network,
interface_asset_id = $asset_id
";
mysqli_query($mysqli, $sql_insert);
logAudit("Asset Interface", "Create", "$session_name created interface $name for asset $asset_name", $client_id, $asset_id);
}
logAudit("Asset Interface", "Bulk Create", "$session_name created $interfaces for asset $asset_name", $client_id, $asset_id);
flashAlert("Created <strong>$interfaces</strong> Interface(s) for asset <strong>$asset_name</strong>");
redirect();
}
if (isset($_POST['edit_asset_interface'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
// Interface info
$interface_id = intval($_POST['interface_id']);
require_once 'asset_interface_model.php';
// sets: $name, $mac, $ip, $ipv6, $port, $notes, $network, $connected_to, etc.
// 1) Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli, "
SELECT asset_name, asset_client_id, asset_id
FROM asset_interfaces
LEFT JOIN assets ON asset_id = interface_asset_id
WHERE interface_id = $interface_id
");
$row = mysqli_fetch_assoc($sql);
$asset_id = intval($row['asset_id']);
$asset_name= escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
// 2) Update the interface details in asset_interfaces
$sql_update = "
UPDATE asset_interfaces SET
interface_name = '$name',
interface_description= '$description',
interface_type = '$type',
interface_mac = '$mac',
interface_ip = '$ip',
interface_nat_ip = '$nat_ip',
interface_ipv6 = '$ipv6',
interface_notes = '$notes',
interface_network_id = $network
WHERE interface_id = $interface_id
";
mysqli_query($mysqli, $sql_update);
// If Primary Interface Checked set all interfaces primary to 0 then set the new interface as primary with a 1
if ($primary_interface) {
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_primary = 0 WHERE interface_asset_id = $asset_id");
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_primary = 1 WHERE interface_id = $interface_id");
}
// 3) Remove any existing link for this interface (one-to-one)
$sql_delete_link = "
DELETE FROM asset_interface_links
WHERE interface_a_id = $interface_id
OR interface_b_id = $interface_id
";
mysqli_query($mysqli, $sql_delete_link);
// 4) If user selected a connected interface, create a new link
if (!empty($connected_to) && intval($connected_to) > 0) {
$sql_link = "
INSERT INTO asset_interface_links SET
interface_a_id = $interface_id,
interface_b_id = $connected_to
";
mysqli_query($mysqli, $sql_link);
}
// 5) Logging
logAudit(
"Asset Interface",
"Edit",
"$session_name edited interface $name for asset $asset_name",
$client_id,
$asset_id
);
// 6) Alert and redirect
flashAlert("Interface <strong>$name</strong> edited");
redirect();
}
if (isset($_GET['delete_asset_interface'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$interface_id = intval($_GET['delete_asset_interface']);
// 1) Fetch details for logging / alerts
$sql = mysqli_query($mysqli, "
SELECT asset_name, interface_name, asset_client_id, asset_id
FROM asset_interfaces
LEFT JOIN assets ON asset_id = interface_asset_id
WHERE interface_id = $interface_id
");
$row = mysqli_fetch_assoc($sql);
$asset_id = intval($row['asset_id']);
$interface_name = escapeSql($row['interface_name']);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
// 2) Delete the interface this cascadingly delete asset_interface_links
mysqli_query($mysqli, "
DELETE FROM asset_interfaces
WHERE interface_id = $interface_id
");
// 3) Logging
logAudit(
"Asset Interface",
"Delete",
"$session_name deleted interface $interface_name from asset $asset_name",
$client_id,
$asset_id
);
// 4) Alert and redirect
flashAlert("Interface <strong>$interface_name</strong> deleted", 'error');
redirect();
}
if (isset($_POST['bulk_edit_asset_interface_type'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$type = escapeSql($_POST['bulk_type']);
if (isset($_POST['interface_ids'])) {
// Get Count
$interface_count = count($_POST['interface_ids']);
foreach($_POST['interface_ids'] as $interface_id) {
$interface_id = intval($interface_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli, "
SELECT asset_name, asset_client_id, asset_id
FROM asset_interfaces
LEFT JOIN assets ON asset_id = interface_asset_id
WHERE interface_id = $interface_id
");
$row = mysqli_fetch_assoc($sql);
$asset_id = intval($row['asset_id']);
$asset_name= escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
// Update inteface type
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_type = '$type' WHERE interface_id = $interface_id");
logAudit("Asset Interface", "Edit", "$session_name set interface type to $type for asset $asset_name", $client_id, $asset_id);
}
logAudit("Asset Interface", "Bulk Edit", "$session_name set interface type to $type on $interface_count interfaces for asset $asset_name", $client_id);
flashAlert("Type set to <strong>$type</strong> on <strong>$interface_count</strong> interfaces.");
}
redirect();
}
if (isset($_POST['bulk_edit_asset_interface_network'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$network_id = intval($_POST['bulk_network']);
// Get Network Name for logging
$network_name = escapeSql(getFieldById('networks', $network_id, 'network_name'));
if (isset($_POST['interface_ids'])) {
// Get Count
$interface_count = count($_POST['interface_ids']);
foreach($_POST['interface_ids'] as $interface_id) {
$interface_id = intval($interface_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli, "
SELECT asset_name, asset_client_id, asset_id
FROM asset_interfaces
LEFT JOIN assets ON asset_id = interface_asset_id
WHERE interface_id = $interface_id
");
$row = mysqli_fetch_assoc($sql);
$asset_id = intval($row['asset_id']);
$asset_name= escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
// Update inteface type
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_network_id = $network_id WHERE interface_id = $interface_id");
logAudit("Asset Interface", "Edit", "$session_name set network to $network_name for asset $asset_name", $client_id, $asset_id);
}
logAudit("Asset Interface", "Bulk Edit", "$session_name set network to $network_name on $interface_count interfaces for asset $asset_name", $client_id);
flashAlert("Network set to <strong>$network_name</strong> on <strong>$interface_count</strong> interfaces.");
}
redirect();
}
if (isset($_POST['bulk_edit_asset_interface_ip_dhcp'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
if (isset($_POST['interface_ids'])) {
// Get Count
$interface_count = count($_POST['interface_ids']);
foreach($_POST['interface_ids'] as $interface_id) {
$interface_id = intval($interface_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli, "
SELECT asset_name, asset_client_id, asset_id
FROM asset_interfaces
LEFT JOIN assets ON asset_id = interface_asset_id
WHERE interface_id = $interface_id
");
$row = mysqli_fetch_assoc($sql);
$asset_id = intval($row['asset_id']);
$asset_name= escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
// Update inteface type
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_ip = 'DHCP' WHERE interface_id = $interface_id");
logAudit("Asset Interface", "Edit", "$session_name set interface IP to DHCP for asset $asset_name", $client_id, $asset_id);
}
logAudit("Asset Interface", "Bulk Edit", "$session_name set interface IP to DHCP on $interface_count interfaces for asset $asset_name", $client_id);
flashAlert("Interface IP set to <strong>DHCP</strong> on <strong>$interface_count</strong> interfaces.");
}
redirect();
}
if (isset($_POST['bulk_delete_asset_interfaces'])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
if (isset($_POST['interface_ids'])) {
// Get Count
$interface_count = count($_POST['interface_ids']);
foreach($_POST['interface_ids'] as $interface_id) {
$interface_id = intval($interface_id);
// Get Asset Name and Client ID for logging and alert message
$sql = mysqli_query($mysqli, "
SELECT asset_name, interface_name, asset_client_id, asset_id
FROM asset_interfaces
LEFT JOIN assets ON asset_id = interface_asset_id
WHERE interface_id = $interface_id
");
$row = mysqli_fetch_assoc($sql);
$asset_id = intval($row['asset_id']);
$interface_name = escapeSql($row['interface_name']);
$asset_name = escapeSql($row['asset_name']);
$client_id = intval($row['asset_client_id']);
enforceClientAccess();
mysqli_query($mysqli, "DELETE FROM asset_interfaces WHERE interface_id = $interface_id");
logAudit("Asset Interface", "Delete", "$session_name deleted interface $interface_name from asset $asset_name", $client_id, $asset_id);
}
logAudit("Asset Interface", "Bulk Delete", "$session_name deleted $interface_count interfaces for asset $asset_name", $client_id);
flashAlert("<strong>$interface_count</strong> interfaces deleted.", 'error');
}
redirect();
}
if (isset($_POST["import_client_asset_interfaces_csv"])) {
validateCSRFToken();
enforceUserPermission('module_support', 2);
$asset_id = intval($_POST['asset_id']);
$file_name = $_FILES["file"]["tmp_name"];
// Get Asset Details for logging
$sql_asset = mysqli_query($mysqli,"SELECT asset_client_id, asset_name FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql_asset);
$client_id = intval($row['asset_client_id']);
$asset_name = escapeSql($row['asset_name']);
enforceClientAccess();
$error = false;
if (!empty($_FILES["file"]["tmp_name"])) {
$file_name = $_FILES["file"]["tmp_name"];
} else {
flashAlert("Please select a file to upload.", 'error');
redirect();
}
//Check file is CSV
$file_extension = strtolower(end(explode('.',$_FILES['file']['name'])));
$allowed_file_extensions = array('csv');
if (in_array($file_extension,$allowed_file_extensions) === false) {
$error = true;
flashAlert("Bad file extension", 'error');
}
//Check file isn't empty
elseif ($_FILES["file"]["size"] < 1) {
$error = true;
flashAlert("Bad file size (empty?)", 'error');
}
//(Else)Check column count (Name, Description, Type, MAC, IP, NAT IP, IPv6, Network)
$f = fopen($file_name, "r");
$f_columns = fgetcsv($f, 1000, ",");
if (!$error & count($f_columns) != 8) {
$error = true;
flashAlert("Bad column count.", 'error');
}
//Else, parse the file
if (!$error) {
$file = fopen($file_name, "r");
fgetcsv($file, 1000, ","); // Skip first line
$row_count = 0;
$duplicate_count = 0;
while(($column = fgetcsv($file, 1000, ",")) !== false) {
// Default variables (if undefined)
$description = $type = $mac = $ip = $nat_ip = $ipv6 = $network = '';
$network_id = 0;
$duplicate_detect = 0;
if (isset($column[0])) {
$name = escapeSql($column[0]);
if (mysqli_num_rows(mysqli_query($mysqli,"SELECT interface_name FROM asset_interfaces WHERE interface_asset_id = $asset_id AND interface_name = '$name'")) > 0) {
$duplicate_detect = 1;
}
}
if (!empty($column[1])) {
$description = escapeSql($column[1]);
}
if (!empty($column[2])) {
$type = escapeSql($column[2]);
}
if (!empty($column[3])) {
$mac = escapeSql($column[3]);
}
if (!empty($column[4])) {
$ip = escapeSql($column[4]);
}
if (!empty($column[5])) {
$nat_ip = escapeSql($column[5]);
}
if (!empty($column[6])) {
$ipv6 = escapeSql($column[6]);
}
if (!empty($column[7])) {
$network = escapeSql($column[7]);
if ($network) {
$sql_network = mysqli_query($mysqli,"SELECT network_id FROM networks WHERE network_name = '$network' AND network_archived_at IS NULL AND network_client_id = $client_id");
$row = mysqli_fetch_assoc($sql_network);
$network_id = intval($row['network_id']);
}
}
// Check if duplicate was detected
if ($duplicate_detect == 0) {
//Add
mysqli_query($mysqli,"INSERT INTO asset_interfaces SET interface_name = '$name', interface_description = '$description', interface_type = '$type', interface_mac = '$mac', interface_ip = '$ip', interface_nat_ip = '$nat_ip', interface_ipv6 = '$ipv6', interface_network_id = $network_id, interface_asset_id = $asset_id");
$row_count = $row_count + 1;
} else {
$duplicate_count = $duplicate_count + 1;
}
}
fclose($file);
logAudit("Asset", "Import", "$session_name imported $row_count interfaces(s) to asset $asset_name via CSV file", $client_id);
flashAlert("<strong>$row_count</strong> Interfaces(s) added to asset <strong>$asset_name</strong>, <strong>$duplicate_count</strong> duplicate(s) detected");
redirect();
}
//Check for any errors, if there are notify user and redirect
if ($error) {
redirect();
}
}
if (isset($_GET['download_client_asset_interfaces_csv_template'])) {
$asset_id = intval($_GET['download_client_asset_interfaces_csv_template']);
//get records from database
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id FROM assets WHERE asset_id = $asset_id");
$row = mysqli_fetch_assoc($sql);
$asset_name = $row['asset_name'];
$delimiter = ",";
$enclosure = '"';
$escape = '\\';
$filename = toAlphanumeric($asset_name) . "-Asset-Interfaces-Template.csv";
//create a file pointer
$f = fopen('php://memory', 'w');
//set column headers
$fields = array('Name', 'Description', 'Type', 'MAC', 'IP', 'NAT IP', 'IPv6', 'Network');
fputcsv($f, $fields, $delimiter, $enclosure, $escape);
//move back to beginning of file
fseek($f, 0);
//set headers to download file rather than displayed
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '";');
//output all remaining data on a file pointer
fpassthru($f);
exit;
}
if (isExportRequest('export_asset_interfaces')) {
validateCSRFToken();
enforceUserPermission('module_support');
$format = resolveExportFormat($_POST['export_asset_interfaces']);
$asset_id = intval($_POST['asset_id']);
$client_id = intval(getFieldById('assets', $asset_id, 'asset_client_id'));
enforceClientAccess();
$asset_name = getFieldById('assets', $asset_id, 'asset_name');
// Get records from database - scoped to the one asset, so no page filters apply
$sql = mysqli_query(
$mysqli,
"SELECT * FROM asset_interfaces
LEFT JOIN assets ON asset_id = interface_asset_id
LEFT JOIN networks ON interface_network_id = network_id
LEFT JOIN clients ON asset_client_id = client_id
WHERE asset_id = $asset_id
AND interface_archived_at IS NULL
ORDER BY interface_name ASC"
);
$num_rows = mysqli_num_rows($sql);
if ($num_rows > 0) {
guardExportPdfRowCount($format, $num_rows);
$export = beginExport('asset_interfaces', $format, toAlphanumeric($asset_name) . '-Interfaces', "$asset_name - Interfaces", '');
while ($row = mysqli_fetch_assoc($sql)) {
addExportRow($export, $row);
}
finishExport($export);
}
logAudit("Asset Interface", "Export", "$session_name exported $num_rows interface(s) to a " . strtoupper($format) . " file", $client_id);
exit;
}