Apply further gating to client pdf export

This commit is contained in:
johnnyq
2026-08-06 19:03:47 -04:00
parent 64423cbefa
commit 942fe41b18
4 changed files with 155 additions and 232 deletions

View File

@@ -31,7 +31,7 @@
</a>
<?php } ?>
<?php } ?>
<?php if (lookupUserPermission("module_client") >= 3) { ?>
<?php if (lookupUserPermission("module_client") >= 1) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#exportClientPDFModal">
<i class="fas fa-fw fa-file-pdf mr-2"></i>Export Data

View File

@@ -12,168 +12,7 @@
<input type="hidden" name="client_id" value="<?= $client_id ?>">
<div class="modal-body">
<ul class="list-group">
<div class="row">
<div class="col-sm-6">
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="contacts" name="include_contacts" value="1" checked>
<label for="contacts" class="custom-control-label">
<i class='fas fa-fw fa-users mr-2'></i>Contacts
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="locations" name="include_locations" value="1" checked>
<label for="locations" class="custom-control-label">
<i class='fas fa-fw fa-map-marker-alt mr-2'></i>Locations
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="assets" name="include_assets" value="1" checked>
<label for="assets" class="custom-control-label">
<i class='fas fa-fw fa-desktop mr-2'></i>Assets
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="software" name="include_software" value="1" checked>
<label for="software" class="custom-control-label">
<i class='fas fa-fw fa-cube mr-2'></i>Software / Licenses
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="credentials" name="include_credentials" value="1">
<label for="credentials" class="custom-control-label">
<i class='fas fa-fw fa-key mr-2'></i>Credentials
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="networks" name="include_networks" value="1" checked>
<label for="networks" class="custom-control-label">
<i class='fas fa-fw fa-network-wired mr-2'></i>Networks
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="certificates" name="include_certificates" value="1" checked>
<label for="certificates" class="custom-control-label">
<i class='fas fa-fw fa-lock mr-2'></i>Certificates
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="domains" name="include_domains" value="1" checked>
<label for="domains" class="custom-control-label">
<i class='fas fa-fw fa-globe mr-2'></i>Domains
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="tickets" name="include_tickets" value="1" checked>
<label for="tickets" class="custom-control-label">
<i class='fas fa-fw fa-life-ring mr-2'></i>Tickets
</label>
</div>
</li>
</div>
<div class="col-sm-6">
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="recurring_tickets" name="include_recurring_tickets" value="1" checked>
<label for="recurring_tickets" class="custom-control-label">
<i class='fas fa-fw fa-clock mr-2'></i>Recurring Tickets
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="vendors" name="include_vendors" value="1" checked>
<label for="vendors" class="custom-control-label">
<i class='fas fa-fw fa-building mr-2'></i>Vendors
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="invoices" name="include_invoices" value="1" checked>
<label for="invoices" class="custom-control-label">
<i class='fas fa-fw fa-file-invoice mr-2'></i>Invoices
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="recurring_invoices" name="include_recurring_invoices" value="1" checked>
<label for="recurring_invoices" class="custom-control-label">
<i class='fas fa-fw fa-sync mr-2'></i>Recurring Invoices
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="quotes" name="include_quotes" value="1" checked>
<label for="quotes" class="custom-control-label">
<i class='fas fa-fw fa-file mr-2'></i>Quotes
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="payments" name="include_payments" value="1" checked>
<label for="payments" class="custom-control-label">
<i class='fas fa-fw fa-credit-card mr-2'></i>Payments
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="trips" name="include_trips" value="1" checked>
<label for="trips" class="custom-control-label">
<i class='fas fa-fw fa-route mr-2'></i>Trips
</label>
</div>
</li>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="logs" name="include_logs" value="1" checked>
<label for="logs" class="custom-control-label">
<i class='fas fa-fw fa-eye mr-2'></i>Audit Log
</label>
</div>
</li>
</div>
</div>
<?php renderClientPackSections(); ?>
</ul>
</div>
<div class="modal-footer">

View File

@@ -1175,11 +1175,15 @@ if (isset($_POST["export_client_pdf"])) {
validateCSRFToken();
// Enforce permissions
enforceUserPermission("module_client", 3);
enforceUserPermission("module_support", 1);
enforceUserPermission("module_sales", 1);
enforceUserPermission("module_financial", 1);
// The pack always carries the client's own record, so client read is the floor.
// Everything past that is gated per section in resolveClientPackSections() - a
// role missing one module loses that section, not the whole export.
enforceUserPermission('module_client');
$client_id = intval($_POST["client_id"]);
enforceClientAccess();
$pack = resolveClientPackSections();
$sql = mysqli_query($mysqli, "SELECT company_email, company_logo, company_name, company_phone, company_phone_country_code,
company_website FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1");
@@ -1191,30 +1195,6 @@ if (isset($_POST["export_client_pdf"])) {
$company_website = escapeHtml($row['company_website']);
$company_logo = escapeHtml($row['company_logo']);
$client_id = intval($_POST["client_id"]);
$export_contacts = intval($_POST["include_contacts"] ?? 0);
$export_locations = intval($_POST["include_locations"] ?? 0);
$export_assets = intval($_POST["include_assets"] ?? 0);
$export_software = intval($_POST["include_software"] ?? 0);
$export_credentials = 0;
if (lookupUserPermission("module_credential") >= 1) {
$export_credentials = intval($_POST["include_credentials"] ?? 0);
}
$export_networks = intval($_POST["include_networks"] ?? 0);
$export_certificates = intval($_POST["include_certificates"] ?? 0);
$export_domains = intval($_POST["include_domains"] ?? 0);
$export_tickets = intval($_POST["include_tickets"] ?? 0);
$export_recurring_tickets = intval($_POST["include_recurring_tickets"] ?? 0);
$export_vendors = intval($_POST["include_vendors"] ?? 0);
$export_invoices = intval($_POST["include_invoices"] ?? 0);
$export_recurring_invoices = intval($_POST["include_recurring_invoices"] ?? 0);
$export_quotes = intval($_POST["include_quotes"] ?? 0);
$export_payments = intval($_POST["include_payments"] ?? 0);
$export_trips = intval($_POST["include_trips"] ?? 0);
$export_logs = intval($_POST["include_logs"] ?? 0);
enforceClientAccess();
logAudit("Client", "Export", "$session_name exported client data to a PDF file", $client_id, $client_id);
// Get client record (joining primary contact and primary location)
@@ -1241,19 +1221,19 @@ if (isset($_POST["export_client_pdf"])) {
$client_website = escapeHtml($row["client_website"]);
// Other queries remain unchanged
$sql_contacts = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_client_id = $client_id AND contact_archived_at IS NULL ORDER BY contact_name ASC");
$sql_locations = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_client_id = $client_id AND location_archived_at IS NULL ORDER BY location_name ASC");
$sql_vendors = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_client_id = $client_id AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
$sql_credentials = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_client_id = $client_id ORDER BY credential_name ASC");
$sql_assets = mysqli_query($mysqli, "SELECT 1 FROM assets
$sql_contacts = $pack['contacts'] ? mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_client_id = $client_id AND contact_archived_at IS NULL ORDER BY contact_name ASC") : false;
$sql_locations = $pack['locations'] ? mysqli_query($mysqli, "SELECT * FROM locations WHERE location_client_id = $client_id AND location_archived_at IS NULL ORDER BY location_name ASC") : false;
$sql_vendors = $pack['vendors'] ? mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_client_id = $client_id AND vendor_archived_at IS NULL ORDER BY vendor_name ASC") : false;
$sql_credentials = $pack['credentials'] ? mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_client_id = $client_id ORDER BY credential_name ASC") : false;
$sql_assets = $pack['assets'] ? mysqli_query($mysqli, "SELECT 1 FROM assets
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
WHERE asset_client_id = $client_id
AND asset_archived_at IS NULL
ORDER BY asset_type ASC"
);
$sql_asset_workstations = mysqli_query($mysqli, "SELECT * FROM assets
) : false;
$sql_asset_workstations = $pack['assets'] ? mysqli_query($mysqli, "SELECT * FROM assets
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
@@ -1261,31 +1241,31 @@ if (isset($_POST["export_client_pdf"])) {
AND (asset_type = 'desktop' OR asset_type = 'laptop')
AND asset_archived_at IS NULL
ORDER BY asset_name ASC"
);
$sql_asset_servers = mysqli_query($mysqli, "SELECT * FROM assets
) : false;
$sql_asset_servers = $pack['assets'] ? mysqli_query($mysqli, "SELECT * FROM assets
LEFT JOIN locations ON asset_location_id = location_id
LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1
WHERE asset_client_id = $client_id
AND asset_type = 'server'
AND asset_archived_at IS NULL
ORDER BY asset_name ASC"
);
$sql_asset_vms = mysqli_query($mysqli, "SELECT * FROM assets
) : false;
$sql_asset_vms = $pack['assets'] ? mysqli_query($mysqli, "SELECT * FROM assets
LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1
WHERE asset_client_id = $client_id
AND asset_type = 'virtual machine'
AND asset_archived_at IS NULL
ORDER BY asset_name ASC"
);
$sql_asset_network = mysqli_query($mysqli, "SELECT * FROM assets
) : false;
$sql_asset_network = $pack['assets'] ? mysqli_query($mysqli, "SELECT * FROM assets
LEFT JOIN locations ON asset_location_id = location_id
LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1
WHERE asset_client_id = $client_id
AND (asset_type = 'Firewall/Router' OR asset_type = 'Switch' OR asset_type = 'Access Point')
AND asset_archived_at IS NULL
ORDER BY asset_type ASC"
);
$sql_asset_other = mysqli_query($mysqli, "SELECT * FROM assets
) : false;
$sql_asset_other = $pack['assets'] ? mysqli_query($mysqli, "SELECT * FROM assets
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
@@ -1293,13 +1273,13 @@ if (isset($_POST["export_client_pdf"])) {
AND (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_archived_at IS NULL
ORDER BY asset_type ASC"
);
$sql_networks = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_client_id = $client_id AND network_archived_at IS NULL ORDER BY network_name ASC");
$sql_domains = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_client_id = $client_id AND domain_archived_at IS NULL ORDER BY domain_name ASC");
$sql_certficates = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_client_id = $client_id AND certificate_archived_at IS NULL ORDER BY certificate_name ASC");
$sql_software = mysqli_query($mysqli, "SELECT * FROM software WHERE software_client_id = $client_id AND software_archived_at IS NULL ORDER BY software_name ASC");
) : false;
$sql_networks = $pack['networks'] ? mysqli_query($mysqli, "SELECT * FROM networks WHERE network_client_id = $client_id AND network_archived_at IS NULL ORDER BY network_name ASC") : false;
$sql_domains = $pack['domains'] ? mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_client_id = $client_id AND domain_archived_at IS NULL ORDER BY domain_name ASC") : false;
$sql_certficates = $pack['certificates'] ? mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_client_id = $client_id AND certificate_archived_at IS NULL ORDER BY certificate_name ASC") : false;
$sql_software = $pack['software'] ? mysqli_query($mysqli, "SELECT * FROM software WHERE software_client_id = $client_id AND software_archived_at IS NULL ORDER BY software_name ASC") : false;
$sql_user_licenses = mysqli_query($mysqli, "
$sql_user_licenses = $pack['software'] ? mysqli_query($mysqli, "
SELECT
contact_name,
software_name
@@ -1315,9 +1295,9 @@ if (isset($_POST["export_client_pdf"])) {
AND contact_client_id = $client_id
ORDER BY
contact_name, software_name;"
);
) : false;
$sql_asset_licenses = mysqli_query($mysqli, "
$sql_asset_licenses = $pack['software'] ? mysqli_query($mysqli, "
SELECT
asset_name,
software_name
@@ -1333,7 +1313,7 @@ if (isset($_POST["export_client_pdf"])) {
AND asset_client_id = $client_id
ORDER BY
asset_name, software_name;"
);
) : false;
require_once("../libs/TCPDF/tcpdf.php");
@@ -1426,7 +1406,7 @@ if (isset($_POST["export_client_pdf"])) {
// Add bookmarks and TOC entries for each major section:
// Contacts Section
if (mysqli_num_rows($sql_contacts) > 0 && $export_contacts == 1) {
if ($pack['contacts'] == 1 && mysqli_num_rows($sql_contacts) > 0) {
$pdf->Bookmark("Contacts", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Contacts</h2>
@@ -1471,7 +1451,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Locations Section
if (mysqli_num_rows($sql_locations) > 0 && $export_locations == 1) {
if ($pack['locations'] == 1 && mysqli_num_rows($sql_locations) > 0) {
$pdf->Bookmark("Locations", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Locations</h2>
@@ -1506,7 +1486,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Vendors Section
if (mysqli_num_rows($sql_vendors) > 0 && $export_vendors == 1) {
if ($pack['vendors'] == 1 && mysqli_num_rows($sql_vendors) > 0) {
$pdf->Bookmark("Vendors", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Vendors</h2>
@@ -1543,7 +1523,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Credentials Section
if (mysqli_num_rows($sql_credentials) > 0 && $export_credentials == 1) {
if ($pack['credentials'] == 1 && mysqli_num_rows($sql_credentials) > 0) {
$pdf->Bookmark("Credentials", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Credentials</h2>
@@ -1582,14 +1562,14 @@ if (isset($_POST["export_client_pdf"])) {
}
// Assets Section Header
if (mysqli_num_rows($sql_assets) > 0 && $export_assets == 1) {
if ($pack['assets'] == 1 && mysqli_num_rows($sql_assets) > 0) {
$pdf->Bookmark("Assets", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Assets</h2>";
}
// Workstations
if (mysqli_num_rows($sql_asset_workstations) > 0 && $export_assets == 1) {
if ($pack['assets'] == 1 && mysqli_num_rows($sql_asset_workstations) > 0) {
$pdf->Bookmark("Workstations", 1, 0, "", "", array(0,0,0));
$html .= "
<h3 class='subsection-title'>Workstations</h3>
@@ -1641,7 +1621,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Servers
if (mysqli_num_rows($sql_asset_servers) > 0 && $export_assets == 1) {
if ($pack['assets'] == 1 && mysqli_num_rows($sql_asset_servers) > 0) {
$pdf->Bookmark("Servers", 1, 0, "", "", array(0,0,0));
$html .= "
<h3 class='subsection-title'>Servers</h3>
@@ -1690,7 +1670,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Virtual Machines
if (mysqli_num_rows($sql_asset_vms) > 0 && $export_assets == 1) {
if ($pack['assets'] == 1 && mysqli_num_rows($sql_asset_vms) > 0) {
$pdf->Bookmark("Virtual Machines", 1, 0, "", "", array(0,0,0));
$html .= "
<h3 class='subsection-title'>Virtual Machines</h3>
@@ -1723,7 +1703,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Network Devices
if (mysqli_num_rows($sql_asset_network) > 0 && $export_assets == 1) {
if ($pack['assets'] == 1 && mysqli_num_rows($sql_asset_network) > 0) {
$pdf->Bookmark("Network Devices", 1, 0, "", "", array(0,0,0));
$html .= "
<h3 class='subsection-title'>Network Devices</h3>
@@ -1772,7 +1752,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Other Devices
if (mysqli_num_rows($sql_asset_other) > 0 && $export_assets == 1) {
if ($pack['assets'] == 1 && mysqli_num_rows($sql_asset_other) > 0) {
$pdf->Bookmark("Other Devices", 1, 0, "", "", array(0,0,0));
$html .= "
<h3 class='subsection-title'>Other Devices</h3>
@@ -1821,7 +1801,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Software Section
if (mysqli_num_rows($sql_software) > 0 && $export_software == 1) {
if ($pack['software'] == 1 && mysqli_num_rows($sql_software) > 0) {
$pdf->Bookmark("Software", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Software</h2>
@@ -1863,7 +1843,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// User Assigned Software Licenses
if (mysqli_num_rows($sql_user_licenses) > 0 && $export_software == 1) {
if ($pack['software'] == 1 && mysqli_num_rows($sql_user_licenses) > 0) {
$pdf->Bookmark("User Assigned Licenses", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>User Assigned Licenses</h2>
@@ -1890,7 +1870,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Asset Assigned Software Licenses
if (mysqli_num_rows($sql_asset_licenses) > 0 && $export_software == 1) {
if ($pack['software'] == 1 && mysqli_num_rows($sql_asset_licenses) > 0) {
$pdf->Bookmark("Asset Assigned Licenses", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Asset Assigned Licenses</h2>
@@ -1917,7 +1897,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Networks Section
if (mysqli_num_rows($sql_networks) > 0 && $export_networks == 1) {
if ($pack['networks'] == 1 && mysqli_num_rows($sql_networks) > 0) {
$pdf->Bookmark("Networks", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Networks</h2>
@@ -1953,7 +1933,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Domains Section
if (mysqli_num_rows($sql_domains) > 0 && $export_domains == 1) {
if ($pack['domains'] == 1 && mysqli_num_rows($sql_domains) > 0) {
$pdf->Bookmark("Domains", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Domains</h2>
@@ -1980,7 +1960,7 @@ if (isset($_POST["export_client_pdf"])) {
}
// Certificates Section
if (mysqli_num_rows($sql_certficates) > 0 && $export_certificates == 1) {
if ($pack['certificates'] == 1 && mysqli_num_rows($sql_certficates) > 0) {
$pdf->Bookmark("Certificates", 0, 0, "", "B", array(0,0,0));
$html .= "
<h2 class='section-title'>Certificates</h2>

View File

@@ -808,3 +808,107 @@ function finishExport(&$export) {
return $export['rows'];
}
/*
* ---------------------------------------------------------------------------
* Client PDF pack
* ---------------------------------------------------------------------------
*
* The sections the client "Export Data" PDF can contain, in document order.
*
* 'label' Checkbox label in the export modal.
* 'icon' Font Awesome class shown beside it.
* 'module' Permission module that owns the section - same mapping the list
* exports use. A role without read access to it never sees the
* checkbox and never gets the section, so one missing module drops a
* section rather than refusing the whole export.
* 'default' Whether the box starts ticked.
*
* The modal renders from this and the handler resolves from it, so a section
* can't be offered by one and ignored by the other.
*/
function getClientPackSections() {
return [
'contacts' => ['label' => 'Contacts', 'icon' => 'fa-users', 'module' => 'module_client', 'default' => true],
'locations' => ['label' => 'Locations', 'icon' => 'fa-map-marker-alt', 'module' => 'module_client', 'default' => true],
'vendors' => ['label' => 'Vendors', 'icon' => 'fa-building', 'module' => 'module_client', 'default' => true],
'credentials' => ['label' => 'Credentials', 'icon' => 'fa-key', 'module' => 'module_credential', 'default' => false],
'assets' => ['label' => 'Assets', 'icon' => 'fa-desktop', 'module' => 'module_support', 'default' => true],
'software' => ['label' => 'Software / Licenses', 'icon' => 'fa-cube', 'module' => 'module_support', 'default' => true],
'networks' => ['label' => 'Networks', 'icon' => 'fa-network-wired', 'module' => 'module_support', 'default' => true],
'domains' => ['label' => 'Domains', 'icon' => 'fa-globe', 'module' => 'module_support', 'default' => true],
'certificates' => ['label' => 'Certificates', 'icon' => 'fa-lock', 'module' => 'module_support', 'default' => true],
];
}
/*
* Read access per module, resolved once rather than once per section.
*/
function getClientPackSectionAccess() {
$access = [];
foreach (getClientPackSections() as $section) {
if (!isset($access[$section['module']])) {
$access[$section['module']] = lookupUserPermission($section['module']) >= 1;
}
}
return $access;
}
/*
* Resolves the posted checkboxes against the signed-in role. Returns
* ['contacts' => 1|0, ...]. A section the role can't read is 0 whatever was
* posted, so a hand-rolled POST can't pull in a section the modal never offered.
*/
function resolveClientPackSections() {
$access = getClientPackSectionAccess();
$selected = [];
foreach (getClientPackSections() as $key => $section) {
$selected[$key] = ($access[$section['module']] && !empty($_POST["include_$key"])) ? 1 : 0;
}
return $selected;
}
/*
* The section checkboxes for the client PDF pack modal, split across two columns.
* Sections the role can't read are left out entirely rather than shown and then
* silently dropped server side.
*/
function renderClientPackSections() {
$access = getClientPackSectionAccess();
$visible = [];
foreach (getClientPackSections() as $key => $section) {
if ($access[$section['module']]) {
$visible[$key] = $section;
}
}
$split = (int) ceil(count($visible) / 2);
$index = 0;
?>
<div class="row">
<div class="col-sm-6">
<?php foreach ($visible as $key => $section) { ?>
<?php if ($index === $split) { ?>
</div>
<div class="col-sm-6">
<?php } ?>
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="include_<?= $key ?>" name="include_<?= $key ?>" value="1" <?php if ($section['default']) { echo 'checked'; } ?>>
<label for="include_<?= $key ?>" class="custom-control-label">
<i class="fas fa-fw <?= $section['icon'] ?> mr-2"></i><?= escapeHtml($section['label']) ?>
</label>
</div>
</li>
<?php $index++; ?>
<?php } ?>
</div>
</div>
<?php
}