Files
itflow/admin/post/starter_content.php
johnnyq ea23a2bad5 Audit logs stage 1: Admin > Audit Logs rebuilt on the standard list with search, sortable columns and paging, filters for date, who (agent, portal contact or ITFlow itself), client, type and action, and counted views for Changes, Deletions, Sign-ins, Security and Data out; each entry shows who with their avatar, the client, the type and action as a coloured label, the description without the name in front, the IP and device in words, and links to its record while it exists or says No longer here; a quick look with the full entry, the raw user agent, everything from that IP, the record's other entries and what the same person did 15 minutes either side; CSV/PDF export with the page's filters, view and picked columns, itself audited; new functions/audit_log.php, admin/modals/audit_log/audit_log.php and audit_log_export.php, admin/post/audit_log.php and audit_logs export columns; agent/files.php takes ?open= for a file's quick look; database 3.3.1 adds log_client_id and log_entity_id keys on logs, gives each action one name (Unarchive/Restored to Restore, Deleted, Merged, Closed, Reopened, Resolved and Sent to Delete, Merge, Close, Reopen, Resolve and Send, Client Access to Denied, saved card and payment provider Updates to Create or Delete, contract template Update to Edit, type client to Client) and repoints entries at the right record (reply edits and redactions to the ticket, API document edits to the document, reimbursements to the recording expense, API client restores to the client), guarded so it can run again; logAudit call sites in agent, admin, api, client, cron and functions use the same names and record ids
2026-10-18 22:36:25 -04:00

175 lines
5.9 KiB
PHP

<?php
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['load_starter_content'])) {
validateCSRFToken();
require_once 'starter_content_model.php';
$starter_content_packs = starterContentPacks();
$requested_pack = $_POST['load_starter_content'];
// Only registry keys are accepted - the value goes nowhere near a query, but
// an unknown pack should say so rather than silently do nothing
if ($requested_pack === 'all') {
$selected_packs = array_keys($starter_content_packs);
} elseif (isset($starter_content_packs[$requested_pack])) {
$selected_packs = [$requested_pack];
} else {
flashAlert("Unknown starter content pack", 'error');
redirect();
}
// Registry order is load order - categories before products, ticket
// templates before the project templates that link to them
$items_added = 0;
$summary = [];
foreach ($selected_packs as $pack) {
$pack_added = starterContentLoad($mysqli, $pack);
if ($pack_added) {
$items_added = $items_added + $pack_added;
$summary[] = "$pack_added " . $starter_content_packs[$pack]['label'];
}
}
if ($items_added) {
$summary = implode(', ', $summary);
logAudit("Starter Content", "Create", "$session_name loaded starter content - $summary");
flashAlert("Added <strong>$items_added</strong> items: $summary");
} else {
flashAlert("Nothing to add - everything in that selection is already here", 'info');
}
redirect();
}
if (isset($_POST['update_starter_ticket_templates'])) {
// The starter ticket templates already here, brought up to this version
validateCSRFToken();
require_once 'starter_content_model.php';
$counts = starterUpdateTicketTemplates();
if ($counts['replaced']) {
logAudit("Starter Content", "Edit", "$session_name brought {$counts['replaced']} starter ticket templates up to date");
flashAlert("Brought <strong>{$counts['replaced']}</strong> starter ticket templates up to date" . ($counts['forms'] ? " - <strong>{$counts['forms']}</strong> have a request form, turned off until you turn it on in their Client portal tab" : ''));
} else {
flashAlert("None of the starter ticket templates are here to update - add them instead", 'info');
}
redirect();
}
if (isset($_POST['update_starter_canned_responses'])) {
// The starter canned responses already here, brought up to this version
validateCSRFToken();
require_once 'starter_content_model.php';
$counts = starterUpdateCannedResponses();
if ($counts['replaced']) {
logAudit("Starter Content", "Edit", "$session_name brought {$counts['replaced']} starter canned responses up to date");
flashAlert("Brought <strong>{$counts['replaced']}</strong> starter canned responses up to date");
} else {
flashAlert("None of the starter canned responses are here to update - add them instead", 'info');
}
redirect();
}
if (isset($_POST['update_starter_document_templates'])) {
// The starter document templates already here, brought up to this version
validateCSRFToken();
require_once 'starter_content_model.php';
$counts = starterUpdateDocumentTemplates();
if ($counts['replaced']) {
logAudit("Starter Content", "Edit", "$session_name brought {$counts['replaced']} starter document templates up to date");
flashAlert("Brought <strong>{$counts['replaced']}</strong> starter document templates up to date");
} else {
flashAlert("None of the starter document templates are here to update - add them instead", 'info');
}
redirect();
}
if (isset($_POST['update_starter_license_templates'])) {
// The starter license templates already here, brought up to this version
validateCSRFToken();
require_once 'starter_content_model.php';
$counts = starterUpdateLicenseTemplates();
if ($counts['replaced']) {
logAudit("Starter Content", "Edit", "$session_name brought {$counts['replaced']} starter license templates up to date");
flashAlert("Brought <strong>{$counts['replaced']}</strong> starter license templates up to date" . ($counts['vendors'] ? " - with <strong>{$counts['vendors']}</strong> vendor template" . ($counts['vendors'] === 1 ? '' : 's') . " they come from" : ''));
} else {
flashAlert("None of the starter license templates are here to update - add them instead", 'info');
}
redirect();
}
if (isset($_POST['load_demo_data'])) {
validateCSRFToken();
require_once 'demo_data_model.php';
$counts = demoDataLoad($mysqli);
if (!$counts['clients']) {
flashAlert("Nothing to add - every demo client is already here", 'info');
redirect();
}
$summary = "{$counts['clients']} clients, {$counts['contacts']} contacts, {$counts['assets']} assets, {$counts['documentation']} documentation records, {$counts['tickets']} tickets, {$counts['projects']} projects, {$counts['billing']} billing records, {$counts['company']} company records";
logAudit("Demo Data", "Create", "$session_name loaded demo data - $summary");
if ($counts['skipped_credentials']) {
flashAlert("Added demo data: $summary. Credentials were skipped - the credential vault did not open for this session", 'warning');
} else {
flashAlert("Added demo data: $summary");
}
redirect();
}
if (isset($_POST['remove_demo_data'])) {
validateCSRFToken();
require_once 'demo_data_model.php';
$clients_removed = demoDataRemove($mysqli);
if ($clients_removed) {
logAudit("Demo Data", "Delete", "$session_name removed demo data - $clients_removed demo clients and all associated records");
flashAlert("Removed <strong>$clients_removed</strong> demo clients and everything associated with them", 'error');
} else {
flashAlert("No demo clients found - nothing to remove", 'info');
}
redirect();
}