Merge pull request #1180 from itflow-org/develop

v25.02.2 Maint / Small Feature Release
This commit is contained in:
Johnny 2025-03-03 15:22:57 -05:00 committed by GitHub
commit 359b04e7d1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 385 additions and 391 deletions

View File

@ -2,6 +2,24 @@
This file documents all notable changes made to ITFlow.
## [25.02.2]
### Fixed
- Corrected some edit modals not showing notes correctly.
- Bugfix: When exporting to CSV, the first asset wasn't being shown.
- Fix broken create / edit credentials.
- Fixed missing Notificatons link.
- Fixed a few dead links.
- Fixed Overdue count also counting Non-Billable Invoices.
- Fix Edit Client Notes.
### Added / Changed
- Implemented SSL certificate history tracking.
- Added Inactive / Active Filter to Recurring Invoices.
- Merged Dismissed notifications and notification in one.
- Added Link Button to addd / edit Document WYSIWYG.
- Added Physical location to the asset export / import.
## [25.02.1]
### Fixed
- Resolved broken links in the client overview, project and client listings, and rack details.
@ -24,33 +42,33 @@ This file documents all notable changes made to ITFlow.
- Added a Vendor Quick Details Modal.
- Enabled vendor linking and added a License Purchase Reference in the Software Licenses section.
- Added download original, optimized and thumbnail option for images.
- Added Paid status to the top corner of Invoice PDFs
- Added Paid status to the top corner of Invoice PDFs.
## [25.02]
### Fixed
- Migrated several reports to the new permissions/roles system
- Resolved issue with empty task box showing for closed/resolved tickets
- Corrected ticket priority sorting
- Cloned asset interfaces when transferring assets between clients
- Migrated several reports to the new permissions/roles system.
- Resolved issue with empty task box showing for closed/resolved tickets.
- Corrected ticket priority sorting.
- Cloned asset interfaces when transferring assets between clients.
### Added / Changed
- Restored max number of records per page option back to 500 since we dont have repeating modals.
- Bulk Categorize Tickets feature
- Renamed "Interface port" to "Interface Description." "Interface Name" should now refer to port name and/or number
- Changed "Transfer Asset to Client" from a single action to a bulk action
- Updated Filter Footer UI to show "Showing x to x of x records" instead of just the total records
- Bulk Categorize Tickets feature.
- Renamed "Interface port" to "Interface Description." "Interface Name" should now refer to port name and/or number.
- Changed "Transfer Asset to Client" from a single action to a bulk action.
- Updated Filter Footer UI to show "Showing x to x of x records" instead of just the total records.
- Added Client Overview section to view client assets, contacts, licenses, credentials, etc.
- Introduced Quick Peek for asset details, contact information, and document viewing throughout the ITFlow App, all made possible by AJAX
- Enabled Simple Drag-and-Drop Ordering for Invoices, Recurring Invoices, Quotes, Ticket Tasks, and Ticket Template Tasks
- Added new Ticket View options: Kanban and Simple View
- Migrated all repeating modals to the new AJAX modal function for faster loading times and quicker development
- Allowed clients to upload PDF documents to accepted quotes
- Client Portal now shows ticket category
- Custom links can now be added to the Client Portal navbar
- Introduced Quick Peek for asset details, contact information, and document viewing throughout the ITFlow App, all made possible by AJAX.
- Enabled Simple Drag-and-Drop Ordering for Invoices, Recurring Invoices, Quotes, Ticket Tasks, and Ticket Template Tasks.
- Added new Ticket View options: Kanban and Simple View.
- Migrated all repeating modals to the new AJAX modal function for faster loading times and quicker development.
- Allowed clients to upload PDF documents to accepted quotes.
- Client Portal now shows ticket category.
- Custom links can now be added to the Client Portal navbar.
- Lots of little tweaks to UI, performance, bugs, etc.
### Breaking Changes
- Cron scripts have officially been moved to the /scripts folder and are no longer in the root directory; they must be updated to function properly
- Cron scripts have officially been moved to the /scripts folder and are no longer in the root directory; they must be updated to function properly.
## [25.01.3]
### Fixed

View File

@ -5,7 +5,7 @@ require_once '../includes/ajax_header.php';
$certificate_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_id = $certificate_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$certificate_name = nullable_htmlentities($row['certificate_name']);
$certificate_description = nullable_htmlentities($row['certificate_description']);
@ -13,10 +13,13 @@ $certificate_domain = nullable_htmlentities($row['certificate_domain']);
$certificate_domain_id = intval($row['certificate_domain_id']);
$certificate_issued_by = nullable_htmlentities($row['certificate_issued_by']);
$certificate_public_key = nullable_htmlentities($row['certificate_public_key']);
$certificate_notes = nullable_htmlentities($row['certificate_notes']);
$certificate_expire = nullable_htmlentities($row['certificate_expire']);
$certificate_created_at = nullable_htmlentities($row['certificate_created_at']);
$client_id = intval($row['certificate_client_id']);
$history_sql = mysqli_query($mysqli, "SELECT * FROM certificate_history WHERE certificate_history_certificate_id = $certificate_id");
// Generate the HTML form content using output buffering.
ob_start();
?>
@ -42,6 +45,9 @@ ob_start();
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pillsEditNotes<?php echo $certificate_id; ?>">Notes</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pillsEditHistory<?php echo $certificate_id; ?>">History</a>
</li>
</ul>
<hr>
@ -78,7 +84,7 @@ ob_start();
</div>
<select class="form-control select2" name="domain_id">
<option value="">- Select Domain -</option>
<?php
<?php
$domains_sql = mysqli_query($mysqli, "SELECT domain_id, domain_name FROM domains WHERE domain_client_id = $client_id");
while ($row = mysqli_fetch_array($domains_sql)) {
$domain_id = intval($row['domain_id']);
@ -141,11 +147,40 @@ ob_start();
</div>
<div class="tab-pane fade" id="pillsEditNotes<?php echo $certificate_id; ?>">
<div class="form-group">
<textarea class="form-control" name="notes" rows="12" placeholder="Enter some notes"><?php echo $certificate_notes; ?></textarea>
</div>
</div>
<div class="tab-pane fade" id="pillsEditHistory<?php echo $certificate_id; ?>">
<div class="table-responsive">
<table class='table table-sm table-striped border table-hover'>
<thead class='thead-dark'>
<tr>
<th>Date</th>
<th>Field</th>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($history_sql)) {
$certificate_modified_at = nullable_htmlentities($row['certificate_history_modified_at']);
$certificate_field = nullable_htmlentities($row['certificate_history_column']);
$certificate_before_value = nullable_htmlentities($row['certificate_history_old_value']);
$certificate_after_value = nullable_htmlentities($row['certificate_history_new_value']);
?>
<tr>
<td><?php echo $certificate_modified_at; ?></td>
<td><?php echo $certificate_field; ?></td>
<td><?php echo $certificate_before_value; ?></td>
<td><?php echo $certificate_after_value; ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>

View File

@ -251,9 +251,7 @@ ob_start();
<div class="tab-pane fade" id="pills-client-notes<?php echo $client_id; ?>">
<div class="form-group">
<textarea class="form-control" rows="10" placeholder="Enter some notes"
name="notes"><?php echo $client_notes; ?>
</textarea>
<textarea class="form-control" rows="10" placeholder="Enter some notes" name="notes"><?php echo $client_notes; ?></textarea>
</div>
</div>

View File

@ -66,13 +66,17 @@ ob_start();
</div>
<div class="modal-footer bg-white justify-content-end">
<?php if ($num_notifications) { ?>
<a href="post.php?dismiss_all_notifications&csrf_token=<?php echo $_SESSION[
"csrf_token"
]; ?>" class="btn btn-primary">
<span class="text-white text-bold"><i class="fas fa-check mr-2"></i>Dismiss all</span>
</a>
<a href="notifications.php" class="btn btn-secondary">
<span class="text-white">See all Notifications</span>
</a>
<?php } else { ?>
<a href="notifications_dismissed.php" class="btn btn-dark">
<a href="notifications.php?dismissed" class="btn btn-dark">
<span class="text-white text-bold">See Dismissed Notifications</span>
</a>
<?php } ?>

View File

@ -17,117 +17,6 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
// We need updates!
if (CURRENT_DATABASE_VERSION == '0.1.0') {
// Insert queries here required to update to DB version 0.1.1
// Logs don't get archived
mysqli_query($mysqli, "ALTER TABLE `logs` DROP `log_archived_at`");
// Assets will eventualy have file associatons which could include a receipt.
mysqli_query($mysqli, "ALTER TABLE `assets` DROP `asset_reciept`");
mysqli_query($mysqli, "ALTER TABLE `campaign_messages` DROP `message_updated_at`");
// This will be a seperate table eventually called contact_documents because contact can have several documents
mysqli_query($mysqli, "ALTER TABLE `documents` DROP `document_contact_id`");
mysqli_query($mysqli, "ALTER TABLE `expenses` DROP `expense_asset_id`");
mysqli_query($mysqli, "ALTER TABLE `files` DROP `file_contact_id`");
mysqli_query($mysqli, "ALTER TABLE `history` DROP `history_archived_at`");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.1'");
}
if (CURRENT_DATABASE_VERSION == '0.1.1') {
// Insert queries here required to update to DB version 0.1.2
// Create Many to Many Relationship tables for Assets, Contacts, Software and Vendors
mysqli_query($mysqli, "CREATE TABLE `asset_documents` (`asset_id` int(11) NOT NULL,`document_id` int(11) NOT NULL, PRIMARY KEY (`asset_id`,`document_id`))");
mysqli_query($mysqli, "CREATE TABLE `asset_logins` (`asset_id` int(11) NOT NULL,`login_id` int(11) NOT NULL, PRIMARY KEY (`asset_id`,`login_id`))");
mysqli_query($mysqli, "CREATE TABLE `asset_files` (`asset_id` int(11) NOT NULL,`file_id` int(11) NOT NULL, PRIMARY KEY (`asset_id`,`file_id`))");
mysqli_query($mysqli, "CREATE TABLE `contact_documents` (`contact_id` int(11) NOT NULL,`document_id` int(11) NOT NULL, PRIMARY KEY (`contact_id`,`document_id`))");
mysqli_query($mysqli, "CREATE TABLE `contact_logins` (`contact_id` int(11) NOT NULL,`login_id` int(11) NOT NULL, PRIMARY KEY (`contact_id`,`login_id`))");
mysqli_query($mysqli, "CREATE TABLE `contact_files` (`contact_id` int(11) NOT NULL,`file_id` int(11) NOT NULL, PRIMARY KEY (`contact_id`,`file_id`))");
mysqli_query($mysqli, "CREATE TABLE `software_documents` (`software_id` int(11) NOT NULL,`document_id` int(11) NOT NULL, PRIMARY KEY (`software_id`,`document_id`))");
mysqli_query($mysqli, "CREATE TABLE `software_logins` (`software_id` int(11) NOT NULL,`login_id` int(11) NOT NULL, PRIMARY KEY (`software_id`,`login_id`))");
mysqli_query($mysqli, "CREATE TABLE `software_files` (`software_id` int(11) NOT NULL,`file_id` int(11) NOT NULL, PRIMARY KEY (`software_id`,`file_id`))");
mysqli_query($mysqli, "CREATE TABLE `vendor_documents` (`vendor_id` int(11) NOT NULL,`document_id` int(11) NOT NULL, PRIMARY KEY (`vendor_id`,`document_id`))");
mysqli_query($mysqli, "CREATE TABLE `vendor_logins` (`vendor_id` int(11) NOT NULL,`login_id` int(11) NOT NULL, PRIMARY KEY (`vendor_id`,`login_id`))");
mysqli_query($mysqli, "CREATE TABLE `vendor_files` (`vendor_id` int(11) NOT NULL,`file_id` int(11) NOT NULL, PRIMARY KEY (`vendor_id`,`file_id`))");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.2'");
}
if (CURRENT_DATABASE_VERSION == '0.1.2') {
// Insert queries here required to update to DB version 0.1.3
mysqli_query($mysqli, "ALTER TABLE `logs` ADD `log_entity_id` INT NOT NULL DEFAULT '0' AFTER `log_user_id`");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.3'");
}
if (CURRENT_DATABASE_VERSION == '0.1.3') {
// Insert queries here required to update to DB version 0.1.4
mysqli_query($mysqli, "ALTER TABLE assets ADD asset_status VARCHAR(200) NULL AFTER asset_mac");
///Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.4'");
}
if (CURRENT_DATABASE_VERSION == '0.1.4') {
// Insert queries here required to update to DB version 0.1.5
mysqli_query($mysqli, "ALTER TABLE `domains` ADD `domain_txt` TEXT NULL DEFAULT NULL AFTER `domain_mail_servers`");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.5'");
}
if (CURRENT_DATABASE_VERSION == '0.1.5') {
// Insert queries here required to update to DB version 0.1.6
// Remove Mailing List Tables
mysqli_query($mysqli, "DROP TABLE campaigns");
mysqli_query($mysqli, "DROP TABLE campaign_messages");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.6'");
}
if (CURRENT_DATABASE_VERSION == '0.1.6') {
// Insert queries here required to update to DB version 0.1.7
//Remove custom links
mysqli_query($mysqli, "DROP TABLE custom_links");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.7'");
}
if (CURRENT_DATABASE_VERSION == '0.1.7') {
// Insert queries here required to update to DB version 0.1.8
mysqli_query($mysqli, "ALTER TABLE `settings` DROP `config_backup_enable`");
mysqli_query($mysqli, "ALTER TABLE `settings` DROP `config_backup_path`");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.8'");
}
if (CURRENT_DATABASE_VERSION == '0.1.8') {
// Insert queries here required to update to DB version 0.1.9
mysqli_query($mysqli, "ALTER TABLE `settings` DROP `config_base_url`");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.1.9'");
}
if (CURRENT_DATABASE_VERSION == '0.1.9') {
// Insert queries here required to update to DB version 0.2.0
// Allow contacts to reset their portal password
mysqli_query($mysqli, "ALTER TABLE contacts ADD contact_password_reset_token VARCHAR(200) NULL DEFAULT NULL AFTER contact_password_hash");
// Then, update the database to the next sequential version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '0.2.0'");
}
if (CURRENT_DATABASE_VERSION == '0.2.0') {
//Insert queries here required to update to DB version 0.2.1
@ -2239,7 +2128,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '1.6.6') {
mysqli_query($mysqli, "CREATE TABLE `contact_notes` (
`contact_note_id` INT(11) NOT NULL AUTO_INCREMENT,
`contact_note_type` VARCHAR(200) NOT NULL,
@ -2280,7 +2169,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '1.6.7') {
mysqli_query($mysqli, "CREATE TABLE `error_logs` (
`error_log_id` INT(11) NOT NULL AUTO_INCREMENT,
`error_log_type` VARCHAR(200) NOT NULL,
@ -2304,7 +2193,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '1.6.8') {
// Create New Vendor Templates Table this eventual be used to seperate templates out of the vendors table
mysqli_query($mysqli, "CREATE TABLE `vendor_templates` (`vendor_template_id` int(11) AUTO_INCREMENT PRIMARY KEY,
`vendor_template_name` varchar(200) NOT NULL,
@ -2322,7 +2211,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '1.6.9') {
mysqli_query($mysqli, "ALTER TABLE `files` ADD `file_has_thumbnail` TINYINT(1) NOT NULL DEFAULT 0 AFTER `file_mime_type`");
mysqli_query($mysqli, "ALTER TABLE `files` ADD `file_has_preview` TINYINT(1) NOT NULL DEFAULT 0 AFTER `file_has_thumbnail`");
@ -2330,7 +2219,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '1.7.0') {
mysqli_query($mysqli, "DROP TABLE `vendor_templates`");
mysqli_query($mysqli, "CREATE TABLE `vendor_contacts` (
@ -2348,12 +2237,12 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
`vendor_contact_archived_at` DATETIME DEFAULT NULL,
`vendor_contact_vendor_id` INT(11) NOT NULL DEFAULT 0
)");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.7.1'");
}
if (CURRENT_DATABASE_VERSION == '1.7.1') {
mysqli_query($mysqli, "DROP TABLE `error_logs`");
mysqli_query($mysqli, "CREATE TABLE `app_logs` (
@ -2364,7 +2253,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
`app_log_created_at` DATETIME NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`app_log_id`)
)");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.7.2'");
}
@ -2377,7 +2266,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '1.7.3') {
// Add Recurring Payments
mysqli_query($mysqli, "CREATE TABLE `recurring_payments` (
`recurring_payment_id` INT(11) NOT NULL AUTO_INCREMENT,
@ -2397,7 +2286,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '1.7.4') {
// Remove Recurring Payment Amount as it will use the Recurring Invoice Amount and is unessessary
mysqli_query($mysqli, "ALTER TABLE `recurring_payments` DROP `recurring_payment_amount`");
@ -2463,14 +2352,14 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '1.7.9') {
mysqli_query($mysqli, "ALTER TABLE `settings` DROP `config_cron_key`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.0'");
}
if (CURRENT_DATABASE_VERSION == '1.8.0') {
mysqli_query($mysqli, "ALTER TABLE `ticket_statuses` ADD `ticket_status_order` int(11) NOT NULL DEFAULT 0");
mysqli_query($mysqli, "ALTER TABLE `tickets` ADD `ticket_order` int(11) NOT NULL DEFAULT 0");
@ -2481,12 +2370,12 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.1'");
}
if (CURRENT_DATABASE_VERSION == '1.8.1') {
mysqli_query($mysqli, "ALTER TABLE `asset_interfaces` CHANGE `interface_port` `interface_description` VARCHAR(200) DEFAULT NULL AFTER `interface_name`");
mysqli_query($mysqli, "ALTER TABLE `asset_interfaces` ADD `interface_type` VARCHAR(50) DEFAULT NULL AFTER `interface_description`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.2'");
}
@ -2520,10 +2409,24 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.6'");
}
// if (CURRENT_DATABASE_VERSION == '1.8.6') {
// // Insert queries here required to update to DB version 1.8.7
if (CURRENT_DATABASE_VERSION == '1.8.6') {
mysqli_query($mysqli, "
CREATE TABLE `certificate_history` (`certificate_history_id` INT(11) NOT NULL AUTO_INCREMENT,
`certificate_history_column` VARCHAR(200) NOT NULL,
`certificate_history_old_value` TEXT NOT NULL,
`certificate_history_new_value` TEXT NOT NULL,
`certificate_history_certificate_id` INT(11) NOT NULL,
`certificate_history_modified_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`certificate_history_id`)) ENGINE = InnoDB CHARSET=utf8mb4 COLLATE utf8mb4_unicode_ci;
");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.7'");
}
// if (CURRENT_DATABASE_VERSION == '1.8.7') {
// // Insert queries here required to update to DB version 1.8.8
// // Then, update the database to the next sequential version
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.7'");
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.8.8'");
// }
} else {

18
db.sql
View File

@ -321,6 +321,24 @@ CREATE TABLE `categories` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `certificate_history`
--
DROP TABLE IF EXISTS `certificate_history`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `certificate_history` (
`certificate_history_id` int(11) NOT NULL AUTO_INCREMENT,
`certificate_history_column` varchar(200) NOT NULL,
`certificate_history_old_value` text NOT NULL,
`certificate_history_new_value` text NOT NULL,
`certificate_history_certificate_id` int(11) NOT NULL,
`certificate_history_modified_at` datetime NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`certificate_history_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `certificates`
--

View File

@ -5,4 +5,4 @@
* Update this file each time we merge develop into master. Format is YY.MM (add a .v if there is more than one release a month.
*/
DEFINE("APP_VERSION", "25.02.1");
DEFINE("APP_VERSION", "25.02.2");

View File

@ -202,7 +202,7 @@
<?php
if ($num_domains > 0) { ?>
<span class="right badge <?php if ($num_domains_expiring > 0) { ?> badge-warning text-dark<?php } ?> <?php if ($num_domains_expired > 0) { ?> badge-danger <?php } ?> text-white"><?php echo $num_domains; ?></span>
<span class="right badge <?php if (isset($num_domains_expiring)) { ?> badge-warning text-dark<?php } ?> <?php if (isset($num_domains_expired)) { ?> badge-danger <?php } ?> text-white"><?php echo $num_domains; ?></span>
<?php } ?>
</p>
</a>

View File

@ -5,4 +5,4 @@
* It is used in conjunction with database_updates.php
*/
DEFINE("LATEST_DATABASE_VERSION", "1.8.6");
DEFINE("LATEST_DATABASE_VERSION", "1.8.7");

View File

@ -33,7 +33,7 @@ $draft_count = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('invoice_id') AS num FROM invoices WHERE invoice_status = 'Cancelled' $client_query"));
$cancelled_count = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('invoice_id') AS num FROM invoices WHERE invoice_status NOT LIKE 'Draft' AND invoice_status NOT LIKE 'Paid' AND invoice_status NOT LIKE 'Cancelled' AND invoice_due < CURDATE() $client_query"));
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('invoice_id') AS num FROM invoices WHERE invoice_status NOT LIKE 'Draft' AND invoice_status NOT LIKE 'Paid' AND invoice_status NOT LIKE 'Cancelled' AND invoice_status NOT LIKE 'Non-Billable' AND invoice_due < CURDATE() $client_query"));
$overdue_count = $row['num'];
$sql_total_draft_amount = mysqli_query($mysqli, "SELECT SUM(invoice_amount) AS total_draft_amount FROM invoices WHERE invoice_status = 'Draft' $client_query");

View File

@ -28,6 +28,7 @@ tinymce.init({
toolbar: [
{ name: 'styles', items: [ 'styles' ] },
{ name: 'formatting', items: [ 'bold', 'italic', 'forecolor' ] },
{ name: 'link', items: [ 'link'] },
{ name: 'lists', items: [ 'bullist', 'numlist' ] },
{ name: 'alignment', items: [ 'alignleft', 'aligncenter', 'alignright', 'alignjustify' ] },
{ name: 'indentation', items: [ 'outdent', 'indent' ] },
@ -59,6 +60,7 @@ tinymce.init({
toolbar: [
{ name: 'styles', items: [ 'styles' ] },
{ name: 'formatting', items: [ 'bold', 'italic', 'forecolor' ] },
{ name: 'link', items: [ 'link'] },
{ name: 'lists', items: [ 'bullist', 'numlist' ] },
{ name: 'alignment', items: [ 'alignleft', 'aligncenter', 'alignright', 'alignjustify' ] },
{ name: 'indentation', items: [ 'outdent', 'indent' ] },
@ -275,20 +277,6 @@ tinymce.init({
}
});
// Initialize TinyMCE
tinymce.init({
selector: '.tinymcePreview',
resize: false,
promotion: false,
branding: false,
menubar: false,
toolbar: false,
statusbar: false,
readonly: false,
plugins: 'autoresize',
license_key: 'gpl',
});
// DateTime
$('.datetimepicker').datetimepicker({
});

View File

@ -14,7 +14,7 @@
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php } ?>
<div class="modal-body bg-white">
<p><strong>Format csv file with headings & data:</strong><br>Name, Description, Type, Make, Model, Serial, OS, Assigned To, Location</p>
<p><strong>Format csv file with headings & data:</strong><br>Name, Description, Type, Make, Model, Serial, OS, Assigned To, Location, Physical Location</p>
<hr>
<div class="form-group my-4">
<input type="file" class="form-control-file" name="file" accept=".csv" required>

View File

@ -1,76 +1,159 @@
<?php
// Default Column Sortby Filter
$sort = "notification_timestamp";
$order = "DESC";
require_once "includes/inc_all.php";
// Dismissed Filter
if (isset($_GET['dismissed'])) {
$dismissed_query = 'AND notification_dismissed_at IS NOT NULL';
$dismissed_filter = 1;
} else {
// Default - any
$dismissed_query = 'AND notification_dismissed_at IS NULL';
$dismissed_filter = 0;
}
$sql = mysqli_query($mysqli, "SELECT * FROM notifications LEFT JOIN clients ON notification_client_id = client_id WHERE notification_dismissed_at IS NULL AND notification_user_id = $session_user_id ORDER BY notification_id DESC");
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM notifications
LEFT JOIN clients ON notification_client_id = client_id
WHERE (notification_type LIKE '%$q%' OR notification LIKE '%$q%')
AND DATE(notification_timestamp) BETWEEN '$dtf' AND '$dtt'
AND notification_user_id = $session_user_id
$dismissed_query
ORDER BY $sort $order
LIMIT $record_from, $record_to
");
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-bell mr-2"></i>Notifications</h3>
<div class="card-tools">
<?php if (mysqli_num_rows($sql) > 0) { ?><a href="post.php?dismiss_all_notifications" class="btn btn-primary"><i class="fas fa-fw fa-check mr-2"></i>Dismiss All</a><?php } ?>
<a href="notifications_dismissed.php" class="btn btn-secondary"><i class="fas fa-fw fa-history mr-2"></i>Dismissed</a>
</div>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2">
<i class="fas fa-fw fa-bell mr-2"></i><?php if($dismissed_filter) { echo "Dismissed "; } ?>Notifications
</h3>
<div class="card-tools">
<?php if($dismissed_filter) { ?>
<a href="notifications.php" class="btn btn-primary"><i class="fas fa-fw fa-history mr-2"></i>Dismissed</a>
<?php } else { ?>
<a href="notifications.php?dismissed" class="btn btn-outline-secondary"><i class="fas fa-fw fa-history mr-2"></i>Dismissed</a>
<?php } ?>
</div>
<div class="card-body">
<?php if (mysqli_num_rows($sql) > 0) { ?>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead>
<tr>
<th>Timestamp</th>
<th>Type</th>
<th>Notification</th>
<th>Client</th>
<th class="text-center">Dismiss</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$notification_id = intval($row['notification_id']);
$notification_type = nullable_htmlentities($row['notification_type']);
$notification = nullable_htmlentities($row['notification']);
$notification_timestamp = nullable_htmlentities($row['notification_timestamp']);
$client_name = nullable_htmlentities($row['client_name']);
$client_id = intval($row['client_id']);
if (empty($client_name)) {
$client_name_display = "-";
} else {
$client_name_display = "<a href='client_overview.php?client_id=$client_id'>$client_name</a>";
}
?>
<tr class="row-danger">
<td><?php echo $notification_timestamp; ?></td>
<td><?php echo $notification_type; ?></td>
<td><?php echo $notification; ?></td>
<td><?php echo $client_name_display; ?></td>
<td class="text-center"><a class="btn btn-info btn-sm" href="post.php?dismiss_notification=<?php echo $notification_id; ?>"><i class="fas fa-check"></a></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
<?php } else { ?>
<div class="my-5" style="text-align: center">
<i class='far fa-fw fa-6x fa-bell-slash text-secondary'></i><h3 class='text-secondary mt-3'>No Notifications</h3>
</div>
<?php } ?>
</div>
<div class="card-body">
<form class="mb-4" autocomplete="off">
<?php if ($dismissed_filter) { ?>
<input type="hidden" name="dismissed" value="">
<?php } ?>
<div class="row">
<div class="col-sm-4">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search <?php if($dismissed_filter) { echo "Dismissed "; } ?>Notifications">
<div class="input-group-append">
<button class="btn btn-primary text-strong"><i class="fa fa-search"></i></button>
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
</div>
</div>
</div>
<div class="col-sm-8">
</div>
</div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf'])) { echo "show"; } ?>" id="advancedFilter">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div>
</div>
</div>
</div>
</form>
<div class="table-responsive-sm">
<table class="table table-hover">
<thead class="<?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=notification_timestamp&order=<?php echo $disp; ?>">
Timestamp <?php if ($sort == 'notification_timestamp') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=notification_type&order=<?php echo $disp; ?>">
Type <?php if ($sort == 'notification_type') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=notification&order=<?php echo $disp; ?>">
Notification <?php if ($sort == 'notification') { echo $order_icon; } ?>
</a>
</th>
<?php if(!$dismissed_filter) { ?>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=notification_dismissed_at&order=<?php echo $disp; ?>">
Dismissed At <?php if ($sort == 'notification_dismissed_at') { echo $order_icon; } ?>
</a>
</th>
<?php } ?>
<?php if($dismissed_filter) { ?>
<th class="text-center p-0">
<?php if (mysqli_num_rows($sql) > 0) { ?>
<a href="post.php?dismiss_all_notifications&csrf_token=<?php echo $_SESSION["csrf_token"]; ?>"
class="btn btn-sm btn-dark mb-2" title="Dismiss All">
<i class="fas fa-fw fa-check-double"></i>
</a>
<?php } ?>
</th>
<?php } ?>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$notification_id = intval($row['notification_id']);
$notification_timestamp = nullable_htmlentities($row['notification_timestamp']);
$notification_type = nullable_htmlentities($row['notification_type']);
$notification = nullable_htmlentities($row['notification']);
$notification_dismissed_at = nullable_htmlentities($row['notification_dismissed_at']);
$client_name = nullable_htmlentities($row['client_name']);
$client_id = intval($row['client_id']);
?>
<tr>
<td><?php echo $notification_timestamp; ?></td>
<td><?php echo $notification_type; ?></td>
<td><?php echo $notification; ?></td>
<?php if(!$dismissed_filter) { ?>
<td><?php echo $notification_dismissed_at; ?></td>
<?php } ?>
<?php if($dismissed_filter) { ?>
<td class="text-center"><a class="btn btn-secondary btn-sm" href="post.php?dismiss_notification=<?php echo $notification_id; ?>" title="Dismiss"><i class="fas fa-check"></i></a></td>
<?php } ?>
</tr>
<?php } ?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php"; ?>
</div>
</div>
<?php
require_once "includes/footer.php";
require_once "includes/footer.php";

View File

@ -1,132 +0,0 @@
<?php
// Default Column Sortby Filter
$sort = "notification_timestamp";
$order = "DESC";
require_once "includes/inc_all.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM notifications
LEFT JOIN clients ON notification_client_id = client_id
WHERE (notification_type LIKE '%$q%' OR notification LIKE '%$q%' OR client_name LIKE '%$q%')
AND DATE(notification_timestamp) BETWEEN '$dtf' AND '$dtt'
AND notification_user_id = $session_user_id
AND notification_dismissed_at IS NOT NULL
ORDER BY $sort $order
LIMIT $record_from, $record_to
");
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-bell mr-2"></i>Dismissed Notications</h3>
</div>
<div class="card-body">
<form class="mb-4" autocomplete="off">
<div class="row">
<div class="col-sm-4">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Dismissed Notifications">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-sm-8">
<button class="btn btn-primary float-right" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
</div>
</div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf'])) { echo "show"; } ?>" id="advancedFilter">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div>
</div>
</div>
</div>
</form>
<div class="table-responsive-sm">
<table class="table table-hover">
<thead class="<?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=notification_timestamp&order=<?php echo $disp; ?>">
Timestamp <?php if ($sort == 'notification_timestamp') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=notification_type&order=<?php echo $disp; ?>">
Type <?php if ($sort == 'notification_type') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=notification&order=<?php echo $disp; ?>">
Notification <?php if ($sort == 'notification') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
Client <?php if ($sort == 'client_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=notification_dismissed_at&order=<?php echo $disp; ?>">
Dismissed At <?php if ($sort == 'notification_dismissed_at') { echo $order_icon; } ?>
</a>
</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$notification_id = intval($row['notification_id']);
$notification_timestamp = nullable_htmlentities($row['notification_timestamp']);
$notification_type = nullable_htmlentities($row['notification_type']);
$notification = nullable_htmlentities($row['notification']);
$notification_dismissed_at = nullable_htmlentities($row['notification_dismissed_at']);
$client_name = nullable_htmlentities($row['client_name']);
$client_id = intval($row['client_id']);
if (empty($client_name)) {
$client_name_display = "-";
} else {
$client_name_display = "<a href='client_overview.php?client_id=$client_id'>$client_name</a>";
}
?>
<tr>
<td><?php echo $notification_timestamp; ?></td>
<td><?php echo $notification_type; ?></td>
<td><?php echo $notification; ?></td>
<td><?php echo $client_name_display; ?></td>
<td><?php echo $notification_dismissed_at; ?></td>
<?php } ?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php"; ?>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@ -740,7 +740,6 @@ if (isset($_GET['unlink_asset_from_file'])) {
if (isset($_POST["import_assets_csv"])) {
enforceUserPermission('module_support', 2);
validateCSRFToken($_POST['csrf_token']);
$client_id = intval($_POST['client_id']);
@ -774,9 +773,9 @@ if (isset($_POST["import_assets_csv"])) {
//(Else)Check column count (name, desc, type, make, model, serial, os, assigned to, location)
$f = fopen($file_name, "r");
$f_columns = fgetcsv($f, 1000, ",");
if (!$error & count($f_columns) != 9) {
if (!$error & count($f_columns) != 10) {
$error = true;
$_SESSION['alert_message'] = "Bad column count.";
$_SESSION['alert_message'] = "Invalid column count.";
}
//Else, parse the file
@ -832,11 +831,14 @@ if (isset($_POST["import_assets_csv"])) {
$location_id = intval($row['location_id']);
}
}
if (!empty($column[9])) {
$physical_location = sanitizeInput($column[9]);
}
// 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_contact_id = $contact_id, asset_location_id = $location_id, asset_client_id = $client_id");
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_physical_location = '$physical_location', asset_contact_id = $contact_id, asset_location_id = $location_id, asset_client_id = $client_id");
$asset_id = mysqli_insert_id($mysqli);
@ -864,7 +866,7 @@ if (isset($_POST["import_assets_csv"])) {
}
if (isset($_GET['download_assets_csv_template'])) {
$client_id = intval($_GET['download_client_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");
@ -879,7 +881,7 @@ if (isset($_GET['download_assets_csv_template'])) {
$f = fopen('php://memory', 'w');
//set column headers
$fields = array('Name', 'Description', 'Type', 'Make', 'Model', 'Serial', 'OS', 'Assigned To', 'Location');
$fields = array('Name', 'Description', 'Type', 'Make', 'Model', 'Serial', 'OS', 'Assigned To', 'Location', 'Physical Location');
fputcsv($f, $fields, $delimiter);
//move back to beginning of file
@ -898,22 +900,22 @@ if (isset($_GET['download_assets_csv_template'])) {
if (isset($_POST['export_assets_csv'])) {
enforceUserPermission('module_support');
validateCSRFToken($_POST['csrf_token']);
$client_name = 'All'; // default
if (isset($_POST['client_id'])) {
$client_id = intval($_POST['client_id']);
$client_query = "AND asset_client_id = $client_id";
$client_row = mysqli_fetch_array(mysqli_query($mysqli,"SELECT client_name FROM clients WHERE client_id = $client_id"));
$client_name = $client_row['client_name'];
} else {
$client_query = '';
}
//get records from database
// Get records from database
$sql = 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 LEFT JOIN clients ON asset_client_id = client_id WHERE asset_archived_at IS NULL $client_query ORDER BY asset_name ASC");
$row = mysqli_fetch_array($sql);
$client_name = $row['client_name'];
$num_rows = mysqli_num_rows($sql);
if ($num_rows > 0) {
@ -924,12 +926,12 @@ if (isset($_POST['export_assets_csv'])) {
$f = fopen('php://memory', 'w');
//set column headers
$fields = array('Name', 'Description', 'Type', 'Make', 'Model', 'Serial Number', 'Operating System', 'Purchase Date', 'Warranty Expire', 'Install Date', 'Assigned To', 'Location', 'Notes');
$fields = array('Name', 'Description', 'Type', 'Make', 'Model', 'Serial Number', 'Operating System', 'Purchase Date', 'Warranty Expire', 'Install Date', 'Assigned To', 'Location', 'Physical Location', 'Notes');
fputcsv($f, $fields, $delimiter);
//output each row of the data, format line as csv and write to file pointer
while($row = mysqli_fetch_array($sql)) {
$lineData = array($row['asset_name'], $row['asset_description'], $row['asset_type'], $row['asset_make'], $row['asset_model'], $row['asset_serial'], $row['asset_os'], $row['asset_purchase_date'], $row['asset_warranty_expire'], $row['asset_install_date'], $row['contact_name'], $row['location_name'], $row['asset_notes']);
while ($row = mysqli_fetch_array($sql)) {
$lineData = array($row['asset_name'], $row['asset_description'], $row['asset_type'], $row['asset_make'], $row['asset_model'], $row['asset_serial'], $row['asset_os'], $row['asset_purchase_date'], $row['asset_warranty_expire'], $row['asset_install_date'], $row['contact_name'], $row['location_name'], $row['asset_physical_location'], $row['asset_notes']);
fputcsv($f, $lineData, $delimiter);
}
@ -1188,7 +1190,6 @@ if (isset($_GET['delete_asset_interface'])) {
if (isset($_POST["import_client_asset_interfaces_csv"])) {
enforceUserPermission('module_support', 2);
validateCSRFToken($_POST['csrf_token']);
$asset_id = intval($_POST['asset_id']);
@ -1338,7 +1339,6 @@ if (isset($_GET['download_client_asset_interfaces_csv_template'])) {
if (isset($_POST['export_client_asset_interfaces_csv'])) {
enforceUserPermission('module_support');
validateCSRFToken($_POST['csrf_token']);
$asset_id = intval($_POST['asset_id']);

View File

@ -64,8 +64,41 @@ if (isset($_POST['edit_certificate'])) {
$expire = "'" . $expire . "'";
}
// Get current certificate info
$original_certificate_info = mysqli_fetch_assoc(mysqli_query($mysqli,"
SELECT
certificates.*,
domains.domain_name
FROM certificates
LEFT JOIN domains ON certificate_domain_id = domain_id
WHERE certificate_id = $certificate_id
"));
// Update certificate
mysqli_query($mysqli,"UPDATE certificates SET certificate_name = '$name', certificate_description = '$description', certificate_domain = '$domain', certificate_issued_by = '$issued_by', certificate_expire = $expire, certificate_public_key = '$public_key', certificate_notes = '$notes', certificate_domain_id = '$domain_id' WHERE certificate_id = $certificate_id");
// Fetch the updated info
$new_certificate_info = mysqli_fetch_assoc(mysqli_query($mysqli,"
SELECT
certificates.*,
domains.domain_name
FROM certificates
LEFT JOIN domains ON certificate_domain_id = domain_id
WHERE certificate_id = $certificate_id
"));
// Compare/log changes between old/new info
$ignored_columns = ["certificate_public_key", "certificate_updated_at", "certificate_accessed_at", "certificate_domain_id"];
foreach ($original_certificate_info as $column => $old_value) {
$new_value = $new_certificate_info[$column];
if ($old_value != $new_value && !in_array($column, $ignored_columns)) {
$column = sanitizeInput($column);
$old_value = sanitizeInput($old_value);
$new_value = sanitizeInput($new_value);
mysqli_query($mysqli,"INSERT INTO certificate_history SET certificate_history_column = '$column', certificate_history_old_value = '$old_value', certificate_history_new_value = '$new_value', certificate_history_certificate_id = $certificate_id");
}
}
// Logging
logAction("Certificate", "Edit", "$session_name edited certificate $name", $client_id, $certificate_id);
@ -144,7 +177,7 @@ if (isset($_POST['bulk_delete_certificates'])) {
$client_id = intval($row['certificate_client_id']);
mysqli_query($mysqli, "DELETE FROM certificates WHERE certificate_id = $certificate_id AND certificate_client_id = $client_id");
// Logging
logAction("Certificate", "Delete", "$session_name deleted certificate $certificate_name", $client_id);

View File

@ -12,7 +12,7 @@ if (isset($_POST['add_login'])) {
require_once 'post/user/credential_model.php';
mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_description = '$description', login_uri = '$uri', login_uri_2 = '$uri_2', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_important = $important, login_contact_id = $contact_id, login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id, login_client_id = $client_id");
mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_description = '$description', login_uri = '$uri', login_uri_2 = '$uri_2', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_important = $important, login_contact_id = $contact_id, login_asset_id = $asset_id, login_client_id = $client_id");
$login_id = mysqli_insert_id($mysqli);
@ -50,7 +50,7 @@ if (isset($_POST['edit_login'])) {
}
// Update the login entry with the new details
mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_description = '$description', login_uri = '$uri', login_uri_2 = '$uri_2', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_important = $important, login_contact_id = $contact_id, login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id WHERE login_id = $login_id");
mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_description = '$description', login_uri = '$uri', login_uri_2 = '$uri_2', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_important = $important, login_contact_id = $contact_id, login_asset_id = $asset_id WHERE login_id = $login_id");
// Tags
// Delete existing tags

View File

@ -18,8 +18,14 @@ if (isset($_GET['client_id'])) {
// Perms
enforceUserPermission('module_sales');
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
// Status Filter
if (isset($_GET['status']) && $_GET['status'] == "inactive") {
$status_filter = "inactive";
$status_query = "AND recurring_status = 0";
} else {
$status_filter = "active";
$status_query = "AND recurring_status = 1";
}
$sql = mysqli_query(
$mysqli,
@ -29,6 +35,7 @@ $sql = mysqli_query(
LEFT JOIN recurring_payments ON recurring_payment_recurring_invoice_id = recurring_id
WHERE (CONCAT(recurring_prefix,recurring_number) LIKE '%$q%' OR recurring_frequency LIKE '%$q%' OR recurring_scope LIKE '%$q%' OR client_name LIKE '%$q%' OR category_name LIKE '%$q%')
AND DATE(recurring_created_at) BETWEEN '$dtf' AND '$dtt'
$status_query
$client_query
ORDER BY $sort $order LIMIT $record_from, $record_to");
@ -49,6 +56,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php if ($client_url) { ?>
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php } ?>
<input type="hidden" name="status" value="<?php echo $status_filter; ?>">
<div class="row">
<div class="col-sm-4">
<div class="input-group">
@ -60,7 +68,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
<div class="col-sm-8">
<div class="btn-group float-right">
<div class="btn-toolbar float-right">
<div class="btn-group mr-2">
<a href="?status=active" class="btn btn-<?php if ($status_filter == "active"){ echo "primary"; } else { echo "default"; } ?>"><i class="fa fa-fw fa-check mr-2"></i>Active</a>
<a href="?status=inactive" class="btn btn-<?php if ($status_filter == "inactive"){ echo "primary"; } else { echo "default"; } ?>"><i class="fa fa-fw fa-ban mr-2"></i>Inactive</a>
</div>
</div>
</div>
</div>

View File

@ -66,7 +66,7 @@ enforceUserPermission('module_financial');
?>
<tr>
<td><a href="client_invoices.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
<td><a href="invoices.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $balance, $session_company_currency); ?></td>
</tr>
<?php

View File

@ -45,7 +45,7 @@ $sql_certificates = mysqli_query(
while ($row = mysqli_fetch_array($sql_certificates)) {
$certificate_id = intval($row['certificate_id']);
$domain = sanitizeInput($row['certificate_domain']);
$certificate = getSSL($domain);
$expire = sanitizeInput($certificate['expire']);
@ -60,8 +60,42 @@ while ($row = mysqli_fetch_array($sql_certificates)) {
echo "$public_key\n\n";
$expire = "'" . $expire . "'";
// Get current certificate info
$original_certificate_info = mysqli_fetch_assoc(mysqli_query($mysqli,"
SELECT
certificates.*,
domains.domain_name
FROM certificates
LEFT JOIN domains ON certificate_domain_id = domain_id
WHERE certificate_id = $certificate_id
"));
// Update
mysqli_query($mysqli,"UPDATE certificates SET certificate_issued_by = '$issued_by', certificate_expire = $expire, certificate_public_key = '$public_key' WHERE certificate_id = $certificate_id");
// Fetch the updated info
$new_certificate_info = mysqli_fetch_assoc(mysqli_query($mysqli,"
SELECT
certificates.*,
domains.domain_name
FROM certificates
LEFT JOIN domains ON certificate_domain_id = domain_id
WHERE certificate_id = $certificate_id
"));
// Compare/log changes between old/new info
$ignored_columns = ["certificate_public_key", "certificate_updated_at", "certificate_accessed_at", "certificate_domain_id"];
foreach ($original_certificate_info as $column => $old_value) {
$new_value = $new_certificate_info[$column];
if ($old_value != $new_value && !in_array($column, $ignored_columns)) {
$column = sanitizeInput($column);
$old_value = sanitizeInput($old_value);
$new_value = sanitizeInput($new_value);
mysqli_query($mysqli,"INSERT INTO certificate_history SET certificate_history_column = '$column', certificate_history_old_value = '$old_value', certificate_history_new_value = '$new_value', certificate_history_certificate_id = $certificate_id");
}
}
} else {
logApp("Cron-Certificate-Refresher", "error", "Cron Certificate Refresh - error updating Error updating $domain.");
error_log("Certificate Cron Error - Error updating $domain");