Compare commits

...

124 Commits

Author SHA1 Message Date
ThaMunsta
e5344c0327 Merge tag 'v25.03' into techbar 2025-03-30 14:23:22 -04:00
Johnny
34397fe468 Merge pull request #1196 from itflow-org/develop
Merge Develop into Master
2025-03-29 15:51:47 -04:00
johnnyq
2f82647f5e One more chnagelog update 2025-03-29 15:35:40 -04:00
johnnyq
7d7854424c Refined and updated changelog 2025-03-28 13:15:33 -04:00
johnnyq
eaeadbe933 Fix users list 2025-03-28 12:01:39 -04:00
johnnyq
cf3f0cee6c Revert Users listing 2025-03-28 11:48:23 -04:00
johnnyq
9f7c289e94 Fix AI Promps 2025-03-27 22:25:01 -04:00
johnnyq
c2bba7a919 Allow to close a project with resolved tickets 2025-03-27 14:21:56 -04:00
johnnyq
4bb37a7198 Removed absent task_description var from projects 2025-03-27 13:41:15 -04:00
johnnyq
231694aabe Fix Invoice Vars in ticket, return empty string instead of null for getFieldByID() 2025-03-27 13:38:22 -04:00
johnnyq
2fb75e6d67 Uncommented out temp comment check cli runtime 2025-03-27 12:40:43 -04:00
Johnny
810af638a3 Merge pull request #1193 from itflow-org/cron-recurring-notify
Recurring items with next-run dates in the past
2025-03-27 12:39:27 -04:00
johnnyq
9223b8cfb1 Fixed some renamed vars 2025-03-27 12:29:55 -04:00
wrongecho
b7df21a663 Notify if a recurring ticket, invoice or expense has a next run date in the past - it needs to be manually adjusted for cron to pick it up again. Also, bugfix bulk recurring ticket delete. 2025-03-27 16:29:39 +00:00
johnnyq
7d47ed4dbd Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-03-27 12:01:24 -04:00
johnnyq
65eaf92862 Fixed a few debug errors where client was not checked to see if it was set in some of the create modals, replaced old url_query_strings_sb var to the correct new var url_query_strings_sort. 2025-03-27 12:01:10 -04:00
wrongecho
8a01bc0d7d Recurring ticket - remove rogue 's' from 'Contact' tab 2025-03-27 15:54:10 +00:00
Johnny
1a8a3781dc Merge pull request #1192 from itflow-org/certs-exp-colours
Certificates page and sidebar - colours/badges
2025-03-27 11:39:49 -04:00
wrongecho
eadfdc41c4 Tickets api - allow setting the billable status when creating a ticket 2025-03-27 14:45:44 +00:00
wrongecho
421abd4c5b Tickets api - bugfix 500 error 2025-03-27 14:34:36 +00:00
wrongecho
ae1a0dcc73 Certificates page and sidebar - Only show yellow on certificates 7 days (blanket, not just for LE) 2025-03-27 12:27:08 +00:00
johnnyq
63b8804e2d Migrated client pdf export to TCPDF from pdfMake 2025-03-26 21:13:00 -04:00
johnnyq
634afcc089 Added TCPDF for PDFs and allow document export to PDF 2025-03-26 19:35:27 -04:00
johnnyq
90f5c8ad57 Simplify getFallBack function to just fallback on - instead N/A 2025-03-26 18:39:45 -04:00
johnnyq
12fd45c144 Dont include Archived Assets, contacts or software is the software license export report 2025-03-26 18:28:33 -04:00
johnnyq
382258a27c Add User and Asset Assigned Licenses to Client PDF Export 2025-03-26 18:17:45 -04:00
johnnyq
b5fa8ab4de Added Search by client Abbreviation to client and global search 2025-03-26 17:56:40 -04:00
johnnyq
bbb0db2f4f Update Changelog 2025-03-26 17:53:33 -04:00
johnnyq
5b89e3dbee Add Phone Country code in even more places 2025-03-26 14:04:47 -04:00
johnnyq
07b29a7bdc Add Phone Country code in more places for proper phone number formatting 2025-03-26 13:36:56 -04:00
johnnyq
3286343026 Update DB to remove phone_mask 2025-03-26 11:14:05 -04:00
johnnyq
6a26b611fa Remove Phone Masking option in favor of Country Codes 2025-03-26 11:10:51 -04:00
johnnyq
218fd2dcdc Update formatPhoneNumber php function to include other country formatting, updated phone inputs to incoude country code 2025-03-25 18:45:24 -04:00
johnnyq
4c85db5e49 Remove legacy redact function in favor of tinymce integration redact 2025-03-24 13:22:41 -04:00
johnnyq
85ae42190a Feature: Added User Signature preferences, currently appends signature to ticket replies / comments 2025-03-24 12:49:47 -04:00
johnnyq
df8a755462 Wrap a wait before the DOM is loaded before loading anything calling anything in app.js 2025-03-23 18:08:14 -04:00
johnnyq
53713a0318 Add back batch payment when in client view for invoices 2025-03-22 21:01:55 -04:00
johnnyq
61aa477cbf Fix Tags 2025-03-22 20:49:37 -04:00
johnnyq
c2adb92d28 Rework tag filter a bit to use array_map instead of looping through the get vars, update string wording to tag_filter and only show tags in the tag filter that are relatd to an entity and also include tags in the get var fixes 2025-03-22 18:32:56 -04:00
johnnyq
19b2b08eac Update locations filter to still include the a location that is not assigned to an entity if present in the url this fixes the issue where for example in client contact you select a location to filter only 1 contact is shown you goto edit the contacts location then submit it pushes you back with no results and all locations is present but in the uri the old location is still present 2025-03-22 15:49:35 -04:00
johnnyq
504346256f Only show locations if an entity references the locations. Previously, all locations were listed in the location filter, even if no entites were assigned to them. 2025-03-22 15:16:53 -04:00
johnnyq
34e92d2223 Update Tags filter to only show tags available 2025-03-22 14:55:13 -04:00
johnnyq
573953704c Limit Client Selection to clients that have an emtity in client filters 2025-03-22 14:11:27 -04:00
johnnyq
0b9f10985d Add Client Select Filters the remaining entities also when creating an entity auto select the client based off the the client selected in the client dropdown filter 2025-03-22 13:50:03 -04:00
johnnyq
8e3dd42a32 Allow start interface to be named 0 2025-03-21 21:54:55 -04:00
johnnyq
0647933df7 Added JS Library to handle Country based Phone formatting inputs intl-tel-input 2025-03-21 12:59:56 -04:00
johnnyq
93f4da3962 Added Phone Country Code fields defaulting to +1 for US will add logic in code later for phone number formatting 2025-03-21 12:48:00 -04:00
johnnyq
f72351ea88 UI tidy 2025-03-21 11:58:16 -04:00
johnnyq
d3c4c8c846 Comment Query 2025-03-20 18:18:33 -04:00
johnnyq
cf047024a1 Add Projects to client side nav and seperated the logic between client and global view of projects 2025-03-20 18:17:26 -04:00
johnnyq
ad3ed68932 Add the ability to Create a ticket inside a project then auto assign it to the project 2025-03-20 17:05:47 -04:00
Johnny
62b8ee9d30 Merge pull request #1190 from itflow-org/cron-certificate-notifs
Cron certificate notifs
2025-03-20 13:51:35 -04:00
johnnyq
eedd92c894 Fix creating a ticket and selecting a template it would use template name instead of the subject for the ticket 2025-03-20 13:47:11 -04:00
johnnyq
622d5e5a44 Delete unused add asset ajax modal 2025-03-20 13:00:51 -04:00
johnnyq
475d653979 You can now upload and create documents, credentials in contact and asset details sections 2025-03-20 12:58:00 -04:00
johnnyq
19a6f8f422 Use nearest text area instead of a static ID for AI rewording, started adding entity creations in contact details and auto selecting the contact when in contact details page 2025-03-20 11:39:50 -04:00
wrongecho
e69d69760d Cron - Only notify on certificates expiring in 45 days if they are valid for longer than 90 (i.e. not LE) 2025-03-20 13:53:53 +00:00
johnnyq
06de349fac Expanded the Redact tool into ticket details area, generalized it to allow redaction in other areas as well 2025-03-19 15:35:02 -04:00
johnnyq
c3ec83f640 Updated changelog also added redact to open tickets 2025-03-19 13:20:55 -04:00
wrongecho
37c20e4e0d Hyperlink the report_time_by_tech report. Need to add a monthly version. 2025-03-19 14:07:07 +00:00
wrongecho
400ba5bb20 Started changelog 2025-03-19 14:02:30 +00:00
wrongecho
a1ea5214a9 Sonarcloud fixes 2025-03-19 13:54:15 +00:00
wrongecho
aae633c4ac Merge pull request #1189 from itflow-org/ticket-redaction
Add ticket redaction feature
2025-03-19 13:53:15 +00:00
johnnyq
ec8d7a36a8 Only store optimized WebP images, so only 1 image is stored and used for thumnails and viewing, removed fields has_preview and has_thumbnail as these are no longer needed, fixed issue when optimizing portrait images the bottom half would get cropped out 2025-03-18 16:48:05 -04:00
wrongecho
21dc26b06f Merge branch 'develop' into ticket-redaction 2025-03-18 09:42:29 +00:00
wrongecho
6a8d2cf1d4 Add ticket redaction feature 2025-03-18 09:40:39 +00:00
johnnyq
b803ba4c55 Use MD5 hashing instead of SHA256 on file uploads which is way faster and still provides a unique file reference 2025-03-17 15:10:39 -04:00
johnnyq
4378fc2719 Removed redundant hash field from files table as the reference already stores this value 2025-03-17 14:59:37 -04:00
johnnyq
244e1290b4 Convert service_domains to use InnoDB instead of MyISAM 2025-03-15 18:35:21 -04:00
johnnyq
5a64bd3a32 Ensure all Tables and fields use CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci 2025-03-15 18:28:48 -04:00
johnnyq
cc0b2126ba Removed most Associated deletions when deleting a client as most of this is performed through SQL now using cascade deleting 2025-03-14 19:45:59 -04:00
johnnyq
97f92e508e Remove Associated Deletions as these are handled by the database cascade deletions 2025-03-14 18:37:56 -04:00
johnnyq
09fbe4e4ad Update more multi to multi link tables to use cascading delete and foreign key relation 2025-03-14 18:18:44 -04:00
johnnyq
508af6a80f Fix some Database update logic 2025-03-14 17:15:10 -04:00
johnnyq
073f816dbd Do not allow cascade deletion for rack devices as this table is optional to reference an asset and will cause issues when adding a devoce without a selected asset 2025-03-14 15:33:00 -04:00
johnnyq
bf327afd19 Bump DataTables from 2.2.1 to 2.2.2 2025-03-14 13:35:48 -04:00
johnnyq
8fb8ce319e Added copy to clipboard for contact and asset ajax modal credentials fixed issue with clipboard because jquery ui was declared last mved it up 2025-03-14 13:28:00 -04:00
johnnyq
eabfef22be Turned caching back on for Ajax Modals Function Fix some PHP Error, update credential vars in assets and contacts 2025-03-14 12:31:18 -04:00
johnnyq
06c31e0808 Update Asset reference SQL Tables to use Foreign keys and cascading delete, and remove orphaned data from the foreign tables to prevent integrity errors during update 2025-03-13 21:35:39 -04:00
johnnyq
509fb5cfed Bump TinyMCE from 7.6.1 to 7.7.1 2025-03-13 19:41:21 -04:00
johnnyq
f1aa66119a Update pointers to the includes folder 2025-03-13 18:12:18 -04:00
johnnyq
7150b1545a Moved files check_login.php, get_settings.php, settings_localization_array.php, inc_set_timezone.php into the includes folder, we also moved /client/check_login.php into client/includes/ 2025-03-13 17:55:31 -04:00
johnnyq
59bbbe4a8d Removed Patch panel tables as they share similarities with assets and assets interfaces, rename events to calendar events and event attendees to calendar even attendees 2025-03-13 16:34:38 -04:00
johnnyq
f64641cfdd Fix regression OTP in guest view item 2025-03-12 23:03:28 -04:00
johnnyq
f1783a6110 update credential model 2025-03-12 22:35:13 -04:00
johnnyq
c8c1155c9c Update the API for the new cred var names 2025-03-12 22:33:06 -04:00
johnnyq
338a08da6c Fix credential vars in Services post 2025-03-12 22:10:48 -04:00
johnnyq
15aed891f4 Fix credential vars in Services 2025-03-12 22:04:55 -04:00
johnnyq
c1c54780cb Update client export pdf for new table field names 2025-03-12 21:39:47 -04:00
johnnyq
e93704bbdb Completely renamed everything login to credential including tables added cascading deletion to the multi to multi tables 2025-03-12 21:28:50 -04:00
johnnyq
c0db914213 Added Recurring Ticket Reference to Tickets 2025-03-12 13:56:36 -04:00
johnnyq
b78e31e518 Fix Recurring Income by Client Report with the updated recurring invoice vars 2025-03-12 11:36:51 -04:00
johnnyq
2533f0ced1 Fix Create Auto Payment after renaming recurring to recurring invoices 2025-03-11 22:54:44 -04:00
johnnyq
c7f4e48a27 A Few more places to update recurring invoice vars 2025-03-11 22:38:13 -04:00
johnnyq
87c1a95b06 Few more places for recurring invoice vars 2025-03-11 22:26:52 -04:00
johnnyq
4efb39358a Missed recurring_invoice details and fixes up a few other places for recurring invoice vars 2025-03-11 22:24:19 -04:00
johnnyq
619b93a545 Renamed Recurring to recurring_invoices updated a large portion of code, and updated many other fields to reflect recurring_invoice and not just recurring 2025-03-11 22:08:37 -04:00
johnnyq
a0598997d7 Update Recurring Tickets in a few more places 2025-03-11 19:55:08 -04:00
johnnyq
d0b8095bba Feature: Added additional assets to Recurring Tickets as well 2025-03-11 19:36:39 -04:00
johnnyq
daab1bca3d Rename the remain items from Scheduled Tickets to Recurring Tickets 2025-03-11 18:32:24 -04:00
johnnyq
a0a2fddd90 Feature: Additonal Assets can now be assigned to a single Ticket 2025-03-11 17:41:40 -04:00
johnnyq
f61c30bd5a Started work on additional assets per ticket, added table ticket_assets, Fixed Legacy Check User Role Functions 2025-03-11 15:10:23 -04:00
johnnyq
4921d1eb19 More Work on Client Users section, added User Icon Indicator in contact if a user account exists 2025-03-11 13:59:01 -04:00
johnnyq
28c8b1a6da Fix missing attachments on ticket replies via the ticket email parser 2025-03-10 19:17:40 -04:00
johnnyq
3f0a6df717 Organize color theme settings into similar color rows 2025-03-10 18:46:08 -04:00
johnnyq
07c8398e0d Update user_roles naming in setup and setup_cli 2025-03-10 18:06:47 -04:00
johnnyq
82c7a64a25 Added Bulk Delete Asset Functionality and also deleted more asset reference tables as we are not using cascade delete yet 2025-03-10 17:35:16 -04:00
johnnyq
164a6a5604 Started Standard user view and client user view in users 2025-03-10 16:51:10 -04:00
johnnyq
9b6ea851e7 Removed the prepended user_ from the fields in the user_roles table, moved user_role_id from user_settings directly to users table, rename table user_permissions to user_client_permissions, removed unused Sessions vars in login. This upedate will require to update using update_cli.php --db_update 2025-03-10 15:57:16 -04:00
johnnyq
3804e18e53 When cron or manually generating invoice from a Recurring Invoice insert referencing recurring Invoice ID into the invoice 2025-03-10 12:34:31 -04:00
johnnyq
244a47efad Added Recurring Invoice Reference ID to Invoices and Product ID reference to Invoice Items 2025-03-10 12:26:14 -04:00
Johnny
89e59b2448 Merge pull request #1184 from itflow-org/tck-time-by-tech
Add work/time by technician report
2025-03-09 12:31:34 -04:00
Johnny
bf9c2f6de7 Merge pull request #1182 from itflow-org/tck-fr-at
Add database field for ticket_first_response_at.
2025-03-09 12:31:07 -04:00
Johnny
ff80a3db3f Merge pull request #1186 from itflow-org/develop
v25.02.4 - Stable Minor Release
2025-03-08 18:11:38 -05:00
johnnyq
c7d00d7b0d Fixed Changelog 2025-03-08 17:53:20 -05:00
johnnyq
1c6e74b08e Update Changelog put back the missing parts for 25.02.3 2025-03-08 17:40:36 -05:00
johnnyq
f8d054f8aa Bump minor version and update the Changelog 2025-03-08 17:25:10 -05:00
wrongecho
e5dc50ec35 Add time by technician report 2025-03-07 22:57:18 +00:00
johnnyq
e0dfaf2d22 Fixed a few var errors in ajax contact details 2025-03-07 16:58:52 -05:00
johnnyq
757a62c35b Fix Ticket Count under contact listing 2025-03-07 16:44:38 -05:00
johnnyq
52a62fc23c Fix Client URL in recurring Invoices 2025-03-07 14:47:47 -05:00
wrongecho
44b70d7161 Add database field for ticket_first_response_at. This can be used as part of metric reporting and also as part of SLAs in the future 2025-03-07 13:28:35 +00:00
johnnyq
ad9e4b4fb4 Added new php function to retrieve and escape a single record from a specified table using an id getFieldById(table, id, field_to_retrieve, escape_method) escape method defaults to SQL but html and json and int can be specified 2025-03-04 13:45:21 -05:00
johnnyq
4fdd5ae769 Fix Bug adding software license if no vendor is selected 2025-03-04 00:13:21 -05:00
588 changed files with 129200 additions and 5843 deletions

View File

@@ -2,6 +2,67 @@
This file documents all notable changes made to ITFlow.
## [25.03]
### Fixed
- Resolved missing attachments in ticket replies processed via the email parser.
- Fixed issue where the top half of portrait image uploads appeared cut off at the bottom.
- Ensured all tables and fields use `CHARACTER SET utf8mb4` and `COLLATE utf8mb4_general_ci` for updates and new installations.
- Converted `service_domains` table to use InnoDB instead of MyISAM.
- Fixed the initials function to properly handle UTF-8 characters, preventing contact-related issues.
- Interfaces can now start with `0`.
- Adjusted AI prompt handling to focus solely on content, avoiding unnecessary additions.
### Added / Changed
- Introduced bulk delete functionality for assets.
- Added the ability to redact ticket replies after a ticket is closed.
- Added support for redacting specific text while a ticket is open.
- Switched file upload hashing from SHA256 to MD5 to significantly improve performance.
- Enabled assigning multiple assets to a single ticket.
- Updated all many-to-many tables to support cascading deletes using foreign key associations, improving efficiency, performance, and data integrity.
- Enabled caching for AJAX modals to reduce repeated reloads and enhance browser performance.
- Upgraded DataTables from 2.2.1 to 2.2.2.
- Upgraded TinyMCE from 7.6.1 to 7.7.1, providing a significant performance boost.
- Added “Copy Credentials to Clipboard” button in AJAX asset and contact views.
- Renamed and reorganized several tables.
- Improved theme color organization by grouping primary colors and their related shades.
- Displayed a user icon next to contacts who have user accounts.
- New image uploads are now converted to optimized `.webp` format by default; original files are no longer saved. Existing images remain unchanged.
- Added international phone number support throughout the system.
- Introduced user signatures in preferences, which are now appended to all ticket replies.
- Optimized search filters to only display defined tags.
- Added “Projects” to the client-side navigation.
- Enabled “Create New Ticket” from within project details.
- Reintroduced batch payment functionality in client invoices.
- Included client abbreviations in both client and global search options.
- Added assigned software license details (User/Asset) to the client PDF export.
- Replaced client-side `pdfMake` with the PHP-based `TCPDF` library for generating client export runbooks.
- Introduced the ability to download documents as PDFs.
- Added a “Reference” field to tickets and invoices generated from recurring templates (not yet in active use).
### Breaking Changes
> **Important:** To update to this version, you **must** run the following commands from the command line from the scripts directory:
>
> ```bash
> php update_cli.php
> php update_cli.php --db_update
> ```
>
> Repeat `--db_update` until no further updates are found.
>
> **Back up your system before upgrading.**
> This version includes numerous backend changes critical for future development.
## [25.02.4]
### Fixed
- Resolved issue preventing the addition or editing of licenses when no vendor was selected.
- Fixed several undeclared variables in AJAX contact details.
- Corrected the contact ticket count display.
- Addressed an issue where clicking "More Details" in AJAX contact/asset details failed to include the `client_id` in the URL.
- Fixed an issue with recurring invoices in the client URL: clicking "Inactive" or "Active" would unexpectedly navigate away from the client section.
- Added new php function getFieldById() to return a record using just an id and sanitized as well.
## [25.02.3]
### Fixed

View File

@@ -1,7 +1,7 @@
<?php
// Default Column Sortby Filter
$sort = "user_role_is_admin";
$sort = "role_is_admin";
$order = "DESC";
require_once "includes/inc_all_admin.php";
@@ -13,8 +13,8 @@ $url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM user_roles
WHERE (user_roles.user_role_name LIKE '%$q%' OR user_roles.user_role_description LIKE '%$q%')
AND user_roles.user_role_archived_at IS NULL
WHERE (role_name LIKE '%$q%' OR role_description LIKE '%$q%')
AND role_archived_at IS NULL
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
@@ -53,14 +53,14 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_role_name&order=<?php echo $disp; ?>">
Role <?php if ($sort == 'user_role_name') { echo $order_icon; } ?>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=role_name&order=<?php echo $disp; ?>">
Role <?php if ($sort == 'role_name') { echo $order_icon; } ?>
</a>
</th>
<th>Members</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_role_is_admin&order=<?php echo $disp; ?>">
Admin <?php if ($sort == 'user_role_is_admin') { echo $order_icon; } ?>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=role_is_admin&order=<?php echo $disp; ?>">
Admin <?php if ($sort == 'role_is_admin') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
@@ -70,17 +70,17 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
while ($row = mysqli_fetch_array($sql)) {
$role_id = intval($row['user_role_id']);
$role_name = nullable_htmlentities($row['user_role_name']);
$role_description = nullable_htmlentities($row['user_role_description']);
$role_admin = intval($row['user_role_is_admin']);
$role_archived_at = nullable_htmlentities($row['user_role_archived_at']);
$role_id = intval($row['role_id']);
$role_name = nullable_htmlentities($row['role_name']);
$role_description = nullable_htmlentities($row['role_description']);
$role_admin = intval($row['role_is_admin']);
$role_archived_at = nullable_htmlentities($row['role_archived_at']);
// Count number of users that have each role
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(users.user_id) FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role = $role_id AND user_archived_at IS NULL");
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(user_id) FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
$role_user_count = mysqli_fetch_row($sql_role_user_count)[0];
$sql_users = mysqli_query($mysqli, "SELECT * FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role = $role_id AND user_archived_at IS NULL");
$sql_users = mysqli_query($mysqli, "SELECT * FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
// Initialize an empty array to hold user names
$user_names = [];
@@ -90,7 +90,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
}
// Convert the array of user names to a comma-separated string
$user_names_string = implode(",", $user_names) ;
$user_names_string = implode(",", $user_names);
if (empty($user_names_string)) {
$user_names_string = "-";

View File

@@ -12,7 +12,8 @@ $company_address = nullable_htmlentities($row['company_address']);
$company_city = nullable_htmlentities($row['company_city']);
$company_state = nullable_htmlentities($row['company_state']);
$company_zip = nullable_htmlentities($row['company_zip']);
$company_phone = formatPhoneNumber($row['company_phone']);
$company_phone_country_code = formatPhoneNumber($row['company_phone_country_code']);
$company_phone = nullable_htmlentities(formatPhoneNumber($row['company_phone'], $company_phone_country_code));
$company_email = nullable_htmlentities($row['company_email']);
$company_website = nullable_htmlentities($row['company_website']);
$company_logo = nullable_htmlentities($row['company_logo']);
@@ -110,13 +111,18 @@ $company_initials = nullable_htmlentities(initials($company_name));
</div>
</div>
<div class="form-group">
<label>Phone</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
<label>Phone</label>
<div class="form-row">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="tel" class="form-control col-2" name="phone_country_code" value="+<?php echo $company_phone_country_code; ?>" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="phone" value="<?php echo $company_phone; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" value="<?php echo $company_phone; ?>">
</div>
</div>
@@ -152,4 +158,3 @@ $company_initials = nullable_htmlentities(initials($company_name));
<?php
require_once "includes/footer.php";

View File

@@ -218,28 +218,6 @@ require_once "includes/inc_all_admin.php";
</div>
</div>
<div class="form-group">
<label>Phone Mask</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-phone"></i></span>
</div>
<select class="form-control select2" name="phone_mask">
<?php
$sql = mysqli_query($mysqli, "SELECT config_phone_mask FROM settings WHERE company_id = 1");
while ($row = mysqli_fetch_array($sql)) {
$phone_mask = intval($row['config_phone_mask']);
} ?>
<option <?php if ($phone_mask == 1) { echo "selected"; }?> value=1>
US Format - e.g. (412) 888-9999
</option>
<option <?php if ($phone_mask == 0) { echo "selected"; }?> value=0>
Non-US Format - e.g. 4128889999
</option>
</select>
</div>
</div>
<hr>
<button type="submit" name="edit_default_settings" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>

View File

@@ -77,7 +77,7 @@ require_once "includes/inc_all_admin.php";
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-barcode"></i></span>
</div>
<input type="text" class="form-control" name="config_recurring_prefix" placeholder="Recurring Prefix" value="<?php echo nullable_htmlentities($config_recurring_prefix); ?>" required>
<input type="text" class="form-control" name="config_recurring_invoice_prefix" placeholder="Recurring Invoice Prefix" value="<?php echo nullable_htmlentities($config_recurring_invoice_prefix); ?>" required>
</div>
</div>
@@ -87,7 +87,7 @@ require_once "includes/inc_all_admin.php";
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-barcode"></i></span>
</div>
<input type="number" min="0" class="form-control" name="config_recurring_next_number" placeholder="Next Recurring Number" value="<?php echo intval($config_recurring_next_number); ?>" required>
<input type="number" min="0" class="form-control" name="config_recurring_invoice_next_number" placeholder="Next Recurring Invoice Number" value="<?php echo intval($config_recurring_invoice_next_number); ?>" required>
</div>
</div>

View File

@@ -19,7 +19,7 @@ require_once "includes/inc_all_admin.php";
?>
<div class="col-3 text-center mb-3">
<div class="col-4 text-center mb-3">
<div class="form-group">
<div class="custom-control custom-radio">
<input class="custom-control-input" type="radio" onchange="this.form.submit()" id="customRadio<?php echo $theme_color; ?>" name="edit_theme_settings" value="<?php echo $theme_color; ?>" <?php if ($config_theme == $theme_color) { echo "checked"; } ?>>

View File

@@ -6,16 +6,13 @@ $order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM users, user_settings, user_roles
WHERE users.user_id = user_settings.user_id
AND user_settings.user_role = user_roles.user_role_id
AND (user_name LIKE '%$q%' OR user_email LIKE '%$q%')
"SELECT SQL_CALC_FOUND_ROWS * FROM users
LEFT JOIN user_roles ON user_role_id = role_id
LEFT JOIN user_settings ON users.user_id = user_settings.user_id
WHERE (user_name LIKE '%$q%' OR user_email LIKE '%$q%')
AND user_type = 1
AND user_archived_at IS NULL
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
@@ -36,6 +33,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="dropdown-menu">
<!--<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#userInviteModal"><i class="fas fa-paper-plane mr-2"></i>Invite User</a>-->
<?php if ($num_rows[0] > 1) { ?>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#exportUserModal"><i class="fa fa-fw fa-download mr-2"></i>Export</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="#" data-toggle="modal" data-target="#resetAllUserPassModal"><i class="fas fa-skull-crossbones mr-2"></i>IR</a>
<?php } ?>
@@ -55,9 +53,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
<div class="col-md-8">
<div class="float-right">
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#exportUserModal"><i class="fa fa-fw fa-download mr-2"></i>Export</button>
</div>
</div>
</div>
</form>
@@ -77,8 +72,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_role&order=<?php echo $disp; ?>">
Role <?php if ($sort == 'user_role') { echo $order_icon; } ?>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=role_name&order=<?php echo $disp; ?>">
Role <?php if ($sort == 'role_name') { echo $order_icon; } ?>
</a>
</th>
<th>
@@ -116,8 +111,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$mfa_status_display = "<i class='fas fa-fw fa-lock text-success'></i>";
}
$user_config_force_mfa = intval($row['user_config_force_mfa']);
$user_role = $row['user_role'];
$user_role_display = nullable_htmlentities($row['user_role_name']);
$user_role = intval($row['user_role_id']);
$user_role_display = nullable_htmlentities($row['role_name']);
$user_initials = nullable_htmlentities(initials($user_name));
$sql_last_login = mysqli_query(
@@ -139,7 +134,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
}
// Get User Client Access Permissions
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id FROM user_permissions WHERE user_id = $user_id");
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id FROM user_client_permissions WHERE user_id = $user_id");
$client_access_array = [];
while ($row = mysqli_fetch_assoc($user_client_access_sql)) {
$client_access_array[] = intval($row['client_id']);
@@ -241,4 +236,4 @@ require_once "modals/admin_user_add_modal.php";
require_once "modals/admin_user_invite_modal.php";
require_once "modals/admin_user_export_modal.php";
require_once "modals/admin_user_all_reset_password_modal.php";
require_once "includes/footer.php";
require_once "includes/footer.php";

View File

@@ -8,7 +8,7 @@
require_once "config.php";
require_once "functions.php";
require_once "check_login.php";
require_once "includes/check_login.php";
require_once "plugins/totp/totp.php";
/*
@@ -165,7 +165,7 @@ if (isset($_GET['ticket_query_views'])) {
}
/*
* Generates public/guest links for sharing logins/docs
* Generates public/guest links for sharing credentials/docs
*/
if (isset($_GET['share_generate_link'])) {
enforceUserPermission('module_support', 2);
@@ -207,23 +207,23 @@ if (isset($_GET['share_generate_link'])) {
$item_name = sanitizeInput($row['file_name']);
}
if ($item_type == "Login") {
$login = mysqli_query($mysqli, "SELECT login_name, login_username, login_password FROM logins WHERE login_id = $item_id AND login_client_id = $client_id LIMIT 1");
$row = mysqli_fetch_array($login);
if ($item_type == "Credential") {
$credential = mysqli_query($mysqli, "SELECT credential_name, credential_username, credential_password FROM credentials WHERE credential_id = $item_id AND credential_client_id = $client_id LIMIT 1");
$row = mysqli_fetch_array($credential);
$item_name = sanitizeInput($row['login_name']);
$item_name = sanitizeInput($row['credential_name']);
// Decrypt & re-encrypt username/password for sharing
$login_encryption_key = randomString();
$credential_encryption_key = randomString();
$login_username_cleartext = decryptLoginEntry($row['login_username']);
$credential_username_cleartext = decryptCredentialEntry($row['credential_username']);
$iv = randomString();
$username_ciphertext = openssl_encrypt($login_username_cleartext, 'aes-128-cbc', $login_encryption_key, 0, $iv);
$username_ciphertext = openssl_encrypt($credential_username_cleartext, 'aes-128-cbc', $credential_encryption_key, 0, $iv);
$item_encrypted_username = $iv . $username_ciphertext;
$login_password_cleartext = decryptLoginEntry($row['login_password']);
$credential_password_cleartext = decryptCredentialEntry($row['credential_password']);
$iv = randomString();
$password_ciphertext = openssl_encrypt($login_password_cleartext, 'aes-128-cbc', $login_encryption_key, 0, $iv);
$password_ciphertext = openssl_encrypt($credential_password_cleartext, 'aes-128-cbc', $credential_encryption_key, 0, $iv);
$item_encrypted_credential = $iv . $password_ciphertext;
}
@@ -232,8 +232,8 @@ if (isset($_GET['share_generate_link'])) {
$share_id = $mysqli->insert_id;
// Return URL
if ($item_type == "Login") {
$url = "https://$config_base_url/guest/guest_view_item.php?id=$share_id&key=$item_key&ek=$login_encryption_key";
if ($item_type == "Credential") {
$url = "https://$config_base_url/guest/guest_view_item.php?id=$share_id&key=$item_key&ek=$credential_encryption_key";
}
else {
$url = "https://$config_base_url/guest/guest_view_item.php?id=$share_id&key=$item_key";
@@ -242,7 +242,7 @@ if (isset($_GET['share_generate_link'])) {
$sql = mysqli_query($mysqli,"SELECT * FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone']));
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
// Sanitize Config vars from get_settings.php
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
@@ -333,24 +333,24 @@ if (isset($_GET['get_client_contacts'])) {
if (isset($_GET['get_totp_token_via_id'])) {
enforceUserPermission('module_credential');
$login_id = intval($_GET['login_id']);
$credential_id = intval($_GET['credential_id']);
$sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT login_name, login_otp_secret, login_client_id FROM logins WHERE login_id = $login_id"));
$name = sanitizeInput($sql['login_name']);
$totp_secret = $sql['login_otp_secret'];
$client_id = intval($sql['login_client_id']);
$sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT credential_name, credential_otp_secret, credential_client_id FROM credentials WHERE credential_id = $credential_id"));
$name = sanitizeInput($sql['credential_name']);
$totp_secret = $sql['credential_otp_secret'];
$client_id = intval($sql['credential_client_id']);
$otp = TokenAuth6238::getTokenCode(strtoupper($totp_secret));
echo json_encode($otp);
// Logging
// Only log the TOTP view if the user hasn't already viewed this specific login entry recently, this prevents logs filling if a user hovers across an entry a few times
$check_recent_totp_view_logged_sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(log_id) AS recent_totp_view FROM logs WHERE log_type = 'Login' AND log_action = 'View TOTP' AND log_user_id = $session_user_id AND log_entity_id = $login_id AND log_client_id = $client_id AND log_created_at > (NOW() - INTERVAL 5 MINUTE)"));
$check_recent_totp_view_logged_sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(log_id) AS recent_totp_view FROM logs WHERE log_type = 'Credential' AND log_action = 'View TOTP' AND log_user_id = $session_user_id AND log_entity_id = $credential_id AND log_client_id = $client_id AND log_created_at > (NOW() - INTERVAL 5 MINUTE)"));
$recent_totp_view_logged_count = intval($check_recent_totp_view_logged_sql['recent_totp_view']);
if ($recent_totp_view_logged_count == 0) {
// Logging
logAction("Credential", "View TOTP", "$session_name viewed credential TOTP code for $name", $client_id, $login_id);
logAction("Credential", "View TOTP", "$session_name viewed credential TOTP code for $name", $client_id, $credential_id);
}
}
@@ -444,10 +444,10 @@ if (isset($_POST['update_kanban_ticket'])) {
$config_base_url = sanitizeInput($config_base_url);
// Get Company Info
$sql = mysqli_query($mysqli, "SELECT company_name, company_phone FROM companies WHERE company_id = 1");
$sql = mysqli_query($mysqli, "SELECT company_name, company_phone, company_phone_country_code FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone']));
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
// EMAIL
$subject = "Ticket resolved - [$ticket_prefix$ticket_number] - $ticket_subject | (pending closure)";
@@ -599,4 +599,3 @@ if (isset($_POST['update_recurring_invoice_items_order'])) {
echo json_encode(['status' => 'success']);
exit;
}

View File

@@ -50,6 +50,7 @@ $device_icon = getAssetIcon($asset_type);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_phone = nullable_htmlentities($row['contact_phone']);
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = nullable_htmlentities($row['contact_mobile']);
$contact_archived_at = nullable_htmlentities($row['contact_archived_at']);
if ($contact_archived_at) {
@@ -111,46 +112,53 @@ $interface_count = mysqli_num_rows($sql_related_interfaces);
// Related Credentials Query
$sql_related_credentials = mysqli_query($mysqli, "
SELECT
logins.login_id AS login_id,
logins.login_name,
logins.login_description,
logins.login_uri,
logins.login_username,
logins.login_password,
logins.login_otp_secret,
logins.login_note,
logins.login_important,
logins.login_contact_id,
logins.login_asset_id
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
WHERE login_asset_id = $asset_id
AND login_archived_at IS NULL
GROUP BY logins.login_id
ORDER BY login_name DESC
credentials.credential_id AS credential_id,
credentials.credential_name,
credentials.credential_description,
credentials.credential_uri,
credentials.credential_username,
credentials.credential_password,
credentials.credential_otp_secret,
credentials.credential_note,
credentials.credential_important,
credentials.credential_contact_id,
credentials.credential_asset_id
FROM credentials
LEFT JOIN credential_tags ON credential_tags.credential_id = credentials.credential_id
LEFT JOIN tags ON tags.tag_id = credential_tags.tag_id
WHERE credential_asset_id = $asset_id
AND credential_archived_at IS NULL
GROUP BY credentials.credential_id
ORDER BY credential_name DESC
");
$credential_count = mysqli_num_rows($sql_related_credentials);
// Related Tickets Query
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
LEFT JOIN users on ticket_assigned_to = user_id
$sql_related_tickets = mysqli_query($mysqli, "
SELECT tickets.*, users.*, ticket_statuses.*
FROM tickets
LEFT JOIN users ON ticket_assigned_to = user_id
LEFT JOIN ticket_statuses ON ticket_status_id = ticket_status
WHERE ticket_asset_id = $asset_id
ORDER BY ticket_number DESC"
);
LEFT JOIN ticket_assets ON tickets.ticket_id = ticket_assets.ticket_id
WHERE ticket_asset_id = $asset_id OR ticket_assets.asset_id = $asset_id
GROUP BY tickets.ticket_id
ORDER BY ticket_number DESC
");
$ticket_count = mysqli_num_rows($sql_related_tickets);
// Related Recurring Tickets Query
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
WHERE scheduled_ticket_asset_id = $asset_id
ORDER BY scheduled_ticket_next_run DESC"
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
LEFT JOIN recurring_ticket_assets ON recurring_tickets.recurring_ticket_id = recurring_ticket_assets.recurring_ticket_id
WHERE recurring_ticket_asset_id = $asset_id OR recurring_ticket_assets.asset_id = $asset_id
GROUP BY recurring_tickets.recurring_ticket_id
ORDER BY recurring_ticket_next_run DESC"
);
$recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets);
// Related Documents
$sql_related_documents = mysqli_query($mysqli, "SELECT * FROM asset_documents
$sql_related_documents = mysqli_query($mysqli, "SELECT * FROM asset_documents
LEFT JOIN documents ON asset_documents.document_id = documents.document_id
LEFT JOIN users ON user_id = document_created_by
WHERE asset_documents.asset_id = $asset_id
AND document_archived_at IS NULL
ORDER BY document_name DESC"
@@ -446,68 +454,69 @@ ob_start();
<?php
while ($row = mysqli_fetch_array($sql_related_credentials)) {
$login_id = intval($row['login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
if (empty($login_uri)) {
$login_uri_display = "-";
$credential_id = intval($row['credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
if (empty($credential_uri)) {
$credential_uri_display = "-";
} else {
$login_uri_display = "$login_uri";
$credential_uri_display = "$credential_uri";
}
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
if (empty($login_username)) {
$login_username_display = "-";
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
if (empty($credential_username)) {
$credential_username_display = "-";
} else {
$login_username_display = "$login_username";
$credential_username_display = "$credential_username <button type='button' class='btn btn-sm clipboardjs' data-clipboard-text='$credential_username'><i class='far fa-copy text-secondary'></i></button>";
}
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_name_display_array = array();
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT * FROM login_tags LEFT JOIN tags ON login_tags.tag_id = tags.tag_id WHERE login_id = $login_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$credential_tag_name_display_array = array();
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT * FROM credential_tags LEFT JOIN tags ON credential_tags.tag_id = tags.tag_id WHERE credential_id = $credential_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_name = nullable_htmlentities($row['tag_name']);
$login_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($login_tag_color)) {
$login_tag_color = "dark";
$credential_tag_id = intval($row['tag_id']);
$credential_tag_name = nullable_htmlentities($row['tag_name']);
$credential_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($credential_tag_color)) {
$credential_tag_color = "dark";
}
$login_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($login_tag_icon)) {
$login_tag_icon = "tag";
$credential_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($credential_tag_icon)) {
$credential_tag_icon = "tag";
}
$login_tag_id_array[] = $login_tag_id;
$login_tag_name_display_array[] = "<a href='client_logins.php?client_id=$client_id&tags[]=$login_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $login_tag_color;'><i class='fa fa-fw fa-$login_tag_icon mr-2'></i>$login_tag_name</span></a>";
$credential_tag_id_array[] = $credential_tag_id;
$credential_tag_name_display_array[] = "<a href='credentials.php?client_id=$client_id&tags[]=$credential_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $credential_tag_color;'><i class='fa fa-fw fa-$credential_tag_icon mr-2'></i>$credential_tag_name</span></a>";
}
$login_tags_display = implode('', $login_tag_name_display_array);
$credential_tags_display = implode('', $credential_tag_name_display_array);
?>
<tr>
<td>
<i class="fa fa-fw fa-key text-secondary"></i>
<?php echo $login_name; ?>
<?php echo $credential_name; ?>
</td>
<td><?php echo $login_username_display; ?></td>
<td><?php echo $credential_username_display; ?></td>
<td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $login_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button type='button' class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $credential_password; ?>'><i class='far fa-copy text-secondary'></i></button>
</td>
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td><?php echo $credential_uri_display; ?></td>
</tr>
<?php
@@ -520,7 +529,7 @@ ob_start();
</table>
</div>
</div>
<!-- Include script to get TOTP code via the login ID -->
<!-- Include script to get TOTP code via the credentials ID -->
<script src="js/credential_show_otp_via_id.js"></script>
<?php } ?>
@@ -547,12 +556,13 @@ ob_start();
$ticket_number = intval($row['ticket_number']);
$ticket_subject = nullable_htmlentities($row['ticket_subject']);
$ticket_priority = nullable_htmlentities($row['ticket_priority']);
$ticket_status_id = intval($row['ticket_status_id']);
$ticket_status_name = nullable_htmlentities($row['ticket_status_name']);
$ticket_status_color = nullable_htmlentities($row['ticket_status_color']);
$ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
$ticket_updated_at = nullable_htmlentities($row['ticket_updated_at']);
if (empty($ticket_updated_at)) {
if ($ticket_status == "Closed") {
if ($ticket_status_name == "Closed") {
$ticket_updated_at_display = "<p>Never</p>";
} else {
$ticket_updated_at_display = "<p class='text-danger'>Never</p>";
@@ -573,7 +583,7 @@ ob_start();
}
$ticket_assigned_to = intval($row['ticket_assigned_to']);
if (empty($ticket_assigned_to)) {
if ($ticket_status == 5) {
if ($ticket_status_id == 5) {
$ticket_assigned_to_display = "<p>Not Assigned</p>";
} else {
$ticket_assigned_to_display = "<p class='text-danger'>Not Assigned</p>";
@@ -628,18 +638,18 @@ ob_start();
<?php
while ($row = mysqli_fetch_array($sql_related_recurring_tickets)) {
$scheduled_ticket_id = intval($row['scheduled_ticket_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$recurring_ticket_id = intval($row['recurring_ticket_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
?>
<tr>
<td class="text-bold"><?php echo $scheduled_ticket_subject ?></td>
<td><?php echo $scheduled_ticket_priority ?></td>
<td><?php echo $scheduled_ticket_frequency ?></td>
<td><?php echo $scheduled_ticket_next_run ?></td>
<td class="text-bold"><?php echo $recurring_ticket_subject ?></td>
<td><?php echo $recurring_ticket_priority ?></td>
<td><?php echo $recurring_ticket_frequency ?></td>
<td><?php echo $recurring_ticket_next_run ?></td>
</tr>
<?php } ?>
@@ -679,11 +689,6 @@ ob_start();
$seat_count = 0;
// Get Login
$login_id = intval($row['login_id']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
// Asset Licenses
$asset_licenses_sql = mysqli_query($mysqli, "SELECT asset_id FROM software_assets WHERE software_id = $software_id");
$asset_licenses_array = array();
@@ -848,7 +853,7 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<a href="asset_details.php?<?php echo $client_url; ?>asset_id=<?php echo $asset_id; ?>" class="btn btn-primary text-bold"><span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span></a>
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>" class="btn btn-primary text-bold"><span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span></a>
<a href="#" class="btn btn-secondary"
data-toggle="ajax-modal" data-ajax-url="ajax/ajax_asset_edit.php" data-ajax-id="<?php echo $asset_id; ?>">
<span class="text-white"><i class="fas fa-edit mr-2"></i>Edit</span>

View File

@@ -4,7 +4,7 @@ require_once '../includes/ajax_header.php';
$event_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id WHERE event_id = $event_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM calendar_events LEFT JOIN calendars ON event_calendar_id = calendar_id WHERE event_id = $event_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$event_title = nullable_htmlentities($row['event_title']);

View File

@@ -9,7 +9,7 @@ $sql = mysqli_query($mysqli, "SELECT * FROM contacts
LEFT JOIN locations ON location_id = contact_location_id
LEFT JOIN users ON user_id = contact_user_id
WHERE contact_id = $contact_id
$client_query
LIMIT 1
");
$row = mysqli_fetch_array($sql);
@@ -18,9 +18,11 @@ $client_name = nullable_htmlentities($row['client_name']);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_department =nullable_htmlentities($row['contact_department']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_mobile_country_code));
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_photo = nullable_htmlentities($row['contact_photo']);
$contact_pin = nullable_htmlentities($row['contact_pin']);
@@ -51,21 +53,21 @@ $software_count = mysqli_num_rows($sql_linked_software);
$linked_software = array();
// Related Logins Query 1 to 1 relationship
$sql_related_logins = mysqli_query($mysqli, "
// Related Credentials Query 1 to 1 relationship
$sql_related_credentials = mysqli_query($mysqli, "
SELECT
logins.login_id AS logins_login_id, -- Alias for logins.login_id
logins.*, -- All other columns from logins
login_tags.*, -- All columns from login_tags
credentials.credential_id AS credentials_credential_id, -- Alias for credentials.credential_id
credentials.*, -- All other columns from credentials
credential_tags.*, -- All columns from credential_tags
tags.* -- All columns from tags
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
WHERE login_contact_id = $contact_id
GROUP BY logins.login_id
ORDER BY login_name DESC
FROM credentials
LEFT JOIN credential_tags ON credential_tags.credential_id = credentials.credential_id
LEFT JOIN tags ON tags.tag_id = credential_tags.tag_id
WHERE credential_contact_id = $contact_id
GROUP BY credentials.credential_id
ORDER BY credential_name DESC
");
$credential_count = mysqli_num_rows($sql_related_logins);
$credential_count = mysqli_num_rows($sql_related_credentials);
// Related Tickets Query - 1 to 1 relationship
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
@@ -75,9 +77,9 @@ $sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
$ticket_count = mysqli_num_rows($sql_related_tickets);
// Related Recurring Tickets Query
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
WHERE scheduled_ticket_contact_id = $contact_id
ORDER BY scheduled_ticket_next_run DESC"
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
WHERE recurring_ticket_contact_id = $contact_id
ORDER BY recurring_ticket_next_run DESC"
);
$recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets);
@@ -114,7 +116,7 @@ $sql_linked_services = mysqli_query($mysqli, "SELECT * FROM service_contacts, se
AND service_contacts.service_id = services.service_id
ORDER BY service_name ASC"
);
$service_count = mysqli_num_rows($sql_linked_services);
$services_count = mysqli_num_rows($sql_linked_services);
$linked_services = array();
@@ -189,11 +191,6 @@ ob_start();
<a class="nav-link" data-toggle="pill" href="#pills-contact-recurring-tickets<?php echo $contact_id; ?>"><i class="fas fa-fw fa-redo-alt fa-2x"></i><br>Rcr Tickets (<?php echo $recurring_ticket_count; ?>)</a>
</li>
<?php } ?>
<?php if ($services_count) { ?>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-services<?php echo $contact_id; ?>"><i class="fas fa-fw fa-stream fa-2x"></i><br>Services (<?php echo $services_count; ?>)</a>
</li>
<?php } ?>
<?php if ($document_count) { ?>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-documents<?php echo $contact_id; ?>"><i class="fas fa-fw fa-file-alt fa-2x"></i><br>Documents (<?php echo $document_count; ?>)</a>
@@ -244,7 +241,7 @@ ob_start();
<div><i class="fa fa-fw fa-map-marker-alt text-secondary mr-2"></i><?php echo $location_name; ?></div>
<?php }
if ($contact_email) { ?>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-2"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-2"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button type="button" class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<?php }
if ($contact_phone) { ?>
<div class="mt-2"><i class="fa fa-fw fa-phone text-secondary mr-2"></i><a href="tel:<?php echo "$contact_phone"?>"><?php echo $contact_phone; ?></a></div>
@@ -404,7 +401,7 @@ ob_start();
<?php if ($credential_count) { ?>
<div class="tab-pane fade" id="pills-contact-credentials<?php echo $contact_id; ?>">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm">
<table class="table table-striped table-borderless table-hover table-sm dataTables" style="width:100%">
<thead>
<tr>
<th>Name</th>
@@ -418,68 +415,70 @@ ob_start();
<tbody>
<?php
while ($row = mysqli_fetch_array($sql_related_logins)) {
$login_id = intval($row['logins_login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
if (empty($login_uri)) {
$login_uri_display = "-";
while ($row = mysqli_fetch_array($sql_related_credentials)) {
$credential_id = intval($row['credentials_credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
if (empty($credential_uri)) {
$credential_uri_display = "-";
} else {
$login_uri_display = "$login_uri";
$credential_uri_display = "$credential_uri";
}
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
if (empty($login_username)) {
$login_username_display = "-";
$credential_uri_2 = nullable_htmlentities($row['credential_uri_2']);
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
if (empty($credential_username)) {
$credential_username_display = "-";
} else {
$login_username_display = "$login_username";
$credential_username_display = "$credential_username <button type='button' class='btn btn-sm clipboardjs' data-clipboard-text='$credential_username'><i class='far fa-copy text-secondary'></i></button>";
}
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_name_display_array = array();
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT * FROM login_tags LEFT JOIN tags ON login_tags.tag_id = tags.tag_id WHERE login_id = $login_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$credential_tag_name_display_array = array();
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT * FROM credential_tags LEFT JOIN tags ON credential_tags.tag_id = tags.tag_id WHERE credential_id = $credential_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_name = nullable_htmlentities($row['tag_name']);
$login_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($login_tag_color)) {
$login_tag_color = "dark";
$credential_tag_id = intval($row['tag_id']);
$credential_tag_name = nullable_htmlentities($row['tag_name']);
$credential_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($credential_tag_color)) {
$credential_tag_color = "dark";
}
$login_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($login_tag_icon)) {
$login_tag_icon = "tag";
$credential_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($credential_tag_icon)) {
$credential_tag_icon = "tag";
}
$login_tag_id_array[] = $login_tag_id;
$login_tag_name_display_array[] = "<a href='client_logins.php?client_id=$client_id&tags[]=$login_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $login_tag_color;'><i class='fa fa-fw fa-$login_tag_icon mr-2'></i>$login_tag_name</span></a>";
$credential_tag_id_array[] = $credential_tag_id;
$credential_tag_name_display_array[] = "<a href='credentials.php?client_id=$client_id&tags[]=$credential_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $credential_tag_color;'><i class='fa fa-fw fa-$credential_tag_icon mr-2'></i>$credential_tag_name</span></a>";
}
$login_tags_display = implode('', $login_tag_name_display_array);
$credential_tags_display = implode('', $credential_tag_name_display_array);
?>
<tr>
<td><i class="fa fa-fw fa-key text-secondary mr-2"></i><?php echo $login_name; ?></td>
<td><?php echo $login_description; ?></td>
<td><?php echo $login_username_display; ?></td>
<td><i class="fa fa-fw fa-key text-secondary mr-2"></i><?php echo $credential_name; ?></td>
<td><?php echo $credential_description; ?></td>
<td><?php echo $credential_username_display; ?></td>
<td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $login_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button type="button" class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $credential_password; ?>'><i class='far fa-copy text-secondary'></i></button>
</td>
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td><?php echo $credential_uri_display; ?></td>
</tr>
<?php
@@ -492,7 +491,7 @@ ob_start();
</table>
</div>
</div>
<!-- Include script to get TOTP code via the login ID -->
<!-- Include script to get TOTP code via the credential ID -->
<script src="js/credential_show_otp_via_id.js"></script>
<?php } ?>
@@ -597,18 +596,18 @@ ob_start();
<?php
while ($row = mysqli_fetch_array($sql_related_recurring_tickets)) {
$scheduled_ticket_id = intval($row['scheduled_ticket_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$recurring_ticket_id = intval($row['recurring_ticket_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
?>
<tr>
<td class="text-bold"><?php echo $scheduled_ticket_subject ?></td>
<td><?php echo $scheduled_ticket_priority ?></td>
<td><?php echo $scheduled_ticket_frequency ?></td>
<td><?php echo $scheduled_ticket_next_run ?></td>
<td class="text-bold"><?php echo $recurring_ticket_subject ?></td>
<td><?php echo $recurring_ticket_priority ?></td>
<td><?php echo $recurring_ticket_frequency ?></td>
<td><?php echo $recurring_ticket_next_run ?></td>
</tr>
<?php } ?>
@@ -846,7 +845,7 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<a href="contact_details.php?<?php echo $client_url; ?>contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold">
<a href="contact_details.php?client_id=<?php echo $client_id; ?>&contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold">
<span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span>
</a>
<a href="#" class="btn btn-secondary"

View File

@@ -16,8 +16,10 @@ $contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_department = nullable_htmlentities($row['contact_department']);
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_mobile_country_code));
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_pin = nullable_htmlentities($row['contact_pin']);
$contact_photo = nullable_htmlentities($row['contact_photo']);
@@ -111,30 +113,38 @@ ob_start();
</div>
</div>
<label>Phone</label>
<label>Phone / <span class="text-secondary">Extension</span></label>
<div class="form-row">
<div class="col-8">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200" value="<?php echo $contact_phone; ?>">
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo "+$contact_phone_country_code"; ?>" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="phone" value="<?php echo $contact_phone; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
</div>
<div class="col-4">
<input type="text" class="form-control" name="extension" placeholder="Extension" maxlength="200" value="<?php echo $contact_extension; ?>">
<div class="col-3">
<div class="form-group">
<input type="text" class="form-control" name="extension" value="<?php echo $contact_extension; ?>" placeholder="ext." maxlength="200">
</div>
</div>
</div>
<div class="form-group">
<label>Mobile</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
<label>Mobile</label>
<div class="form-row">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
</div>
<input type="tel" class="form-control col-2" name="mobile_country_code" value="<?php echo "+$contact_mobile_country_code"; ?>" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="mobile" value="<?php echo $contact_mobile; ?>" placeholder="Phone Number">
</div>
</div>
<input type="text" class="form-control" name="mobile" placeholder="Mobile Phone Number" maxlength="200" value="<?php echo $contact_mobile; ?>">
</div>
</div>

View File

@@ -2,33 +2,32 @@
require_once '../includes/ajax_header.php';
$login_id = intval($_GET['id']);
$credential_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = $login_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = $credential_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$client_id = intval($row['login_client_id']);
$login_id = intval($row['login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_note = nullable_htmlentities($row['login_note']);
$login_created_at = nullable_htmlentities($row['login_created_at']);
$login_archived_at = nullable_htmlentities($row['login_archived_at']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$client_id = intval($row['credential_client_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
$credential_uri_2 = nullable_htmlentities($row['credential_uri_2']);
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_created_at = nullable_htmlentities($row['credential_created_at']);
$credential_archived_at = nullable_htmlentities($row['credential_archived_at']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT tag_id FROM login_tags WHERE login_id = $login_id");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_id_array[] = $login_tag_id;
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT tag_id FROM credential_tags WHERE credential_id = $credential_id");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$credential_tag_id = intval($row['tag_id']);
$credential_tag_id_array[] = $credential_tag_id;
}
// Generate the HTML form content using output buffering.
@@ -36,26 +35,26 @@ ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class='fas fa-fw fa-key mr-2'></i>Editing credential: <strong><?php echo $login_name; ?></strong></h5>
<h5 class="modal-title"><i class='fas fa-fw fa-key mr-2'></i>Editing credential: <strong><?php echo $credential_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="login_id" value="<?php echo $login_id; ?>">
<input type="hidden" name="credential_id" value="<?php echo $credential_id; ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<div class="modal-body bg-white">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-login-details<?php echo $login_id; ?>">Details</a>
<a class="nav-link active" data-toggle="pill" href="#pills-credential-details<?php echo $credential_id; ?>">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-login-relation<?php echo $login_id; ?>">Relation</a>
<a class="nav-link" data-toggle="pill" href="#pills-credential-relation<?php echo $credential_id; ?>">Relation</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-login-notes<?php echo $login_id; ?>">Notes</a>
<a class="nav-link" data-toggle="pill" href="#pills-credential-notes<?php echo $credential_id; ?>">Notes</a>
</li>
</ul>
@@ -63,7 +62,7 @@ ob_start();
<div class="tab-content" <?php if (lookupUserPermission('module_credential') <= 1) { echo 'inert'; } ?>>
<div class="tab-pane fade show active" id="pills-login-details<?php echo $login_id; ?>">
<div class="tab-pane fade show active" id="pills-credential-details<?php echo $credential_id; ?>">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong> / <span class="text-secondary">Important?</span></label>
@@ -71,10 +70,10 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Name of Login" maxlength="200" value="<?php echo $login_name; ?>" required>
<input type="text" class="form-control" name="name" placeholder="Name of Credential" maxlength="200" value="<?php echo $credential_name; ?>" required>
<div class="input-group-append">
<div class="input-group-text">
<input type="checkbox" name="important" value="1" <?php if ($login_important == 1) { echo "checked"; } ?>>
<input type="checkbox" name="important" value="1" <?php if ($credential_important == 1) { echo "checked"; } ?>>
</div>
</div>
</div>
@@ -86,7 +85,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
</div>
<input type="text" class="form-control" name="description" placeholder="Description" value="<?php echo $login_description; ?>">
<input type="text" class="form-control" name="description" placeholder="Description" value="<?php echo $credential_description; ?>">
</div>
</div>
@@ -96,7 +95,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<input type="text" class="form-control" name="username" placeholder="Username or ID" maxlength="350" value="<?php echo $login_username; ?>">
<input type="text" class="form-control" name="username" placeholder="Username or ID" maxlength="350" value="<?php echo $credential_username; ?>">
</div>
</div>
@@ -106,12 +105,12 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
</div>
<input type="password" class="form-control" data-toggle="password" name="password" placeholder="Password or Key" maxlength="350" value="<?php echo $login_password; ?>" required autocomplete="new-password">
<input type="password" class="form-control" data-toggle="password" name="password" placeholder="Password or Key" maxlength="350" value="<?php echo $credential_password; ?>" required autocomplete="new-password">
<div class="input-group-append">
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
</div>
<div class="input-group-append">
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $login_password; ?>"><i class="fa fa-fw fa-copy"></i></button>
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $credential_password; ?>"><i class="fa fa-fw fa-copy"></i></button>
</div>
</div>
</div>
@@ -122,7 +121,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="password" class="form-control" data-toggle="password" name="otp_secret" maxlength="200" value="<?php echo $login_otp_secret; ?>" placeholder="Insert secret key">
<input type="password" class="form-control" data-toggle="password" name="otp_secret" maxlength="200" value="<?php echo $credential_otp_secret; ?>" placeholder="Insert secret key">
<div class="input-group-append">
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
</div>
@@ -135,13 +134,13 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-link"></i></span>
</div>
<input type="text" class="form-control" name="uri" placeholder="ex. http://192.168.1.1" maxlength="500" value="<?php echo $login_uri; ?>">
<input type="text" class="form-control" name="uri" placeholder="ex. http://192.168.1.1" maxlength="500" value="<?php echo $credential_uri; ?>">
<div class="input-group-append">
<a href="<?php echo $login_uri; ?>" class="input-group-text"><i class="fa fa-fw fa-link"></i></a>
<a href="<?php echo $credential_uri; ?>" class="input-group-text"><i class="fa fa-fw fa-link"></i></a>
</div>
<div class="input-group-append">
<button class="input-group-text clipboardjs" type="button" data-clipboard-text="<?php echo $login_uri; ?>"><i class="fa fa-fw fa-copy"></i></button>
<button class="input-group-text clipboardjs" type="button" data-clipboard-text="<?php echo $credential_uri; ?>"><i class="fa fa-fw fa-copy"></i></button>
</div>
</div>
</div>
@@ -152,19 +151,19 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-link"></i></span>
</div>
<input type="text" class="form-control" name="uri_2" placeholder="ex. https://server.company.com:5001" maxlength="500" value="<?php echo $login_uri_2; ?>">
<input type="text" class="form-control" name="uri_2" placeholder="ex. https://server.company.com:5001" maxlength="500" value="<?php echo $credential_uri_2; ?>">
<div class="input-group-append">
<a href="<?php echo $login_uri_2; ?>" class="input-group-text"><i class="fa fa-fw fa-link"></i></a>
<a href="<?php echo $credential_uri_2; ?>" class="input-group-text"><i class="fa fa-fw fa-link"></i></a>
</div>
<div class="input-group-append">
<button class="input-group-text clipboardjs" type="button" data-clipboard-text="<?php echo $login_uri_2; ?>"><i class="fa fa-fw fa-copy"></i></button>
<button class="input-group-text clipboardjs" type="button" data-clipboard-text="<?php echo $credential_uri_2; ?>"><i class="fa fa-fw fa-copy"></i></button>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-login-relation<?php echo $login_id; ?>">
<div class="tab-pane fade" id="pills-credential-relation<?php echo $credential_id; ?>">
<div class="form-group">
<label>Contact</label>
@@ -173,7 +172,7 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<select class="form-control select2" name="contact">
<option value="">- Contact -</option>
<option value="">- Select Contact -</option>
<?php
$sql_contacts = mysqli_query($mysqli, "SELECT contact_id, contact_name FROM contacts WHERE contact_client_id = $client_id ORDER BY contact_name ASC");
@@ -181,7 +180,7 @@ ob_start();
$contact_id_select = intval($row['contact_id']);
$contact_name_select = nullable_htmlentities($row['contact_name']);
?>
<option <?php if ($login_contact_id == $contact_id_select) { echo "selected"; } ?> value="<?php echo $contact_id_select; ?>"><?php echo $contact_name_select; ?></option>
<option <?php if ($credential_contact_id == $contact_id_select) { echo "selected"; } ?> value="<?php echo $contact_id_select; ?>"><?php echo $contact_name_select; ?></option>
<?php } ?>
</select>
</div>
@@ -194,7 +193,7 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<select class="form-control select2" name="asset">
<option value="0">- None -</option>
<option value="0">- Select Asset -</option>
<?php
$sql_assets = mysqli_query($mysqli, "SELECT asset_id, asset_name, location_name FROM assets LEFT JOIN locations on asset_location_id = location_id WHERE asset_client_id = $client_id AND asset_archived_at IS NULL ORDER BY asset_name ASC");
@@ -209,7 +208,7 @@ ob_start();
}
?>
<option <?php if ($login_asset_id == $asset_id_select) { echo "selected"; } ?> value="<?php echo $asset_id_select; ?>"><?php echo $asset_select_display_string; ?></option>
<option <?php if ($credential_asset_id == $asset_id_select) { echo "selected"; } ?> value="<?php echo $asset_id_select; ?>"><?php echo $asset_select_display_string; ?></option>
<?php } ?>
</select>
@@ -218,10 +217,10 @@ ob_start();
</div>
<div class="tab-pane fade" id="pills-login-notes<?php echo $login_id; ?>">
<div class="tab-pane fade" id="pills-credential-notes<?php echo $credential_id; ?>">
<div class="form-group">
<textarea class="form-control" rows="12" placeholder="Enter some notes" name="note"><?php echo $login_note; ?></textarea>
<textarea class="form-control" rows="12" placeholder="Enter some notes" name="note"><?php echo $credential_note; ?></textarea>
</div>
<div class="form-group">
@@ -238,7 +237,7 @@ ob_start();
$tag_id_select = intval($row['tag_id']);
$tag_name_select = nullable_htmlentities($row['tag_name']);
?>
<option value="<?php echo $tag_id_select; ?>" <?php if (in_array($tag_id_select, $login_tag_id_array)) { echo "selected"; } ?>><?php echo $tag_name_select; ?></option>
<option value="<?php echo $tag_id_select; ?>" <?php if (in_array($tag_id_select, $credential_tag_id_array)) { echo "selected"; } ?>><?php echo $tag_name_select; ?></option>
<?php } ?>
</select>
@@ -259,7 +258,7 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="edit_login" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="submit" name="edit_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>

View File

@@ -2,26 +2,26 @@
require_once '../includes/ajax_header.php';
$login_id = intval($_GET['id']);
$credential_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = $login_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = $credential_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
$credential_uri_2 = nullable_htmlentities($row['credential_uri_2']);
$credential_username = nullable_htmlentities(decryptLoginEntry($row['credential_username']));
$credential_password = nullable_htmlentities(decryptLoginEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_created_at = nullable_htmlentities($row['login_created_at']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_created_at = nullable_htmlentities($row['credential_created_at']);
// Generate the HTML form content using output buffering.
ob_start();

View File

@@ -14,8 +14,11 @@ $location_address = nullable_htmlentities($row['location_address']);
$location_city = nullable_htmlentities($row['location_city']);
$location_state = nullable_htmlentities($row['location_state']);
$location_zip = nullable_htmlentities($row['location_zip']);
$location_phone = formatPhoneNumber($row['location_phone']);
$location_fax = formatPhoneNumber($row['location_fax']);
$location_phone_country_code = nullable_htmlentities($row['location_phone_country_code']);
$location_phone = nullable_htmlentities(formatPhoneNumber($row['location_phone'], $location_phone_country_code));
$location_extension = formatPhoneNumber($row['location_extension']);
$location_fax_country_code = nullable_htmlentities($row['location_fax_country_code']);
$location_fax = nullable_htmlentities(formatPhoneNumber($row['location_fax'], $location_fax_country_code));
$location_hours = nullable_htmlentities($row['location_hours']);
$location_photo = nullable_htmlentities($row['location_photo']);
$location_notes = nullable_htmlentities($row['location_notes']);
@@ -198,23 +201,38 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Phone</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
<label>Phone / <span class="text-secondary">Extension</span></label>
<div class="form-row">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo "+$location_phone_country_code"; ?>" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="phone" value="<?php echo $location_phone; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
</div>
<div class="col-3">
<div class="form-group">
<input type="text" class="form-control" name="extension" value="<?php echo $location_extension; ?>" placeholder="ext." maxlength="200">
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200" value="<?php echo $location_phone; ?>">
</div>
</div>
<div class="form-group">
<label>Fax</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-fax"></i></span>
<label>Fax</label>
<div class="form-row">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-fax"></i></span>
</div>
<input type="tel" class="form-control col-2" name="fax_country_code" value="<?php echo "+$location_fax_country_code"; ?>" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="fax" value="<?php echo $location_fax; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
<input type="text" class="form-control" name="fax" placeholder="Fax Number" maxlength="200" value="<?php echo $location_fax; ?>">
</div>
</div>

View File

@@ -74,9 +74,8 @@ ob_start();
<?php
$sql_project_managers_select = mysqli_query(
$mysqli,
"SELECT users.user_id, user_name FROM users
LEFT JOIN user_settings on users.user_id = user_settings.user_id
WHERE user_role > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
"SELECT user_id, user_name FROM users
WHERE user_role_id > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
);
while ($row = mysqli_fetch_array($sql_project_managers_select)) {
$user_id_select = intval($row['user_id']);

View File

@@ -2,33 +2,33 @@
require_once '../includes/ajax_header.php';
$recurring_id = intval($_GET['id']);
$recurring_invoice_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM recurring WHERE recurring_id = $recurring_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$recurring_prefix = nullable_htmlentities($row['recurring_prefix']);
$recurring_number = intval($row['recurring_number']);
$recurring_scope = nullable_htmlentities($row['recurring_scope']);
$recurring_frequency = nullable_htmlentities($row['recurring_frequency']);
$recurring_status = nullable_htmlentities($row['recurring_status']);
$recurring_created_at = date('Y-m-d', strtotime($row['recurring_created_at']));
$recurring_next_date = nullable_htmlentities($row['recurring_next_date']);
$recurring_discount = floatval($row['recurring_discount_amount']);
$category_id = intval($row['recurring_category_id']);
$recurring_invoice_prefix = nullable_htmlentities($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$recurring_invoice_scope = nullable_htmlentities($row['recurring_invoice_scope']);
$recurring_invoice_frequency = nullable_htmlentities($row['recurring_invoice_frequency']);
$recurring_invoice_status = nullable_htmlentities($row['recurring_invoice_status']);
$recurring_invoice_created_at = date('Y-m-d', strtotime($row['recurring_invoice_created_at']));
$recurring_invoice_next_date = nullable_htmlentities($row['recurring_invoice_next_date']);
$recurring_invoice_discount = floatval($row['recurring_invoice_discount_amount']);
$category_id = intval($row['recurring_invoice_category_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-fw fa-redo-alt mr-2"></i>Editing Recur Invoice: <strong><?php echo "$recurring_prefix$recurring_number"; ?></strong></h5>
<h5 class="modal-title"><i class="fas fa-fw fa-redo-alt mr-2"></i>Editing Recur Invoice: <strong><?php echo "$recurring_invoice_prefix$recurring_invoice_number"; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="recurring_id" value="<?php echo $recurring_id; ?>">
<input type="hidden" name="recurring_invoice_id" value="<?php echo $recurring_invoice_id; ?>">
<div class="modal-body bg-white">
@@ -38,7 +38,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-comment"></i></span>
</div>
<input type="text" class="form-control" name="scope" placeholder="Quick description" maxlength="255" value="<?php echo $recurring_scope; ?>">
<input type="text" class="form-control" name="scope" placeholder="Quick description" maxlength="255" value="<?php echo $recurring_invoice_scope; ?>">
</div>
</div>
@@ -50,8 +50,8 @@ ob_start();
</div>
<select class="form-control select2" name="frequency" required>
<option value="">- Frequency -</option>
<option <?php if ($recurring_frequency == 'month') { echo "selected"; } ?> value="month">Monthly</option>
<option <?php if ($recurring_frequency == 'year') { echo "selected"; } ?> value="year">Yearly</option>
<option <?php if ($recurring_invoice_frequency == 'month') { echo "selected"; } ?> value="month">Monthly</option>
<option <?php if ($recurring_invoice_frequency == 'year') { echo "selected"; } ?> value="year">Yearly</option>
</select>
</div>
</div>
@@ -62,7 +62,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
</div>
<input type="date" class="form-control" name="next_date" max="2999-12-31" value="<?php echo $recurring_next_date; ?>" required>
<input type="date" class="form-control" name="next_date" max="2999-12-31" value="<?php echo $recurring_invoice_next_date; ?>" required>
</div>
</div>
@@ -76,7 +76,7 @@ ob_start();
<option value="">- Category -</option>
<?php
$sql_income_category = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Income' AND (category_archived_at > '$recurring_created_at' OR category_archived_at IS NULL) ORDER BY category_name ASC");
$sql_income_category = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Income' AND (category_archived_at > '$recurring_invoice_created_at' OR category_archived_at IS NULL) ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql_income_category)) {
$category_id_select = intval($row['category_id']);
$category_name_select = nullable_htmlentities($row['category_name']);
@@ -104,7 +104,7 @@ ob_start();
<div class='input-group-prepend'>
<span class='input-group-text'><i class='fa fa-fw fa-dollar-sign'></i></span>
</div>
<input type='text' class='form-control' inputmode="numeric" pattern="-?[0-9]*\.?[0-9]{0,2}" name='recurring_discount' placeholder='0.00' value="<?php echo number_format($recurring_discount, 2, '.', ''); ?>">
<input type='text' class='form-control' inputmode="numeric" pattern="-?[0-9]*\.?[0-9]{0,2}" name='recurring_invoice_discount' placeholder='0.00' value="<?php echo number_format($recurring_invoice_discount, 2, '.', ''); ?>">
</div>
</div>
@@ -115,10 +115,10 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
</div>
<select class="form-control select2" name="status" required>
<option <?php if ($recurring_status == 1) {
<option <?php if ($recurring_invoice_status == 1) {
echo "selected";
} ?> value="1">Active</option>
<option <?php if ($recurring_status == 0) {
<option <?php if ($recurring_invoice_status == 0) {
echo "selected";
} ?> value="0">InActive</option>
</select>
@@ -127,7 +127,7 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<button type="submit" name="edit_recurring" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="submit" name="edit_recurring_invoice" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>

View File

@@ -2,56 +2,64 @@
require_once '../includes/ajax_header.php';
$scheduled_ticket_id = intval($_GET['id']);
$recurring_ticket_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets WHERE scheduled_ticket_id = $scheduled_ticket_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$client_id = intval($row['scheduled_ticket_client_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_details = nullable_htmlentities($row['scheduled_ticket_details']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$scheduled_ticket_assigned_to = intval($row['scheduled_ticket_assigned_to']);
$scheduled_ticket_contact_id = intval($row['scheduled_ticket_contact_id']);
$scheduled_ticket_asset_id = intval($row['scheduled_ticket_asset_id']);
$scheduled_ticket_billable = intval($row['scheduled_ticket_billable']);
$client_id = intval($row['recurring_ticket_client_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_details = nullable_htmlentities($row['recurring_ticket_details']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
$recurring_ticket_assigned_to = intval($row['recurring_ticket_assigned_to']);
$recurring_ticket_contact_id = intval($row['recurring_ticket_contact_id']);
$recurring_ticket_asset_id = intval($row['recurring_ticket_asset_id']);
$recurring_ticket_billable = intval($row['recurring_ticket_billable']);
// Additional Assets Selected
$additional_assets_array = array();
$sql_additional_assets = mysqli_query($mysqli, "SELECT asset_id FROM recurring_ticket_assets WHERE recurring_ticket_id = $recurring_ticket_id");
while ($row = mysqli_fetch_array($sql_additional_assets)) {
$additional_asset_id = intval($row['asset_id']);
$additional_assets_array[] = $additional_asset_id;
}
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-fw fa-calendar-check mr-2"></i>Editing Recurring Ticket: <strong><?php echo $scheduled_ticket_subject; ?></strong></h5>
<h5 class="modal-title"><i class="fas fa-fw fa-calendar-check mr-2"></i>Editing Recurring Ticket: <strong><?php echo $recurring_ticket_subject; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="scheduled_ticket_id" value="<?php echo $scheduled_ticket_id; ?>">
<input type="hidden" name="recurring_ticket_id" value="<?php echo $recurring_ticket_id; ?>">
<input type="hidden" name="client" value="<?php echo $client_id; ?>">
<div class="modal-body bg-white">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-edit-details<?php echo $scheduled_ticket_id; ?>"><i class="fa fa-fw fa-life-ring mr-2"></i>Details</a>
<a class="nav-link active" data-toggle="pill" href="#pills-edit-details<?php echo $recurring_ticket_id; ?>"><i class="fa fa-fw fa-life-ring mr-2"></i>Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-edit-contacts<?php echo $scheduled_ticket_id; ?>"><i class="fa fa-fw fa-users mr-2"></i>Contacts</a>
<a class="nav-link" data-toggle="pill" href="#pills-edit-contacts<?php echo $recurring_ticket_id; ?>"><i class="fa fa-fw fa-users mr-2"></i>Contact</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-edit-schedule<?php echo $scheduled_ticket_id; ?>"><i class="fa fa-fw fa-building mr-2"></i>Schedule</a>
<a class="nav-link" data-toggle="pill" href="#pills-edit-schedule<?php echo $recurring_ticket_id; ?>"><i class="fa fa-fw fa-building mr-2"></i>Schedule</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-edit-assets<?php echo $scheduled_ticket_id; ?>"><i class="fa fa-fw fa-desktop mr-2"></i>Assets</a>
<a class="nav-link" data-toggle="pill" href="#pills-edit-assets<?php echo $recurring_ticket_id; ?>"><i class="fa fa-fw fa-desktop mr-2"></i>Assets</a>
</li>
</ul>
<div class="tab-content" <?php if (lookupUserPermission('module_support') <= 1) { echo 'inert'; } ?>>
<div class="tab-pane fade show active" id="pills-edit-details<?php echo $scheduled_ticket_id; ?>">
<div class="tab-pane fade show active" id="pills-edit-details<?php echo $recurring_ticket_id; ?>">
<div class="form-group">
<label>Subject <strong class="text-danger">*</strong></label>
@@ -59,12 +67,12 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="subject" placeholder="Subject" maxlength="500" value="<?php echo $scheduled_ticket_subject; ?>" required >
<input type="text" class="form-control" name="subject" placeholder="Subject" maxlength="500" value="<?php echo $recurring_ticket_subject; ?>" required >
</div>
</div>
<div class="form-group">
<textarea class="form-control tinymce" name="details"><?php echo $scheduled_ticket_details; ?></textarea>
<textarea class="form-control tinymce" name="details"><?php echo $recurring_ticket_details; ?></textarea>
</div>
<div class="form-group">
@@ -74,9 +82,9 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-thermometer-half"></i></span>
</div>
<select class="form-control select2" name="priority" required>
<option <?php if ($scheduled_ticket_priority == "Low") { echo "selected"; } ?> >Low</option>
<option <?php if ($scheduled_ticket_priority == "Medium") { echo "selected"; } ?> >Medium</option>
<option <?php if ($scheduled_ticket_priority == "High") { echo "selected"; } ?> >High</option>
<option <?php if ($recurring_ticket_priority == "Low") { echo "selected"; } ?> >Low</option>
<option <?php if ($recurring_ticket_priority == "Medium") { echo "selected"; } ?> >Medium</option>
<option <?php if ($recurring_ticket_priority == "High") { echo "selected"; } ?> >High</option>
</select>
</div>
</div>
@@ -100,7 +108,7 @@ ob_start();
$user_name_select = nullable_htmlentities($row['user_name']);
?>
<option value="<?php echo $user_id_select; ?>" <?php if ($scheduled_ticket_assigned_to == $user_id_select) { echo "selected"; } ?>><?php echo $user_name_select; ?></option>
<option value="<?php echo $user_id_select; ?>" <?php if ($recurring_ticket_assigned_to == $user_id_select) { echo "selected"; } ?>><?php echo $user_name_select; ?></option>
<?php } ?>
</select>
</div>
@@ -109,7 +117,7 @@ ob_start();
<div class="form-group <?php if (!$config_module_enable_accounting) { echo 'd-none'; } ?>">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="editTicketBillable" name="billable"
<?php if ($scheduled_ticket_billable == 1) { echo "checked"; } ?> value="1"
<?php if ($recurring_ticket_billable == 1) { echo "checked"; } ?> value="1"
>
<label class="custom-control-label" for="editTicketBillable">Mark Billable</label>
</div>
@@ -117,7 +125,7 @@ ob_start();
</div>
<div class="tab-pane fade" id="pills-edit-contacts<?php echo $scheduled_ticket_id; ?>">
<div class="tab-pane fade" id="pills-edit-contacts<?php echo $recurring_ticket_id; ?>">
<div class="form-group">
<label>Contact</label>
@@ -152,7 +160,7 @@ ob_start();
}
?>
<option value="<?php echo $contact_id_select; ?>" <?php if ($contact_id_select == $scheduled_ticket_contact_id) { echo "selected"; } ?>><?php echo "$contact_name_select$contact_title_display_select$contact_primary_display_select$contact_technical_display_select"; ?></option>
<option value="<?php echo $contact_id_select; ?>" <?php if ($contact_id_select == $recurring_ticket_contact_id) { echo "selected"; } ?>><?php echo "$contact_name_select$contact_title_display_select$contact_primary_display_select$contact_technical_display_select"; ?></option>
<?php } ?>
</select>
</div>
@@ -160,7 +168,7 @@ ob_start();
</div>
<div class="tab-pane fade" id="pills-edit-schedule<?php echo $scheduled_ticket_id; ?>">
<div class="tab-pane fade" id="pills-edit-schedule<?php echo $recurring_ticket_id; ?>">
<div class="form-group">
<label>Frequency <strong class="text-danger">*</strong></label>
@@ -169,11 +177,11 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-recycle"></i></span>
</div>
<select class="form-control select2" name="frequency">
<option <?php if ($scheduled_ticket_frequency == "Weekly") { echo "selected"; } ?>>Weekly</option>
<option <?php if ($scheduled_ticket_frequency == "Monthly") { echo "selected"; } ?>>Monthly</option>
<option <?php if ($scheduled_ticket_frequency == "Quarterly") { echo "selected"; } ?>>Quarterly</option>
<option <?php if ($scheduled_ticket_frequency == "Biannually") { echo "selected"; } ?>>Biannually</option>
<option <?php if ($scheduled_ticket_frequency == "Annually") { echo "selected"; } ?>>Annually</option>
<option <?php if ($recurring_ticket_frequency == "Weekly") { echo "selected"; } ?>>Weekly</option>
<option <?php if ($recurring_ticket_frequency == "Monthly") { echo "selected"; } ?>>Monthly</option>
<option <?php if ($recurring_ticket_frequency == "Quarterly") { echo "selected"; } ?>>Quarterly</option>
<option <?php if ($recurring_ticket_frequency == "Biannually") { echo "selected"; } ?>>Biannually</option>
<option <?php if ($recurring_ticket_frequency == "Annually") { echo "selected"; } ?>>Annually</option>
</select>
</div>
</div>
@@ -184,13 +192,13 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar-day"></i></span>
</div>
<input class="form-control" type="date" name="next_date" max="2999-12-31" value="<?php echo $scheduled_ticket_next_run; ?>">
<input class="form-control" type="date" name="next_date" max="2999-12-31" value="<?php echo $recurring_ticket_next_run; ?>">
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-edit-assets<?php echo $scheduled_ticket_id; ?>">
<div class="tab-pane fade" id="pills-edit-assets<?php echo $recurring_ticket_id; ?>">
<div class="form-group">
<label>Asset</label>
@@ -208,7 +216,7 @@ ob_start();
$asset_name_select = nullable_htmlentities($row['asset_name']);
$asset_contact_name_select = nullable_htmlentities($row['contact_name']);
?>
<option <?php if ($scheduled_ticket_asset_id == $asset_id_select) { echo "selected"; } ?> value="<?php echo $asset_id_select; ?>"><?php echo "$asset_name_select - $asset_contact_name_select"; ?></option>
<option <?php if ($recurring_ticket_asset_id == $asset_id_select) { echo "selected"; } ?> value="<?php echo $asset_id_select; ?>"><?php echo "$asset_name_select - $asset_contact_name_select"; ?></option>
<?php
}
@@ -217,6 +225,31 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Additional Assets</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
</div>
<select class="form-control select2" name="additional_assets[]" data-tags="true" data-placeholder="- Select Additional Assets -" multiple>
<option value=""></option>
<?php
$sql_assets = mysqli_query($mysqli, "SELECT asset_id, asset_name, contact_name FROM assets LEFT JOIN contacts ON contact_id = asset_contact_id WHERE asset_client_id = $client_id AND asset_id != $recurring_ticket_asset_id AND asset_archived_at IS NULL ORDER BY asset_name ASC");
while ($row = mysqli_fetch_array($sql_assets)) {
$asset_id_select = intval($row['asset_id']);
$asset_name_select = nullable_htmlentities($row['asset_name']);
$asset_contact_name_select = nullable_htmlentities($row['contact_name']);
?>
<option value="<?php echo $asset_id_select; ?>"
<?php if (in_array($asset_id_select, $additional_assets_array)) { echo "selected"; } ?>
><?php echo "$asset_name_select - $asset_contact_name_select"; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
</div>

View File

@@ -4,18 +4,18 @@ require_once '../includes/ajax_header.php';
$role_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE user_role_id = $role_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE role_id = $role_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$role_name = nullable_htmlentities($row['user_role_name']);
$role_description = nullable_htmlentities($row['user_role_description']);
$role_admin = intval($row['user_role_is_admin']);
$role_name = nullable_htmlentities($row['role_name']);
$role_description = nullable_htmlentities($row['role_description']);
$role_admin = intval($row['role_is_admin']);
// Count number of users that have each role
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(users.user_id) FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role = $role_id AND user_archived_at IS NULL");
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(user_id) FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
$role_user_count = mysqli_fetch_row($sql_role_user_count)[0];
$sql_users = mysqli_query($mysqli, "SELECT * FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role = $role_id AND user_archived_at IS NULL");
$sql_users = mysqli_query($mysqli, "SELECT * FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
// Initialize an empty array to hold user names
$user_names = [];

View File

@@ -28,23 +28,23 @@ if ($service_importance == "High") {
$service_importance_display = "-";
}
// Associated Assets (and their logins/networks/locations)
// Associated Assets (and their credentials/networks/locations)
$sql_assets = mysqli_query(
$mysqli,
"SELECT * FROM service_assets
LEFT JOIN assets ON service_assets.asset_id = assets.asset_id
LEFT JOIN asset_interfaces ON interface_asset_id = assets.asset_id AND interface_primary = 1
LEFT JOIN logins ON service_assets.asset_id = logins.login_asset_id
LEFT JOIN credentials ON service_assets.asset_id = credentials.credential_asset_id
LEFT JOIN networks ON interface_network_id = networks.network_id
LEFT JOIN locations ON assets.asset_location_id = locations.location_id
WHERE service_id = $service_id"
);
// Associated logins
$sql_logins = mysqli_query(
// Associated credentials
$sql_credentials = mysqli_query(
$mysqli,
"SELECT * FROM service_logins
LEFT JOIN logins ON service_logins.login_id = logins.login_id
"SELECT * FROM service_credentials
LEFT JOIN credentials ON service_credentials.credential_id = credentials.credential_id
WHERE service_id = $service_id"
);
@@ -318,27 +318,27 @@ ob_start();
}
?>
<!-- Logins -->
<!-- Credentials -->
<?php
if (mysqli_num_rows($sql_assets) > 0 || mysqli_num_rows($sql_logins) > 0) { ?>
<h5><i class="fas fa-fw fa-key mr-2"></i>Logins</h5>
if (mysqli_num_rows($sql_assets) > 0 || mysqli_num_rows($sql_credentials) > 0) { ?>
<h5><i class="fas fa-fw fa-key mr-2"></i>Credentials</h5>
<ul>
<?php
// Reset the $sql_assets/logins pointer to the start
// Reset the $sql_assets/credentials pointer to the start
mysqli_data_seek($sql_assets, 0);
mysqli_data_seek($sql_logins, 0);
mysqli_data_seek($sql_credentials, 0);
// Showing logins linked to assets
// Showing credentials linked to assets
while ($row = mysqli_fetch_array($sql_assets)) {
if (!empty($row['login_name'])) {
echo "<li><a href=\"credentials.php?client_id=$client_id&q=$row[login_name]\">$row[login_name]</a></li>";
if (!empty($row['credential_name'])) {
echo "<li><a href=\"credentials.php?client_id=$client_id&q=$row[credential_name]\">$row[credential_name]</a></li>";
}
}
// Showing explicitly linked logins
while ($row = mysqli_fetch_array($sql_logins)) {
if (!empty($row['login_name'])) {
echo "<li><a href=\"credentials.php?client_id=$client_id&q=$row[login_name]\">$row[login_name]</a></li>";
// Showing explicitly linked credentials
while ($row = mysqli_fetch_array($sql_credentials)) {
if (!empty($row['credential_name'])) {
echo "<li><a href=\"credentials.php?client_id=$client_id&q=$row[credential_name]\">$row[credential_name]</a></li>";
}
}
?>
@@ -349,27 +349,27 @@ ob_start();
<!-- URLs -->
<?php
if ($sql_logins || $sql_assets) { ?>
if ($sql_credentials || $sql_assets) { ?>
<h5><i class="fas fa-fw fa-link mr-2"></i>URLs</h5>
<ul>
<?php
// Reset the $sql_logins pointer to the start
mysqli_data_seek($sql_logins, 0);
// Reset the $sql_credentials pointer to the start
mysqli_data_seek($sql_credentials, 0);
// Showing URLs linked to logins
while ($row = mysqli_fetch_array($sql_logins)) {
if (!empty($row['login_uri'])) {
echo "<li><a href=\"https://$row[login_uri]\">$row[login_uri]</a></li>";
// Showing URLs linked to credentials
while ($row = mysqli_fetch_array($sql_credentials)) {
if (!empty($row['credential_uri'])) {
echo "<li><a href=\"https://$row[credential_uri]\">$row[credential_uri]</a></li>";
}
}
// Reset the $sql_assets pointer to the start
mysqli_data_seek($sql_assets, 0);
// Show URLs linked to assets, that also have logins
// Show URLs linked to assets, that also have credentials
while ($row = mysqli_fetch_array($sql_assets)) {
if (!empty($row['login_uri'])) {
echo "<li><a href=\"https://$row[login_uri]\">$row[login_uri]</a></li>";
if (!empty($row['credential_uri'])) {
echo "<li><a href=\"https://$row[credential_uri]\">$row[credential_uri]</a></li>";
}
}
?>

View File

@@ -18,23 +18,23 @@ $service_updated_at = nullable_htmlentities($row['service_updated_at']);
$service_review_due = nullable_htmlentities($row['service_review_due']);
$client_id = intval($row['service_client_id']);
// Associated Assets (and their logins/networks/locations)
// Associated Assets (and their credentials/networks/locations)
$sql_assets = mysqli_query(
$mysqli,
"SELECT * FROM service_assets
LEFT JOIN assets ON service_assets.asset_id = assets.asset_id
LEFT JOIN asset_interfaces ON interface_asset_id = assets.asset_id AND interface_primary = 1
LEFT JOIN logins ON service_assets.asset_id = logins.login_asset_id
LEFT JOIN credentials ON service_assets.asset_id = credentials.credential_asset_id
LEFT JOIN networks ON interface_network_id = networks.network_id
LEFT JOIN locations ON assets.asset_location_id = locations.location_id
WHERE service_id = $service_id"
);
// Associated logins
$sql_logins = mysqli_query(
// Associated credentials
$sql_credentials = mysqli_query(
$mysqli,
"SELECT * FROM service_logins
LEFT JOIN logins ON service_logins.login_id = logins.login_id
"SELECT * FROM service_credentials
LEFT JOIN credentials ON service_credentials.credential_id = credentials.credential_id
WHERE service_id = $service_id"
);
@@ -280,21 +280,21 @@ ob_start();
</div>
<div class="form-group">
<label for="logins">Logins</label>
<select multiple class="form-control select2" name="logins[]">
<label for="credentials">Credentials</label>
<select multiple class="form-control select2" name="credentials[]">
<?php
$selected_ids = array_column(mysqli_fetch_all($sql_logins, MYSQLI_ASSOC), "login_id");
$selected_ids = array_column(mysqli_fetch_all($sql_credentials, MYSQLI_ASSOC), "credential_id");
$sql_all = mysqli_query($mysqli, "SELECT * FROM logins WHERE (login_archived_at > '$service_created_at' OR login_archived_at IS NULL) AND login_client_id = $client_id");
$sql_all = mysqli_query($mysqli, "SELECT * FROM credentials WHERE (credential_archived_at > '$service_created_at' OR credential_archived_at IS NULL) AND credential_client_id = $client_id");
while ($row_all = mysqli_fetch_array($sql_all)) {
$login_id = intval($row_all['login_id']);
$login_name = nullable_htmlentities($row_all['login_name']);
$credential_id = intval($row_all['credential_id']);
$credential_name = nullable_htmlentities($row_all['credential_name']);
if (in_array($login_id, $selected_ids)) {
echo "<option value=\"$login_id\" selected>$login_name</option>";
if (in_array($credential_id, $selected_ids)) {
echo "<option value=\"$credential_id\" selected>$credential_name</option>";
}
else{
echo "<option value=\"$login_id\">$login_name</option>";
echo "<option value=\"$credential_id\">$credential_name</option>";
}
}
?>

View File

@@ -24,6 +24,14 @@ $location_id = intval($row['ticket_location_id']);
$vendor_id = intval($row['ticket_vendor_id']);
$project_id = intval($row['ticket_project_id']);
// Additional Assets Selected
$additional_assets_array = array();
$sql_additional_assets = mysqli_query($mysqli, "SELECT asset_id FROM ticket_assets WHERE ticket_id = $ticket_id");
while ($row = mysqli_fetch_array($sql_additional_assets)) {
$additional_asset_id = intval($row['asset_id']);
$additional_assets_array[] = $additional_asset_id;
}
// Generate the HTML form content using output buffering.
ob_start();
?>
@@ -67,7 +75,7 @@ ob_start();
</div>
<div class="form-group">
<textarea class="form-control tinymce" rows="8" name="details"><?php echo $ticket_details; ?></textarea>
<textarea class="form-control tinymceTicket" rows="8" name="details"><?php echo $ticket_details; ?></textarea>
</div>
<div class="row">
@@ -212,6 +220,31 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Additional Assets</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
</div>
<select class="form-control select2" name="additional_assets[]" data-tags="true" data-placeholder="- Select Additional Assets -" multiple>
<option value=""></option>
<?php
$sql_assets = mysqli_query($mysqli, "SELECT asset_id, asset_name, contact_name FROM assets LEFT JOIN contacts ON contact_id = asset_contact_id WHERE asset_client_id = $client_id AND asset_id != $asset_id AND asset_archived_at IS NULL ORDER BY asset_name ASC");
while ($row = mysqli_fetch_array($sql_assets)) {
$asset_id_select = intval($row['asset_id']);
$asset_name_select = nullable_htmlentities($row['asset_name']);
$asset_contact_name_select = nullable_htmlentities($row['contact_name']);
?>
<option value="<?php echo $asset_id_select; ?>"
<?php if (in_array($asset_id_select, $additional_assets_array)) { echo "selected"; } ?>
><?php echo "$asset_name_select - $asset_contact_name_select"; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Location</label>
<div class="input-group">

View File

@@ -0,0 +1,54 @@
<?php
require_once '../includes/ajax_header.php';
$ticket_reply_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM ticket_replies
LEFT JOIN tickets ON ticket_id = ticket_reply_ticket_id
WHERE ticket_reply_id = $ticket_reply_id
LIMIT 1"
);
$row = mysqli_fetch_array($sql);
$ticket_reply_type = nullable_htmlentities($row['ticket_reply_type']);
$ticket_reply_time_worked = date_create($row['ticket_reply_time_worked']);
$ticket_reply_time_worked_formatted = date_format($ticket_reply_time_worked, 'H:i:s');
$ticket_reply = nullable_htmlentities($row['ticket_reply']);
$client_id = intval($row['ticket_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-edit mr-2"></i>Redacting Ticket Reply</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_reply_id" value="<?php echo $ticket_reply_id; ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<input type="hidden" name="ticket_reply_type" value="<?php echo $ticket_reply_type; ?>">
<?php if (!empty($ticket_reply_time_worked)) { ?>
<input type="hidden" name="time" value="<?php echo $ticket_reply_time_worked_formatted; ?>">
<?php } ?>
<div class="modal-body bg-white">
<div class="form-group">
<textarea class="form-control tinymceRedact" name="ticket_reply"><?php echo $ticket_reply; ?></textarea>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="edit_ticket_reply" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -4,7 +4,10 @@ require_once '../includes/ajax_header.php';
$user_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM users, user_settings WHERE users.user_id = user_settings.user_id AND users.user_id = $user_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM users
LEFT JOIN user_settings ON users.user_id = user_settings.user_id
WHERE users.user_id = $user_id LIMIT 1"
);
$row = mysqli_fetch_array($sql);
$user_name = nullable_htmlentities($row['user_name']);
@@ -12,11 +15,11 @@ $user_email = nullable_htmlentities($row['user_email']);
$user_avatar = nullable_htmlentities($row['user_avatar']);
$user_token = nullable_htmlentities($row['user_token']);
$user_config_force_mfa = intval($row['user_config_force_mfa']);
$user_role = intval($row['user_role']);
$user_role_id = intval($row['user_role_id']);
$user_initials = nullable_htmlentities(initials($user_name));
// Get User Client Access Permissions
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id FROM user_permissions WHERE user_id = $user_id");
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id FROM user_client_permissions WHERE user_id = $user_id");
$client_access_array = [];
while ($row = mysqli_fetch_assoc($user_client_access_sql)) {
$client_access_array[] = intval($row['client_id']);
@@ -107,13 +110,13 @@ ob_start();
</div>
<select class="form-control select2" name="role" required>
<?php
$sql_user_roles = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE user_role_archived_at IS NULL");
$sql_user_roles = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE role_archived_at IS NULL");
while ($row = mysqli_fetch_array($sql_user_roles)) {
$user_role_id = intval($row['user_role_id']);
$user_role_name = nullable_htmlentities($row['user_role_name']);
$role_id = intval($row['role_id']);
$role_name = nullable_htmlentities($row['role_name']);
?>
<option <?php if ($user_role == $user_role_id) {echo "selected";} ?> value="<?php echo $user_role_id; ?>"><?php echo $user_role_name; ?></option>
<option <?php if ($role_id == $user_role_id) {echo "selected";} ?> value="<?php echo $role_id; ?>"><?php echo $role_name; ?></option>
<?php } ?>
</select>

View File

@@ -11,7 +11,8 @@ $vendor_name = nullable_htmlentities($row['vendor_name']);
$vendor_description = nullable_htmlentities($row['vendor_description']);
$vendor_account_number = nullable_htmlentities($row['vendor_account_number']);
$vendor_contact_name = nullable_htmlentities($row['vendor_contact_name']);
$vendor_phone = formatPhoneNumber($row['vendor_phone']);
$vendor_phone_country_code = nullable_htmlentities($row['vendor_phone_country_code']);
$vendor_phone = nullable_htmlentities(formatPhoneNumber($row['vendor_phone'], $vendor_phone_country_code));
$vendor_extension = nullable_htmlentities($row['vendor_extension']);
$vendor_email = nullable_htmlentities($row['vendor_email']);
$vendor_website = nullable_htmlentities($row['vendor_website']);
@@ -118,20 +119,23 @@ ob_start();
<div class="tab-pane fade" id="pills-support<?php echo $vendor_id; ?>">
<label>Support Phone</label>
<label>Support Phone / <span class="text-secondary">Extension</span></label>
<div class="form-row">
<div class="col-8">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200" value="<?php echo $vendor_phone; ?>">
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo "+$vendor_phone_country_code"; ?>" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="phone" value="<?php echo $vendor_phone; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
</div>
<div class="col-4">
<input type="text" class="form-control" name="extension" placeholder="Prompts" maxlength="200" value="<?php echo $vendor_extension; ?>">
<div class="col-3">
<div class="form-group">
<input type="text" class="form-control" name="extension" value="<?php echo $vendor_extension; ?>" placeholder="ext." maxlength="200">
</div>
</div>
</div>

View File

@@ -134,7 +134,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200" value="<?php echo $vendor_phone; ?>">
<input type="tel" class="form-control" name="phone" value="<?php echo $vendor_phone; ?>">
<div class="input-group-append">
<div class="input-group-text">
<input type="checkbox" name="global_update_vendor_phone" value="1">

View File

@@ -13,7 +13,7 @@ $insert_id = false;
if (!empty($api_key_decrypt_password) && !empty($name) && !(empty($password))) {
// Add credential
$insert_sql = 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");
$insert_sql = mysqli_query($mysqli,"INSERT INTO credentials SET credential_name = '$name', credential_description = '$description', credential_uri = '$uri', credential_uri_2 = '$uri_2', credential_username = '$username', credential_password = '$password', credential_otp_secret = '$otp_secret', credential_note = '$note', credential_important = $important, credential_contact_id = $contact_id, credential_vendor_id = $vendor_id, credential_asset_id = $asset_id, credential_software_id = $software_id, credential_client_id = $client_id");
// Check insert & get insert ID
if ($insert_sql) {

View File

@@ -8,53 +8,53 @@ if (isset($_POST['api_key_decrypt_password'])) {
$api_key_decrypt_password = $_POST['api_key_decrypt_password']; // No sanitization
}
if (isset($_POST['login_name'])) {
$name = sanitizeInput($_POST['login_name']);
} elseif (isset($credential_row) && isset($credential_row['login_name'])) {
$name = $credential_row['login_name'];
if (isset($_POST['credential_name'])) {
$name = sanitizeInput($_POST['credential_name']);
} elseif (isset($credential_row) && isset($credential_row['credential_name'])) {
$name = $credential_row['credential_name'];
} else {
$name = '';
}
if (isset($_POST['login_description'])) {
$description = sanitizeInput($_POST['login_description']);
} elseif (isset($credential_row) && isset($credential_row['login_description'])) {
$description = $credential_row['login_description'];
if (isset($_POST['credential_description'])) {
$description = sanitizeInput($_POST['credential_description']);
} elseif (isset($credential_row) && isset($credential_row['credential_description'])) {
$description = $credential_row['credential_description'];
} else {
$description = '';
}
if (isset($_POST['login_uri'])) {
$uri = sanitizeInput($_POST['login_uri']);
} elseif (isset($credential_row) && isset($credential_row['login_uri'])) {
$uri = $credential_row['login_uri'];
if (isset($_POST['credential_uri'])) {
$uri = sanitizeInput($_POST['credential_uri']);
} elseif (isset($credential_row) && isset($credential_row['credential_uri'])) {
$uri = $credential_row['credential_uri'];
} else {
$uri = '';
}
if (isset($_POST['login_uri_2'])) {
$uri_2 = sanitizeInput($_POST['login_uri_2']);
} elseif (isset($credential_row) && isset($credential_row['login_uri_2'])) {
$uri_2 = $credential_row['login_uri_2'];
if (isset($_POST['credential_uri_2'])) {
$uri_2 = sanitizeInput($_POST['credential_uri_2']);
} elseif (isset($credential_row) && isset($credential_row['credential_uri_2'])) {
$uri_2 = $credential_row['credential_uri_2'];
} else {
$uri_2 = '';
}
if (isset($_POST['login_username'])) {
$username = $_POST['login_username'];
if (isset($_POST['credential_username'])) {
$username = $_POST['credential_username'];
$username = apiEncryptLoginEntry($username, $api_key_decrypt_hash, $api_key_decrypt_password);
} elseif (isset($credential_row) && isset($credential_row['login_username'])) {
$username = $credential_row['login_username'];
} elseif (isset($credential_row) && isset($credential_row['credential_username'])) {
$username = $credential_row['credential_username'];
} else {
$username = '';
}
if (isset($_POST['login_password'])) {
$password = $_POST['login_password'];
if (isset($_POST['credential_password'])) {
$password = $_POST['credential_password'];
$password = apiEncryptLoginEntry($password, $api_key_decrypt_hash, $api_key_decrypt_password);
$password_changed = true;
} elseif (isset($credential_row) && isset($credential_row['login_password'])) {
$password = $credential_row['login_password'];
} elseif (isset($credential_row) && isset($credential_row['credential_password'])) {
$password = $credential_row['credential_password'];
$password_changed = false;
} else {
$password = '';
@@ -63,58 +63,58 @@ if (isset($_POST['login_password'])) {
if (isset($_POST['login_otp_secret'])) {
$otp_secret = sanitizeInput($_POST['login_otp_secret']);
} elseif (isset($credential_row) && isset($credential_row['login_otp_secret'])) {
$otp_secret = $credential_row['login_otp_secret'];
if (isset($_POST['credential_otp_secret'])) {
$otp_secret = sanitizeInput($_POST['credential_otp_secret']);
} elseif (isset($credential_row) && isset($credential_row['credential_otp_secret'])) {
$otp_secret = $credential_row['credential_otp_secret'];
} else {
$otp_secret = '';
}
if (isset($_POST['login_note'])) {
$note = sanitizeInput($_POST['login_note']);
} elseif (isset($credential_row) && isset($credential_row['login_note'])) {
$note = $credential_row['login_note'];
if (isset($_POST['credential_note'])) {
$note = sanitizeInput($_POST['credential_note']);
} elseif (isset($credential_row) && isset($credential_row['credential_note'])) {
$note = $credential_row['credential_note'];
} else {
$note = '';
}
if (isset($_POST['login_important'])) {
$important = intval($_POST['login_important']);
} elseif (isset($credential_row) && isset($credential_row['login_important'])) {
$important = $credential_row['login_important'];
if (isset($_POST['credential_important'])) {
$important = intval($_POST['credential_important']);
} elseif (isset($credential_row) && isset($credential_row['credential_important'])) {
$important = $credential_row['credential_important'];
} else {
$important = '';
}
if (isset($_POST['login_contact_id'])) {
$contact_id = intval($_POST['login_contact_id']);
} elseif (isset($credential_row) && isset($credential_row['login_contact_id'])) {
$contact_id = $credential_row['login_contact_id'];
if (isset($_POST['credential_contact_id'])) {
$contact_id = intval($_POST['credential_contact_id']);
} elseif (isset($credential_row) && isset($credential_row['credential_contact_id'])) {
$contact_id = $credential_row['credential_contact_id'];
} else {
$contact_id = '';
}
if (isset($_POST['login_vendor_id'])) {
$vendor_id = intval($_POST['login_vendor_id']);
} elseif (isset($credential_row) && isset($credential_row['login_vendor_id'])) {
$vendor_id = $credential_row['login_vendor_id'];
if (isset($_POST['credential_vendor_id'])) {
$vendor_id = intval($_POST['credential_vendor_id']);
} elseif (isset($credential_row) && isset($credential_row['credential_vendor_id'])) {
$vendor_id = $credential_row['credential_vendor_id'];
} else {
$vendor_id = '';
}
if (isset($_POST['login_asset_id'])) {
$asset_id = intval($_POST['login_asset_id']);
} elseif (isset($credential_row) && isset($credential_row['login_asset_id'])) {
$asset_id = $credential_row['login_asset_id'];
if (isset($_POST['credential_asset_id'])) {
$asset_id = intval($_POST['credential_asset_id']);
} elseif (isset($credential_row) && isset($credential_row['credential_asset_id'])) {
$asset_id = $credential_row['credential_asset_id'];
} else {
$asset_id = '';
}
if (isset($_POST['login_software_id'])) {
$software_id = intval($_POST['login_software_id']);
} elseif (isset($credential_row) && isset($credential_row['login_software_id'])) {
$software_id = $credential_row['login_software_id'];
if (isset($_POST['credential_software_id'])) {
$software_id = intval($_POST['credential_software_id']);
} elseif (isset($credential_row) && isset($credential_row['credential_software_id'])) {
$software_id = $credential_row['credential_software_id'];
} else {
$software_id = '';
}

View File

@@ -13,17 +13,17 @@ if (isset($_GET['api_key_decrypt_password'])) {
}
// Specific credential/login via ID (single)
if (isset($_GET['login_id']) && !empty($api_key_decrypt_password)) {
if (isset($_GET['credential_id']) && !empty($api_key_decrypt_password)) {
$id = intval($_GET['login_id']);
$id = intval($_GET['credential_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = '$id' AND login_client_id LIKE '$client_id' LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = '$id' AND credential_client_id LIKE '$client_id' LIMIT 1");
} elseif (!empty($api_key_decrypt_password)) {
// All credentials ("logins")
// All credentials ("credentials")
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_client_id LIKE '$client_id' ORDER BY login_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_client_id LIKE '$client_id' ORDER BY credential_id LIMIT $limit OFFSET $offset");
}
@@ -37,8 +37,8 @@ if ($sql && mysqli_num_rows($sql) > 0) {
$row = array();
while ($row = mysqli_fetch_array($sql)) {
$row['login_username'] = apiDecryptLoginEntry($row['login_username'], $api_key_decrypt_hash, $api_key_decrypt_password);
$row['login_password'] = apiDecryptLoginEntry($row['login_password'], $api_key_decrypt_hash, $api_key_decrypt_password);
$row['credential_username'] = apiDecryptCredentialEntry($row['credential_username'], $api_key_decrypt_hash, $api_key_decrypt_password);
$row['credential_password'] = apiDecryptCredentialEntry($row['credential_password'], $api_key_decrypt_hash, $api_key_decrypt_password);
$return_arr['data'][] = $row;
}

View File

@@ -5,30 +5,30 @@ require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse ID
$login_id = intval($_POST['login_id']);
$credential_id = intval($_POST['credential_id']);
// Default
$update_count = false;
if (!empty($_POST['api_key_decrypt_password']) && !empty($login_id)) {
if (!empty($_POST['api_key_decrypt_password']) && !empty($credential_id)) {
$credential_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = '$login_id' AND login_client_id = $client_id LIMIT 1"));
$credential_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = '$credential_id' AND credential_client_id = $client_id LIMIT 1"));
// Variable assignment from POST - assigning the current database value if a value is not provided
require_once 'credential_model.php';
$update_sql = 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, login_client_id = $client_id WHERE login_id = '$login_id' AND login_client_id = $client_id LIMIT 1");
$update_sql = mysqli_query($mysqli,"UPDATE credentials SET credential_name = '$name', credential_description = '$description', credential_uri = '$uri', credential_uri_2 = '$uri_2', credential_username = '$username', credential_password = '$password', credential_otp_secret = '$otp_secret', credential_note = '$note', credential_important = $important, credential_contact_id = $contact_id, credential_vendor_id = $vendor_id, credential_asset_id = $asset_id, credential_software_id = $software_id, credential_client_id = $client_id WHERE credential_id = '$credential_id' AND credential_client_id = $client_id LIMIT 1");
// Check insert & get insert ID
if ($update_sql) {
$update_count = mysqli_affected_rows($mysqli);
if ($password_changed) {
mysqli_query($mysqli, "UPDATE logins SET login_password_changed_at = NOW() WHERE login_id = $login_id LIMIT 1");
mysqli_query($mysqli, "UPDATE credentials SET credential_password_changed_at = NOW() WHERE credential_id = $credential_id LIMIT 1");
}
// Logging
logAction("Credential", "Edit", "$name via API ($api_key_name)", $client_id, $login_id);
logAction("Credential", "Edit", "$name via API ($api_key_name)", $client_id, $credential_id);
logAction("API", "Success", "Updated credential $name via API ($api_key_name)", $client_id);
}

View File

@@ -5,7 +5,7 @@ require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Ticket-related settings
require_once "../../../get_settings.php";
require_once "../../../includes/get_settings.php";
$sql = mysqli_query($mysqli, "SELECT company_name, company_phone FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
@@ -39,7 +39,7 @@ if (!empty($subject)) {
// Insert ticket
$url_key = randomString(156);
$insert_sql = mysqli_query($mysqli,"INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_vendor_ticket_number = '$vendor_ticket_number', ticket_vendor_id = $vendor_id, ticket_created_by = 0, ticket_assigned_to = $assigned_to, ticket_contact_id = $contact, ticket_url_key = '$url_key', ticket_client_id = $client_id");
$insert_sql = mysqli_query($mysqli,"INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_billable = $billable, ticket_vendor_ticket_number = '$vendor_ticket_number', ticket_vendor_id = $vendor_id, ticket_created_by = 0, ticket_assigned_to = $assigned_to, ticket_contact_id = $contact, ticket_url_key = '$url_key', ticket_client_id = $client_id");
// Check insert & get insert ID
if ($insert_sql) {

View File

@@ -59,3 +59,11 @@ if (isset($_POST['ticket_assigned_to'])) {
} else {
$assigned_to = '0';
}
if (isset($_POST['ticket_billable'])) {
$billable = intval($_POST['ticket_billable']);
} elseif ($ticket_row) {
$billable = $ticket_row['ticket_billable'];
} else {
$billable = '0';
}

View File

@@ -81,19 +81,24 @@ if (isset($_GET['asset_id'])) {
// Override Tab Title // No Sanitizing needed as this var will opnly be used in the tab title
$page_title = $row['asset_name'];
// Related Tickets Query
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
LEFT JOIN users on ticket_assigned_to = user_id
$sql_related_tickets = mysqli_query($mysqli, "
SELECT tickets.*, users.*, ticket_statuses.*
FROM tickets
LEFT JOIN users ON ticket_assigned_to = user_id
LEFT JOIN ticket_statuses ON ticket_status_id = ticket_status
WHERE ticket_asset_id = $asset_id
ORDER BY ticket_number DESC"
);
LEFT JOIN ticket_assets ON tickets.ticket_id = ticket_assets.ticket_id
WHERE ticket_asset_id = $asset_id OR ticket_assets.asset_id = $asset_id
GROUP BY tickets.ticket_id
ORDER BY ticket_number DESC
");
$ticket_count = mysqli_num_rows($sql_related_tickets);
// Related Recurring Tickets Query
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
WHERE scheduled_ticket_asset_id = $asset_id
ORDER BY scheduled_ticket_next_run DESC"
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
LEFT JOIN recurring_ticket_assets ON recurring_tickets.recurring_ticket_id = recurring_ticket_assets.recurring_ticket_id
WHERE recurring_ticket_asset_id = $asset_id OR recurring_ticket_assets.asset_id = $asset_id
GROUP BY recurring_tickets.recurring_ticket_id
ORDER BY recurring_ticket_next_run DESC"
);
$recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets);
@@ -179,29 +184,29 @@ if (isset($_GET['asset_id'])) {
$document_count = mysqli_num_rows($sql_related_documents);
// Related Logins Query
$sql_related_logins = mysqli_query($mysqli, "
// Related Credentials Query
$sql_related_credentials = mysqli_query($mysqli, "
SELECT
logins.login_id AS login_id,
logins.login_name,
logins.login_description,
logins.login_uri,
logins.login_username,
logins.login_password,
logins.login_otp_secret,
logins.login_note,
logins.login_important,
logins.login_contact_id,
logins.login_asset_id
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
WHERE login_asset_id = $asset_id
AND login_archived_at IS NULL
GROUP BY logins.login_id
ORDER BY login_name DESC
credentials.credential_id AS credential_id,
credentials.credential_name,
credentials.credential_description,
credentials.credential_uri,
credentials.credential_username,
credentials.credential_password,
credentials.credential_otp_secret,
credentials.credential_note,
credentials.credential_important,
credentials.credential_contact_id,
credentials.credential_asset_id
FROM credentials
LEFT JOIN credential_tags ON credential_tags.credential_id = credentials.credential_id
LEFT JOIN tags ON tags.tag_id = credential_tags.tag_id
WHERE credential_asset_id = $asset_id
AND credential_archived_at IS NULL
GROUP BY credentials.credential_id
ORDER BY credential_name DESC
");
$login_count = mysqli_num_rows($sql_related_logins);
$credential_count = mysqli_num_rows($sql_related_credentials);
// Related Software Query
$sql_related_software = mysqli_query(
@@ -356,8 +361,16 @@ if (isset($_GET['asset_id'])) {
<i class="fa fa-fw fa-recycle mr-2"></i>New Recurring Ticket
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#createContactNoteModal<?php echo $contact_id; ?>">
<i class="fa fa-fw fa-sticky-note mr-2"></i>New Note (WIP)
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addCredentialModal">
<i class="fa fa-fw fa-key mr-2"></i>New Credential
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addDocumentModal">
<i class="fa fa-fw fa-file-alt mr-2"></i>New Document
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#uploadFilesModal">
<i class="fa fa-fw fa-upload mr-2"></i>Upload file(s)
</a>
</div>
</div>
@@ -518,7 +531,7 @@ if (isset($_GET['asset_id'])) {
</div>
</div>
<div class="card card-dark <?php if ($login_count == 0) { echo "d-none"; } ?>">
<div class="card card-dark <?php if ($credential_count == 0) { echo "d-none"; } ?>">
<div class="card-header">
<h3 class="card-title"><i class="fa fa-fw fa-key mr-2"></i>Credentials</h3>
</div>
@@ -539,56 +552,56 @@ if (isset($_GET['asset_id'])) {
<tbody>
<?php
while ($row = mysqli_fetch_array($sql_related_logins)) {
$login_id = intval($row['login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
if (empty($login_uri)) {
$login_uri_display = "-";
while ($row = mysqli_fetch_array($sql_related_credentials)) {
$credential_id = intval($row['credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
if (empty($credential_uri)) {
$credential_uri_display = "-";
} else {
$login_uri_display = "$login_uri<button class='btn btn-sm clipboardjs' data-clipboard-text='$login_uri'><i class='far fa-copy text-secondary'></i></button><a href='$login_uri' target='_blank'><i class='fa fa-external-link-alt text-secondary'></i></a>";
$credential_uri_display = "$credential_uri<button class='btn btn-sm clipboardjs' data-clipboard-text='$credential_uri'><i class='far fa-copy text-secondary'></i></button><a href='$credential_uri' target='_blank'><i class='fa fa-external-link-alt text-secondary'></i></a>";
}
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
if (empty($login_username)) {
$login_username_display = "-";
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
if (empty($credential_username)) {
$credential_username_display = "-";
} else {
$login_username_display = "$login_username<button class='btn btn-sm clipboardjs' data-clipboard-text='$login_username'><i class='far fa-copy text-secondary'></i></button>";
$credential_username_display = "$credential_username<button class='btn btn-sm clipboardjs' data-clipboard-text='$credential_username'><i class='far fa-copy text-secondary'></i></button>";
}
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_name_display_array = array();
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT * FROM login_tags LEFT JOIN tags ON login_tags.tag_id = tags.tag_id WHERE login_id = $login_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$credential_tag_name_display_array = array();
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT * FROM credential_tags LEFT JOIN tags ON credential_tags.tag_id = tags.tag_id WHERE credential_id = $credential_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_name = nullable_htmlentities($row['tag_name']);
$login_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($login_tag_color)) {
$login_tag_color = "dark";
$credential_tag_id = intval($row['tag_id']);
$credential_tag_name = nullable_htmlentities($row['tag_name']);
$credential_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($credential_tag_color)) {
$credential_tag_color = "dark";
}
$login_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($login_tag_icon)) {
$login_tag_icon = "tag";
$credential_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($credential_tag_icon)) {
$credential_tag_icon = "tag";
}
$login_tag_id_array[] = $login_tag_id;
$login_tag_name_display_array[] = "<a href='client_logins.php?client_id=$client_id&tags[]=$login_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $login_tag_color;'><i class='fa fa-fw fa-$login_tag_icon mr-2'></i>$login_tag_name</span></a>";
$credential_tag_id_array[] = $credential_tag_id;
$credential_tag_name_display_array[] = "<a href='credentials.php?client_id=$client_id&tags[]=$credential_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $credential_tag_color;'><i class='fa fa-fw fa-$credential_tag_icon mr-2'></i>$credential_tag_name</span></a>";
}
$login_tags_display = implode('', $login_tag_name_display_array);
$credential_tags_display = implode('', $credential_tag_name_display_array);
?>
<tr>
@@ -597,18 +610,18 @@ if (isset($_GET['asset_id'])) {
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_credential_edit.php"
data-ajax-id="<?php echo $login_id; ?>"
data-ajax-id="<?php echo $credential_id; ?>"
>
<?php echo $login_name; ?>
<?php echo $credential_name; ?>
</a>
</td>
<td><?php echo $login_description; ?></td>
<td><?php echo $login_username_display; ?></td>
<td><?php echo $credential_description; ?></td>
<td><?php echo $credential_username_display; ?></td>
<td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $login_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" data-clipboard-text="<?php echo $login_password; ?>"><i class="far fa-copy text-secondary"></i></button>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" data-clipboard-text="<?php echo $credential_password; ?>"><i class="far fa-copy text-secondary"></i></button>
</td>
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td><?php echo $credential_uri_display; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
@@ -618,20 +631,20 @@ if (isset($_GET['asset_id'])) {
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_credential_edit.php"
data-ajax-id="<?php echo $login_id; ?>"
data-ajax-id="<?php echo $credential_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Login', $login_id"; ?>)">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Credential', $credential_id"; ?>)">
<i class="fas fa-fw fa-share-alt mr-2"></i>Share
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="post.php?unlink_credential_from_asset&asset_id=<?php echo $asset_id; ?>&login_id=<?php echo $login_id; ?>">
<a class="dropdown-item" href="post.php?unlink_credential_from_asset&asset_id=<?php echo $asset_id; ?>&credential_id=<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-unlink mr-2"></i>Unlink
</a>
<?php if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold" href="post.php?delete_login=<?php echo $login_id; ?>">
<a class="dropdown-item text-danger text-bold" href="post.php?delete_credential=<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
@@ -686,11 +699,6 @@ if (isset($_GET['asset_id'])) {
$seat_count = 0;
// Get Login
$login_id = intval($row['login_id']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
// Asset Licenses
$asset_licenses_sql = mysqli_query($mysqli, "SELECT asset_id FROM software_assets WHERE software_id = $software_id");
$asset_licenses_array = array();
@@ -917,29 +925,30 @@ if (isset($_GET['asset_id'])) {
<?php
while ($row = mysqli_fetch_array($sql_related_recurring_tickets)) {
$scheduled_ticket_id = intval($row['scheduled_ticket_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$recurring_ticket_id = intval($row['recurring_ticket_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
?>
<tr>
<td class="text-bold">
<a href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_recurring_ticket_edit.php"
data-ajax-id="<?php echo $scheduled_ticket_id; ?>"
data-ajax-id="<?php echo $recurring_ticket_id; ?>"
>
<?php echo $scheduled_ticket_subject ?>
<?php echo $recurring_ticket_subject ?>
</a>
</td>
<td><?php echo $scheduled_ticket_priority ?></td>
<td><?php echo $recurring_ticket_priority ?></td>
<td><?php echo $scheduled_ticket_frequency ?></td>
<td><?php echo $recurring_ticket_frequency ?></td>
<td><?php echo $scheduled_ticket_next_run ?></td>
<td><?php echo $recurring_ticket_next_run ?></td>
<td>
<div class="dropdown dropleft text-center">
@@ -949,19 +958,20 @@ if (isset($_GET['asset_id'])) {
<div class="dropdown-menu">
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_recurring_ticket_edit.php"
data-ajax-id="<?php echo $scheduled_ticket_id; ?>"
data-ajax-id="<?php echo $recurring_ticket_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="post.php?force_recurring_ticket=<?php echo $scheduled_ticket_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<a class="dropdown-item" href="post.php?force_recurring_ticket=<?php echo $recurring_ticket_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fa fa-fw fa-paper-plane text-secondary mr-2"></i>Force Reoccur
</a>
<?php
if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?php echo $scheduled_ticket_id; ?>">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?php echo $recurring_ticket_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
@@ -1005,12 +1015,13 @@ if (isset($_GET['asset_id'])) {
$ticket_number = intval($row['ticket_number']);
$ticket_subject = nullable_htmlentities($row['ticket_subject']);
$ticket_priority = nullable_htmlentities($row['ticket_priority']);
$ticket_status_id = intval($row['ticket_status_id']);
$ticket_status_name = nullable_htmlentities($row['ticket_status_name']);
$ticket_status_color = nullable_htmlentities($row['ticket_status_color']);
$ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
$ticket_updated_at = nullable_htmlentities($row['ticket_updated_at']);
if (empty($ticket_updated_at)) {
if ($ticket_status == "Closed") {
if ($ticket_status_name == "Closed") {
$ticket_updated_at_display = "<p>Never</p>";
} else {
$ticket_updated_at_display = "<p class='text-danger'>Never</p>";
@@ -1031,7 +1042,7 @@ if (isset($_GET['asset_id'])) {
}
$ticket_assigned_to = intval($row['ticket_assigned_to']);
if (empty($ticket_assigned_to)) {
if ($ticket_status == 5) {
if ($ticket_status_id == 5) {
$ticket_assigned_to_display = "<p>Not Assigned</p>";
} else {
$ticket_assigned_to_display = "<p class='text-danger'>Not Assigned</p>";
@@ -1167,7 +1178,7 @@ if (isset($_GET['asset_id'])) {
});
</script>
<!-- Include script to get TOTP code via the login ID -->
<!-- Include script to get TOTP code via the credential ID -->
<script src="js/credential_show_otp_via_id.js"></script>
<?php
@@ -1178,6 +1189,9 @@ require_once "modals/asset_interface_import_modal.php";
require_once "modals/asset_interface_export_modal.php";
require_once "modals/ticket_add_modal.php";
require_once "modals/recurring_ticket_add_modal.php";
require_once "modals/credential_add_modal.php";
require_once "modals/client_document_add_modal.php";
require_once "modals/client_file_upload_modal.php";
require_once "modals/asset_link_software_modal.php";
require_once "modals/asset_link_credential_modal.php";

View File

@@ -53,7 +53,7 @@ if ($client_url && isset($_GET['location']) && !empty($_GET['location'])) {
} else {
// Default - any
$location_query = '';
$location_filter = '';
$location_filter = 0;
}
//Get Asset Counts
@@ -210,7 +210,15 @@ if (mysqli_num_rows($os_sql) > 0) {
<option value="">- All Locations -</option>
<?php
$sql_locations_filter = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_client_id = $client_id AND location_archived_at IS NULL ORDER BY location_name ASC");
$sql_locations_filter = mysqli_query($mysqli, "
SELECT DISTINCT location_id, location_name
FROM locations
LEFT JOIN assets ON asset_location_id = location_id
WHERE location_client_id = $client_id
AND location_archived_at IS NULL
AND (asset_location_id != 0 OR location_id = $location_filter)
ORDER BY location_name ASC
");
while ($row = mysqli_fetch_array($sql_locations_filter)) {
$location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
@@ -230,7 +238,14 @@ if (mysqli_num_rows($os_sql) > 0) {
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
$sql_clients_filter = mysqli_query($mysqli, "
SELECT DISTINCT client_id, client_name
FROM clients
JOIN assets ON asset_client_id = client_id
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_name ASC
");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
@@ -298,6 +313,11 @@ if (mysqli_num_rows($os_sql) > 0) {
type="submit" form="bulkActions" name="bulk_unarchive_assets">
<i class="fas fa-fw fa-redo mr-2"></i>Unarchive
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger text-bold"
type="submit" form="bulkActions" name="bulk_delete_assets">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</button>
<?php } else { ?>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger confirm-link"
@@ -519,8 +539,8 @@ if (mysqli_num_rows($os_sql) > 0) {
$location_name_display = $location_name;
}
$sql_logins = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_asset_id = $asset_id");
$login_count = mysqli_num_rows($sql_logins);
$sql_credentials = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_asset_id = $asset_id");
$credential_count = mysqli_num_rows($sql_credentials);
?>
<tr>
@@ -664,14 +684,6 @@ if (mysqli_num_rows($os_sql) > 0) {
<script src="js/bulk_actions.js"></script>
<?php
require_once "modals/asset_add_modal.php";
require_once "modals/asset_import_modal.php";
require_once "modals/asset_export_modal.php";
require_once "includes/footer.php";
?>
<!-- JSON Autocomplete / type ahead -->
<link rel="stylesheet" href="plugins/jquery-ui/jquery-ui.min.css">
<script src="plugins/jquery-ui/jquery-ui.min.js"></script>
@@ -687,3 +699,9 @@ require_once "includes/footer.php";
});
});
</script>
<?php
require_once "modals/asset_add_modal.php";
require_once "modals/asset_import_modal.php";
require_once "modals/asset_export_modal.php";
require_once "includes/footer.php";

View File

@@ -12,6 +12,8 @@
<h1>Blank Page</h1>
<hr>
<p>This is a great starting point for new custom pages.</p>
<h1><?php echo $session_user_role; ?></h1>
<?php validateAdminRole(); ?>
<?php
@@ -26,6 +28,8 @@ echo getUserAgent();
?>
<br>
<input type="tel" name="phone" id="phone">
<dl>
<dt>Requester</dt>
<dd>Sam Adams</dd>

View File

@@ -89,7 +89,7 @@ require_once "modals/calendar_add_modal.php";
//loop through IDs and create a modal for each
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
$sql = mysqli_query($mysqli, "SELECT * FROM calendar_events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['event_id']);
$event_title = nullable_htmlentities($row['event_title']);
@@ -170,7 +170,7 @@ while ($row = mysqli_fetch_array($sql)) {
},
events: [
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
$sql = mysqli_query($mysqli, "SELECT * FROM calendar_events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['event_id']);
$event_title = json_encode($row['event_title']);
@@ -245,15 +245,15 @@ while ($row = mysqli_fetch_array($sql)) {
// Recurring Tickets
$sql = mysqli_query($mysqli, "SELECT * FROM clients
LEFT JOIN scheduled_tickets ON client_id = scheduled_ticket_client_id
LEFT JOIN users ON scheduled_ticket_assigned_to = user_id
LEFT JOIN recurring_tickets ON client_id = recurring_ticket_client_id
LEFT JOIN users ON recurring_ticket_assigned_to = user_id
$client_query"
);
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['scheduled_ticket_id']);
$event_id = intval($row['recurring_ticket_id']);
$client_id = intval($row['client_id']);
$username = $row['user_name'];
$frequency = $row['scheduled_ticket_frequency'];
$frequency = $row['recurring_ticket_frequency'];
if (empty($username)) {
$username = "";
} else {
@@ -261,8 +261,8 @@ while ($row = mysqli_fetch_array($sql)) {
$username = "[". substr($row['user_name'], 0, 9) . "...]";
}
$event_title = json_encode("R Ticket ($frequency) - " . $row['scheduled_ticket_subject'] . " " . $username);
$event_start = json_encode($row['scheduled_ticket_next_run']);
$event_title = json_encode("R Ticket ($frequency) - " . $row['recurring_ticket_subject'] . " " . $username);
$event_start = json_encode($row['recurring_ticket_next_run']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: '$event_color', url: 'recurring_tickets.php?client_id=$client_id$client_url' },";
}

View File

@@ -18,8 +18,17 @@ if (isset($_GET['client_id'])) {
// Perms
enforceUserPermission('module_support');
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
if (!$client_url) {
// Client Filter
if (isset($_GET['client']) & !empty($_GET['client'])) {
$client_query = 'AND (certificate_client_id = ' . intval($_GET['client']) . ')';
$client = intval($_GET['client']);
} else {
// Default - any
$client_query = '';
$client = '';
}
}
$sql = mysqli_query($mysqli, "SELECT SQL_CALC_FOUND_ROWS * FROM certificates
LEFT JOIN clients ON client_id = certificate_client_id
@@ -67,7 +76,38 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
<div class="col-md-8">
<?php if ($client_url) { ?>
<div class="col-md-2"></div>
<?php } else { ?>
<div class="col-md-2">
<div class="input-group">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "
SELECT DISTINCT client_id, client_name
FROM clients
JOIN certificates ON certificate_client_id = client_id
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_name ASC
");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<option <?php if ($client == $client_id) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } ?>
<div class="col-md-6">
<div class="btn-group float-right">
<div class="dropdown ml-2" id="bulkActionButton" hidden>
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
@@ -154,9 +194,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
// Determine the class based on the number of days until expiry
if ($days_until_expiry <= 0) {
$tr_class = "table-secondary";
} elseif ($days_until_expiry <= 14) {
} elseif ($days_until_expiry <= 1) {
$tr_class = "table-danger";
} elseif ($days_until_expiry <= 90) {
} elseif ($days_until_expiry <= 7) {
$tr_class = "table-warning";
} else {
$tr_class = '';

View File

@@ -27,7 +27,7 @@ if ($_SESSION['user_type'] !== 2) {
}
// Set Timezone
require_once "../inc_set_timezone.php";
require_once "../includes/inc_set_timezone.php";
// User IP & UA
$session_ip = sanitizeInput(getIP());

View File

@@ -5,7 +5,7 @@
*/
require_once '../config.php';
require_once '../get_settings.php';
require_once '../includes/get_settings.php';
require_once '../functions.php';
require_once 'check_login.php';
require_once 'functions.php';

View File

@@ -10,7 +10,7 @@ require_once '../config.php';
require_once '../functions.php';
require_once '../get_settings.php';
require_once '../includes/get_settings.php';
if (!isset($_SESSION)) {
// HTTP Only cookies
@@ -23,7 +23,7 @@ if (!isset($_SESSION)) {
}
// Set Timezone after session_start
require_once "../inc_set_timezone.php";
require_once "../includes/inc_set_timezone.php";
// Check to see if client portal is enabled
if($config_client_portal_enable == 0) {

View File

@@ -18,7 +18,7 @@ if (!isset($_SESSION)) {
}
// Set Timezone after session starts
require_once "../inc_set_timezone.php";
require_once "../includes/inc_set_timezone.php";
$session_ip = sanitizeInput(getIP());
$session_user_agent = sanitizeInput($_SERVER['HTTP_USER_AGENT']);

View File

@@ -8,7 +8,7 @@ header("Content-Security-Policy: default-src 'self'");
require_once '../config.php';
require_once '../functions.php';
require_once '../get_settings.php';
require_once '../includes/get_settings.php';
if (empty($config_smtp_host)) {
@@ -33,7 +33,7 @@ if (!isset($_SESSION)) {
}
// Set Timezone after session
require_once "../inc_set_timezone.php";
require_once "../includes/inc_set_timezone.php";
$ip = sanitizeInput(getIP());
$user_agent = sanitizeInput($_SERVER['HTTP_USER_AGENT']);

View File

@@ -5,9 +5,9 @@
*/
require_once '../config.php';
require_once '../get_settings.php';
require_once '../includes/get_settings.php';
require_once '../functions.php';
require_once 'check_login.php';
require_once 'includes/check_login.php';
require_once 'functions.php';
if (isset($_POST['add_ticket'])) {
@@ -605,6 +605,7 @@ if (isset($_GET['stripe_save_card'])) {
$sql_settings = mysqli_query($mysqli, "SELECT * FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1");
$row = mysqli_fetch_array($sql_settings);
$company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
$config_smtp_host = $row['config_smtp_host'];
$config_smtp_port = intval($row['config_smtp_port']);
$config_smtp_encryption = $row['config_smtp_encryption'];

View File

@@ -83,14 +83,16 @@ if (isset($_GET['id']) && intval($_GET['id'])) {
</ol>
<div class="card">
<div class="card-header bg-dark text-center">
<h4 class="mt-1">
<div class="card-header bg-dark my-2">
<h4 class="card-title mt-1">
Ticket <?php echo $ticket_prefix, $ticket_number ?>
</h4>
<div class="card-tools">
<?php
if (empty($ticket_resolved_at) && $task_count == $completed_task_count) { ?>
<a href="post.php?resolve_ticket=<?php echo $ticket_id; ?>" class="btn btn-sm btn-outline-success float-right text-white confirm-link"><i class="fas fa-fw fa-check text-success"></i> Resolve ticket</a>
<?php } ?>
</h4>
</div>
</div>
<div class="card-body prettyContent">
@@ -122,7 +124,7 @@ if (isset($_GET['id']) && intval($_GET['id'])) {
while ($ticket_attachment = mysqli_fetch_array($sql_ticket_attachments)) {
$name = nullable_htmlentities($ticket_attachment['ticket_attachment_name']);
$ref_name = nullable_htmlentities($ticket_attachment['ticket_attachment_reference_name']);
echo "<hr class=''><i class='fas fa-fw fa-paperclip text-secondary mr-1'></i>$name | <a target='_blank' href='https://$config_base_url/uploads/tickets/$ticket_id/$ref_name'><i class='fas fa-fw fa-external-link-alt mr-1'></i>View</a>";
echo "<hr><i class='fas fa-fw fa-paperclip text-secondary mr-1'></i>$name | <a href='../uploads/tickets/$ticket_id/$ref_name' download='$name'><i class='fas fa-fw fa-download mr-1'></i>Download</a> | <a target='_blank' href='../uploads/tickets/$ticket_id/$ref_name'><i class='fas fa-fw fa-external-link-alt mr-1'></i>View</a>";
}
?>
</div>
@@ -259,7 +261,7 @@ if (isset($_GET['id']) && intval($_GET['id'])) {
while ($ticket_attachment = mysqli_fetch_array($sql_ticket_reply_attachments)) {
$name = nullable_htmlentities($ticket_attachment['ticket_attachment_name']);
$ref_name = nullable_htmlentities($ticket_attachment['ticket_attachment_reference_name']);
echo "<hr><i class='fas fa-fw fa-paperclip text-secondary mr-1'></i>$name | <a target='_blank' href='https://$config_base_url/uploads/tickets/$ticket_id/$ref_name'><i class='fas fa-fw fa-external-link-alt mr-1'></i>View</a>";
echo "<hr><i class='fas fa-fw fa-paperclip text-secondary mr-1'></i>$name | <a href='../uploads/tickets/$ticket_id/$ref_name' download='$name'><i class='fas fa-fw fa-download mr-1'></i>Download</a> | <a target='_blank' href='../uploads/tickets/$ticket_id/$ref_name'><i class='fas fa-fw fa-external-link-alt mr-1'></i>View</a>";
}
?>
</div>

View File

@@ -171,13 +171,14 @@ $page_title = $row['document_name'];
data-ajax-url="ajax/ajax_document_edit.php"
data-ajax-id="<?php echo $document_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
<i class="fas fa-fw fa-edit"></i>
</button>
<button type="button" class="btn btn-secondary mr-2" data-toggle="modal" data-target="#shareModal"
onclick="populateShareModal(<?php echo "$client_id, 'Document', $document_id"; ?>)">
<i class="fas fa-fw fa-share mr-2"></i>Share
<i class="fas fa-fw fa-share"></i>
</button>
<button type="button" class="btn btn-secondary" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
<a class="btn btn-success mr-2" href="post.php?export_document=<?php echo $document_id; ?>"><i class='fas fa-fw fa-file-pdf'></i></a>
<button type="button" class="btn btn-secondary" onclick="window.print();"><i class="fas fa-fw fa-print"></i></button>
</div>
</div>
<div class="card card-body bg-light">

View File

@@ -322,22 +322,12 @@ while ($folder_id > 0) {
$file_size_KB = number_format($file_size / 1024);
$file_mime_type = nullable_htmlentities($row['file_mime_type']);
$file_uploaded_by = nullable_htmlentities($row['user_name']);
$file_has_thumbnail = intval($row['file_has_thumbnail']);
$file_has_preview = intval($row['file_has_preview']);
$file_thumbnail_source = $file_reference_name;
if ($file_has_thumbnail == 1) {
$file_thumbnail_source = "thumbnail_$file_reference_name";
}
$file_preview_source = $file_reference_name;
if ($file_has_preview == 1) {
$file_preview_source = "preview_$file_reference_name";
}
// Store file data into an array for JS
$files[] = [
'id' => $file_id,
'name' => $file_name,
'preview' => "uploads/clients/$client_id/$file_preview_source"
'preview' => "uploads/clients/$client_id/$file_reference_name"
];
?>
@@ -345,7 +335,7 @@ while ($folder_id > 0) {
<div class="col-xl-2 col-lg-2 col-md-6 col-sm-6 mb-3 text-center">
<a href="#" onclick="openModal(<?php echo count($files)-1; ?>)"><!-- passing the index -->
<img class="img-thumbnail" src="<?php echo "uploads/clients/$client_id/$file_thumbnail_source"; ?>" alt="<?php echo $file_reference_name ?>">
<img class="img-thumbnail" src="<?php echo "uploads/clients/$client_id/$file_reference_name"; ?>" alt="<?php echo $file_reference_name ?>">
</a>
<div>
@@ -356,18 +346,8 @@ while ($folder_id > 0) {
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/$file_reference_name"; ?>" download="<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Original
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download
</a>
<?php if ($file_has_preview) { ?>
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/preview_$file_reference_name"; ?>" download="preview_<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Optimized
</a>
<?php } ?>
<?php if ($file_has_thumbnail) { ?>
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/thumbnail_$file_reference_name"; ?>" download="thumbnail_<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Thumbnail
</a>
<?php } ?>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'File', $file_id"; ?>)">
<i class="fas fa-fw fa-share mr-2"></i>Share
</a>
@@ -493,8 +473,6 @@ while ($folder_id > 0) {
$file_mime_type = nullable_htmlentities($row['file_mime_type']);
$file_size = intval($row['file_size']);
$file_uploaded_by = nullable_htmlentities($row['user_name']);
$file_has_thumbnail = intval($row['file_has_thumbnail']);
$file_has_preview = intval($row['file_has_preview']);
$file_created_at = nullable_htmlentities($row['file_created_at']);
$file_folder_id = intval($row['file_folder_id']);
@@ -573,18 +551,8 @@ while ($folder_id > 0) {
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/$file_reference_name"; ?>" download="<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Original
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download
</a>
<?php if ($file_has_preview) { ?>
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/preview_$file_reference_name"; ?>" download="preview_<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Optimized
</a>
<?php } ?>
<?php if ($file_has_thumbnail) { ?>
<a class="dropdown-item" href="<?php echo "uploads/clients/$client_id/thumbnail_$file_reference_name"; ?>" download="thumbnail_<?php echo $file_name; ?>">
<i class="fas fa-fw fa-cloud-download-alt mr-2"></i>Download Thumbnail
</a>
<?php } ?>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'File', $file_id"; ?>)">
<i class="fas fa-fw fa-share mr-2"></i>Share
</a>

View File

@@ -32,12 +32,12 @@ $sql_recent_tickets = mysqli_query(
LIMIT 5"
);
$sql_recent_logins = mysqli_query(
$sql_recent_credentials = mysqli_query(
$mysqli,
"SELECT * FROM logins
WHERE login_client_id = $client_id
AND login_archived_at IS NULL
ORDER BY login_updated_at ASC
"SELECT * FROM credentials
WHERE credential_client_id = $client_id
AND credential_archived_at IS NULL
ORDER BY credential_updated_at ASC
LIMIT 5"
);
@@ -221,9 +221,11 @@ $sql_asset_retired = mysqli_query(
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
?>
<tr>
@@ -286,10 +288,10 @@ $sql_asset_retired = mysqli_query(
$item_expire_at = nullable_htmlentities($row['item_expire_at']);
$item_expire_at_human = timeAgo($row['item_expire_at']);
if ($item_type == 'Login') {
$share_item_sql = mysqli_query($mysqli, "SELECT login_name FROM logins WHERE login_id = $item_related_id AND login_client_id = $client_id");
if ($item_type == 'Credential') {
$share_item_sql = mysqli_query($mysqli, "SELECT credential_name FROM credentials WHERE credential_id = $item_related_id AND credential_client_id = $client_id");
$share_item = mysqli_fetch_array($share_item_sql);
$item_name = nullable_htmlentities($share_item['login_name']);
$item_name = nullable_htmlentities($share_item['credential_name']);
$item_icon = "fas fa-key";
} elseif ($item_type == 'Document') {
$share_item_sql = mysqli_query($mysqli, "SELECT document_name FROM documents WHERE document_id = $item_related_id AND document_client_id = $client_id");

View File

@@ -20,18 +20,14 @@ if (isset($_GET['leads']) && $_GET['leads'] == 1) {
// Tags Filter
if (isset($_GET['tags']) && is_array($_GET['tags']) && !empty($_GET['tags'])) {
// Sanitize each element of the status array
$sanitizedTags = array();
foreach ($_GET['tags'] as $tag) {
// Escape each status to prevent SQL injection
$sanitizedTags[] = "'" . intval($tag) . "'";
}
// Sanitize each element of the tags array
$sanitizedTags = array_map('intval', $_GET['tags']);
// Convert the sanitized tags into a comma-separated string
$sanitizedTagsString = implode(",", $sanitizedTags);
$tag_query = "AND tags.tag_id IN ($sanitizedTagsString)";
$tag_filter = implode(",", $sanitizedTags);
$tag_query = "AND tags.tag_id IN ($tag_filter)";
} else {
$tag_query = '';
$tag_filter = 0;
$tag_query = '';
}
// Industry Filter
@@ -63,7 +59,7 @@ $sql = mysqli_query(
LEFT JOIN locations ON clients.client_id = locations.location_client_id AND location_primary = 1
LEFT JOIN client_tags ON client_tags.client_id = clients.client_id
LEFT JOIN tags ON tags.tag_id = client_tags.tag_id
WHERE (client_name LIKE '%$q%' OR client_type LIKE '%$q%' OR client_referral LIKE '%$q%'
WHERE (client_name LIKE '%$q%' OR client_abbreviation LIKE '%$q%' OR client_type LIKE '%$q%' OR client_referral LIKE '%$q%'
OR contact_email LIKE '%$q%' OR contact_name LIKE '%$q%' OR contact_phone LIKE '%$phone_query%'
OR contact_mobile LIKE '%$phone_query%' OR location_address LIKE '%$q%'
OR location_city LIKE '%$q%' OR location_state LIKE '%$q%' OR location_zip LIKE '%$q%'
@@ -190,8 +186,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php
$sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 1");
while ($row = mysqli_fetch_array($sql_tags)) {
$sql_tags_filter = mysqli_query($mysqli, "
SELECT tags.tag_id, tags.tag_name
FROM tags
LEFT JOIN client_tags ON client_tags.tag_id = tags.tag_id
WHERE tag_type = 1
GROUP BY tags.tag_id
HAVING COUNT(client_tags.client_id) > 0 OR tags.tag_id IN ($tag_filter)
");
while ($row = mysqli_fetch_array($sql_tags_filter)) {
$tag_id = intval($row['tag_id']);
$tag_name = nullable_htmlentities($row['tag_name']); ?>
@@ -199,15 +202,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="1">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
<div class="col-sm-2">
@@ -297,9 +291,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
$contact_email = nullable_htmlentities($row['contact_email']);
$client_website = nullable_htmlentities($row['client_website']);
$client_rate = floatval($row['client_rate']);
@@ -362,13 +358,13 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
}
//Get Monthly Recurring Total
$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_monthly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'month' AND recurring_client_id = $client_id");
$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_invoice_amount) AS recurring_monthly_total FROM recurring_invoices WHERE recurring_invoice_status = 1 AND recurring_invoice_frequency = 'month' AND recurring_invoice_client_id = $client_id");
$row = mysqli_fetch_array($sql_recurring_monthly_total);
$recurring_monthly_total = floatval($row['recurring_monthly_total']);
//Get Yearly Recurring Total
$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_yearly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'year' AND recurring_client_id = $client_id");
$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_invoice_amount) AS recurring_yearly_total FROM recurring_invoices WHERE recurring_invoice_status = 1 AND recurring_invoice_frequency = 'year' AND recurring_invoice_client_id = $client_id");
$row = mysqli_fetch_array($sql_recurring_yearly_total);
$recurring_yearly_total = floatval($row['recurring_yearly_total']) / 12;
@@ -499,10 +495,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
require_once "modals/client_add_modal.php";
require_once "modals/client_import_modal.php";
require_once "modals/client_export_modal.php";
require_once "includes/footer.php";

View File

@@ -28,9 +28,11 @@ if (isset($_GET['contact_id'])) {
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_department =nullable_htmlentities($row['contact_department']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_mobile_country_code));
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_photo = nullable_htmlentities($row['contact_photo']);
$contact_pin = nullable_htmlentities($row['contact_pin']);
@@ -69,21 +71,21 @@ if (isset($_GET['contact_id'])) {
$linked_software = array();
// Related Logins Query 1 to 1 relationship
$sql_related_logins = mysqli_query($mysqli, "
// Related Credentials Query 1 to 1 relationship
$sql_related_credentials = mysqli_query($mysqli, "
SELECT
logins.login_id AS logins_login_id, -- Alias for logins.login_id
logins.*, -- All other columns from logins
login_tags.*, -- All columns from login_tags
credentials.credential_id AS credentials_credential_id, -- Alias for credentials.credential_id
credentials.*, -- All other columns from credentials
credential_tags.*, -- All columns from credential_tags
tags.* -- All columns from tags
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
WHERE login_contact_id = $contact_id
GROUP BY logins.login_id
ORDER BY login_name DESC
FROM credentials
LEFT JOIN credential_tags ON credential_tags.credential_id = credentials.credential_id
LEFT JOIN tags ON tags.tag_id = credential_tags.tag_id
WHERE credential_contact_id = $contact_id
GROUP BY credentials.credential_id
ORDER BY credential_name DESC
");
$login_count = mysqli_num_rows($sql_related_logins);
$credential_count = mysqli_num_rows($sql_related_credentials);
// Related Tickets Query - 1 to 1 relationship
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
@@ -93,9 +95,9 @@ if (isset($_GET['contact_id'])) {
$ticket_count = mysqli_num_rows($sql_related_tickets);
// Related Recurring Tickets Query
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
WHERE scheduled_ticket_contact_id = $contact_id
ORDER BY scheduled_ticket_next_run DESC"
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
WHERE recurring_ticket_contact_id = $contact_id
ORDER BY recurring_ticket_next_run DESC"
);
$recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets);
@@ -264,6 +266,22 @@ if (isset($_GET['contact_id'])) {
<i class="fa fa-fw fa-recycle mr-2"></i>New Recurring Ticket
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addAssetModal">
<i class="fa fa-fw fa-desktop mr-2"></i>New Asset
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addCredentialModal">
<i class="fa fa-fw fa-key mr-2"></i>New Credential
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addDocumentModal">
<i class="fa fa-fw fa-file-alt mr-2"></i>New Document
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#uploadFilesModal">
<i class="fa fa-fw fa-upload mr-2"></i>Upload file(s)
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_contact_note_create.php"
@@ -446,7 +464,7 @@ if (isset($_GET['contact_id'])) {
</div>
</div>
<div class="card card-dark <?php if ($login_count == 0) { echo "d-none"; } ?>">
<div class="card card-dark <?php if ($credential_count == 0) { echo "d-none"; } ?>">
<div class="card-header">
<h3 class="card-title"><i class="fa fa-fw fa-key mr-2"></i>Credentials</h3>
</div>
@@ -467,57 +485,57 @@ if (isset($_GET['contact_id'])) {
<tbody>
<?php
while ($row = mysqli_fetch_array($sql_related_logins)) {
$login_id = intval($row['logins_login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
if (empty($login_uri)) {
$login_uri_display = "-";
while ($row = mysqli_fetch_array($sql_related_credentials)) {
$credential_id = intval($row['credentials_credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
if (empty($credential_uri)) {
$credential_uri_display = "-";
} else {
$login_uri_display = "$login_uri<button class='btn btn-sm clipboardjs' data-clipboard-text='$login_uri'><i class='far fa-copy text-secondary'></i></button><a href='$login_uri' target='_blank'><i class='fa fa-external-link-alt text-secondary'></i></a>";
$credential_uri_display = "$credential_uri<button class='btn btn-sm clipboardjs' data-clipboard-text='$credential_uri'><i class='far fa-copy text-secondary'></i></button><a href='$credential_uri' target='_blank'><i class='fa fa-external-link-alt text-secondary'></i></a>";
}
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
if (empty($login_username)) {
$login_username_display = "-";
$credential_uri_2 = nullable_htmlentities($row['credential_uri_2']);
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
if (empty($credential_username)) {
$credential_username_display = "-";
} else {
$login_username_display = "$login_username<button class='btn btn-sm clipboardjs' data-clipboard-text='$login_username'><i class='far fa-copy text-secondary'></i></button>";
$credential_username_display = "$credential_username<button class='btn btn-sm clipboardjs' data-clipboard-text='$credential_username'><i class='far fa-copy text-secondary'></i></button>";
}
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_name_display_array = array();
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT * FROM login_tags LEFT JOIN tags ON login_tags.tag_id = tags.tag_id WHERE login_id = $login_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$credential_tag_name_display_array = array();
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT * FROM credential_tags LEFT JOIN tags ON credential_tags.tag_id = tags.tag_id WHERE credential_id = $credential_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_name = nullable_htmlentities($row['tag_name']);
$login_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($login_tag_color)) {
$login_tag_color = "dark";
$credential_tag_id = intval($row['tag_id']);
$credential_tag_name = nullable_htmlentities($row['tag_name']);
$credential_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($credential_tag_color)) {
$credential_tag_color = "dark";
}
$login_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($login_tag_icon)) {
$login_tag_icon = "tag";
$credential_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($credential_tag_icon)) {
$credential_tag_icon = "tag";
}
$login_tag_id_array[] = $login_tag_id;
$login_tag_name_display_array[] = "<a href='client_logins.php?client_id=$client_id&tags[]=$login_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $login_tag_color;'><i class='fa fa-fw fa-$login_tag_icon mr-2'></i>$login_tag_name</span></a>";
$credential_tag_id_array[] = $credential_tag_id;
$credential_tag_name_display_array[] = "<a href='credentials.php?client_id=$client_id&tags[]=$credential_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $credential_tag_color;'><i class='fa fa-fw fa-$credential_tag_icon mr-2'></i>$credential_tag_name</span></a>";
}
$login_tags_display = implode('', $login_tag_name_display_array);
$credential_tags_display = implode('', $credential_tag_name_display_array);
?>
<tr>
@@ -526,18 +544,18 @@ if (isset($_GET['contact_id'])) {
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_credential_edit.php"
data-ajax-id="<?php echo $login_id; ?>"
data-ajax-id="<?php echo $credential_id; ?>"
>
<?php echo $login_name; ?>
<?php echo $credential_name; ?>
</a>
</td>
<td><?php echo $login_description; ?></td>
<td><?php echo $login_username_display; ?></td>
<td><?php echo $credential_description; ?></td>
<td><?php echo $credential_username_display; ?></td>
<td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $login_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" data-clipboard-text="<?php echo $login_password; ?>"><i class="far fa-copy text-secondary"></i></button>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" data-clipboard-text="<?php echo $credential_password; ?>"><i class="far fa-copy text-secondary"></i></button>
</td>
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td><?php echo $credential_uri_display; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
@@ -547,21 +565,21 @@ if (isset($_GET['contact_id'])) {
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_credential_edit.php"
data-ajax-id="<?php echo $login_id; ?>">
data-ajax-id="<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Login', $login_id"; ?>)">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Credential', $credential_id"; ?>)">
<i class="fas fa-fw fa-share-alt mr-2"></i>Share
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item"
href="post.php?unlink_credential_from_contact&contact_id=<?php echo $contact_id; ?>&login_id=<?php echo $login_id; ?>"
href="post.php?unlink_credential_from_contact&contact_id=<?php echo $contact_id; ?>&credential_id=<?php echo $credential_id; ?>"
class="btn btn-secondary btn-sm" title="Unlink">
<i class="fas fa-fw fa-unlink mr-2"></i>Unlink
</a>
<?php if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold" href="post.php?delete_login=<?php echo $login_id; ?>">
<a class="dropdown-item text-danger text-bold" href="post.php?delete_credential=<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
@@ -683,11 +701,11 @@ if (isset($_GET['contact_id'])) {
<?php
while ($row = mysqli_fetch_array($sql_related_recurring_tickets)) {
$scheduled_ticket_id = intval($row['scheduled_ticket_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$recurring_ticket_id = intval($row['recurring_ticket_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
?>
<tr>
@@ -695,14 +713,14 @@ if (isset($_GET['contact_id'])) {
<a href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_recurring_ticket_edit.php"
data-ajax-id="<?php echo $scheduled_ticket_id; ?>"
data-ajax-id="<?php echo $recurring_ticket_id; ?>"
>
<?php echo $scheduled_ticket_subject ?>
<?php echo $recurring_ticket_subject ?>
</a>
</td>
<td><?php echo $scheduled_ticket_priority ?></td>
<td><?php echo $scheduled_ticket_frequency ?></td>
<td><?php echo $scheduled_ticket_next_run ?></td>
<td><?php echo $recurring_ticket_priority ?></td>
<td><?php echo $recurring_ticket_frequency ?></td>
<td><?php echo $recurring_ticket_next_run ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
@@ -712,18 +730,18 @@ if (isset($_GET['contact_id'])) {
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_recurring_ticket_edit.php"
data-ajax-id="<?php echo $scheduled_ticket_id; ?>"
data-ajax-id="<?php echo $recurring_ticket_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="post.php?force_recurring_ticket=<?php echo $scheduled_ticket_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<a class="dropdown-item" href="post.php?force_recurring_ticket=<?php echo $recurring_ticket_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fa fa-fw fa-paper-plane text-secondary mr-2"></i>Force Reoccur
</a>
<?php
if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?php echo $scheduled_ticket_id; ?>">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?php echo $recurring_ticket_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
@@ -1162,12 +1180,18 @@ if (isset($_GET['contact_id'])) {
});
</script>
<!-- Include script to get TOTP code via the login ID -->
<!-- Include script to get TOTP code via the Credential ID -->
<script src="js/credential_show_otp_via_id.js"></script>
<?php
require_once "modals/ticket_add_modal.php";
require_once "modals/recurring_ticket_add_modal.php";
require_once "modals/asset_add_modal.php";
require_once "modals/credential_add_modal.php";
require_once "modals/client_document_add_modal.php";
require_once "modals/client_file_upload_modal.php";
require_once "modals/contact_link_asset_modal.php";
require_once "modals/contact_link_software_modal.php";
require_once "modals/contact_link_credential_modal.php";
@@ -1175,6 +1199,4 @@ require_once "modals/contact_link_service_modal.php";
require_once "modals/contact_link_document_modal.php";
require_once "modals/contact_link_file_modal.php";
require_once "modals/recurring_ticket_add_modal.php";
require_once "includes/footer.php";

View File

@@ -17,17 +17,13 @@ if (isset($_GET['client_id'])) {
// Tags Filter
if (isset($_GET['tags']) && is_array($_GET['tags']) && !empty($_GET['tags'])) {
// Sanitize each element of the status array
$sanitizedTags = array();
foreach ($_GET['tags'] as $tag) {
// Escape each status to prevent SQL injection
$sanitizedTags[] = "'" . intval($tag) . "'";
}
// Sanitize each element of the tags array
$sanitizedTags = array_map('intval', $_GET['tags']);
// Convert the sanitized tags into a comma-separated string
$sanitizedTagsString = implode(",", $sanitizedTags);
$tag_query = "AND tags.tag_id IN ($sanitizedTagsString)";
$tag_filter = implode(",", $sanitizedTags);
$tag_query = "AND tags.tag_id IN ($tag_filter)";
} else {
$tag_filter = 0;
$tag_query = '';
}
@@ -50,7 +46,7 @@ if ($client_url && isset($_GET['location']) && !empty($_GET['location'])) {
} else {
// Default - any
$location_query = '';
$location_filter = '';
$location_filter = 0;
}
$sql = mysqli_query($mysqli, "SELECT SQL_CALC_FOUND_ROWS contacts.*, clients.*, locations.*, users.*, GROUP_CONCAT(tags.tag_name) FROM contacts
@@ -117,24 +113,25 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="input-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php $sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 3");
while ($row = mysqli_fetch_array($sql_tags)) {
<?php
$sql_tags_filter = mysqli_query($mysqli, "
SELECT tags.tag_id, tags.tag_name
FROM tags
LEFT JOIN contact_tags ON contact_tags.tag_id = tags.tag_id
LEFT JOIN contacts ON contact_tags.contact_id = contacts.contact_id
WHERE tag_type = 3
$client_query OR tags.tag_id IN ($tag_filter)
GROUP BY tags.tag_id
HAVING COUNT(contact_tags.contact_id) > 0 OR tags.tag_id IN ($tag_filter)
");
while ($row = mysqli_fetch_array($sql_tags_filter)) {
$tag_id = intval($row['tag_id']);
$tag_name = nullable_htmlentities($row['tag_name']); ?>
<option value="<?php echo $tag_id ?>" <?php if (isset($_GET['tags']) && is_array($_GET['tags']) && in_array($tag_id, $_GET['tags'])) { echo 'selected'; } ?>> <?php echo $tag_name ?> </option>
<option value="<?php echo $tag_id ?>" <?php if (isset($_GET['tags']) && in_array($tag_id, $_GET['tags'])) { echo 'selected'; } ?>> <?php echo $tag_name ?> </option>
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="2">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
@@ -145,7 +142,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<option value="">- All Locations -</option>
<?php
$sql_locations_filter = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_client_id = $client_id AND location_archived_at IS NULL ORDER BY location_name ASC");
$sql_locations_filter = mysqli_query($mysqli, "
SELECT DISTINCT location_id, location_name
FROM locations
LEFT JOIN contacts ON contact_location_id = location_id
WHERE location_client_id = $client_id
AND location_archived_at IS NULL
AND (contact_location_id != 0 OR location_id = $location_filter)
ORDER BY location_name ASC
");
while ($row = mysqli_fetch_array($sql_locations_filter)) {
$location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
@@ -165,7 +170,14 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
$sql_clients_filter = mysqli_query($mysqli, "
SELECT DISTINCT client_id, client_name
FROM clients
JOIN contacts ON contact_client_id = client_id
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_name ASC
");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
@@ -300,14 +312,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
} else {
$contact_extension_display = "<small class='text-secondary ml-1'>x$contact_extension</small>";
}
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
if (empty($contact_phone)) {
$contact_phone_display = "";
} else {
$contact_phone_display = "<div><i class='fas fa-fw fa-phone mr-2'></i><a href='tel:$contact_phone'>$contact_phone$contact_extension_display</a></div>";
}
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
if (empty($contact_mobile)) {
$contact_mobile_display = "";
} else {
@@ -351,6 +364,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
}
$auth_method = nullable_htmlentities($row['user_auth_method']);
$contact_user_id = intval($row['contact_user_id']);
if ($contact_user_id) {
$user_exists_display = "<span class='badge badge-pill badge-dark p-1' title='User: $auth_method'><i class='fas fa-fw fa-user'></i></span>";
} else {
$user_exists_display = "";
}
// Related Assets Query
$sql_related_assets = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_contact_id = $contact_id ORDER BY asset_id DESC");
@@ -361,13 +379,13 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$asset_count_display = '';
}
// Related Logins Query
$sql_related_logins = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_contact_id = $contact_id ORDER BY login_id DESC");
$login_count = mysqli_num_rows($sql_related_logins);
if ($login_count) {
$login_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$login_count Credentials'><i class='fas fa-fw fa-key mr-2'></i>$login_count</span>";
// Related Credentials Query
$sql_related_credentials = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_contact_id = $contact_id ORDER BY credential_id DESC");
$credential_count = mysqli_num_rows($sql_related_credentials);
if ($credential_count) {
$credential_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$credential_count Credentials'><i class='fas fa-fw fa-key mr-2'></i>$credential_count</span>";
} else {
$login_count_display = '';
$credential_count_display = '';
}
// Related Software Query
@@ -385,7 +403,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if ($ticket_count) {
$ticket_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$ticket_count Tickets'><i class='fas fa-fw fa-life-ring mr-2'></i>$ticket_count</span>";
} else {
$software_count_display = '';
$ticket_count_display = '';
}
// Related Documents Query
@@ -445,7 +463,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php } ?>
<div class="media-body">
<div class="<?php if($contact_important) { echo "text-bold"; } ?>"><?php echo $contact_name; ?></div>
<div class="<?php if($contact_important) { echo "text-bold"; } ?>"><?php echo $contact_name; ?> <?php echo $user_exists_display; ?></div>
<?php echo $contact_title_display; ?>
<div><?php echo $contact_primary_display; ?></div>
<?php
@@ -463,7 +481,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<td><?php echo $contact_info_display; ?></td>
<td><?php echo $location_name_display; ?></td>
<td>
<?php echo "$asset_count_display$login_count_display$software_count_display$ticket_count_display$document_count_display"; ?>
<?php echo "$asset_count_display$credential_count_display$software_count_display$ticket_count_display$document_count_display"; ?>
</td>
<?php if (!$client_url) { ?>
<td><a href="contacts.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>

View File

@@ -1,21 +1,21 @@
<?php
// Default Column Sortby Filter
$sort = "login_name";
$sort = "credential_name";
$order = "ASC";
// If client_id is in URI then show client Side Bar and client header
if (isset($_GET['client_id'])) {
require_once "includes/inc_all_client.php";
$client_query = "AND login_client_id = $client_id";
$client_query = "AND credential_client_id = $client_id";
$client_url = "client_id=$client_id&";
// Log when users load the Credentials/Logins page
// Log when users load the Credentials page
logAction("Credential", "View", "$session_name viewed the Credentials page for client", $client_id);
} else {
require_once "includes/inc_client_overview_all.php";
$client_query = '';
$client_url = '';
// Log when users load the Credentials/Logins page
// Log when users load the Credentials page
logAction("Credential", "View", "$session_name viewed the All Credentials page");
}
@@ -24,24 +24,20 @@ enforceUserPermission('module_credential');
// Tags Filter
if (isset($_GET['tags']) && is_array($_GET['tags']) && !empty($_GET['tags'])) {
// Sanitize each element of the status array
$sanitizedTags = array();
foreach ($_GET['tags'] as $tag) {
// Escape each status to prevent SQL injection
$sanitizedTags[] = "'" . intval($tag) . "'";
}
// Sanitize each element of the tags array
$sanitizedTags = array_map('intval', $_GET['tags']);
// Convert the sanitized tags into a comma-separated string
$sanitizedTagsString = implode(",", $sanitizedTags);
$tag_query = "AND tags.tag_id IN ($sanitizedTagsString)";
$tag_filter = implode(",", $sanitizedTags);
$tag_query = "AND tags.tag_id IN ($tag_filter)";
} else {
$tag_filter = 0;
$tag_query = '';
}
if (!$client_url) {
// Client Filter
if (isset($_GET['client']) & !empty($_GET['client'])) {
$client_query = 'AND (login_client_id = ' . intval($_GET['client']) . ')';
$client_query = 'AND (credential_client_id = ' . intval($_GET['client']) . ')';
$client = intval($_GET['client']);
} else {
// Default - any
@@ -53,7 +49,7 @@ if (!$client_url) {
// Location Filter
if ($client_url && isset($_GET['location']) && !empty($_GET['location'])) {
$location_query = 'AND (a.asset_location_id = ' . intval($_GET['location']) . ')';
$location_query_innerjoin = 'INNER JOIN assets a on a.asset_id = l.login_asset_id ';
$location_query_innerjoin = 'INNER JOIN assets a on a.asset_id = c.credential_asset_id ';
$location_filter = intval($_GET['location']);
} else {
// Default - any
@@ -64,22 +60,22 @@ if ($client_url && isset($_GET['location']) && !empty($_GET['location'])) {
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS l.login_id AS l_login_id, l.*, login_tags.*, tags.*, clients.*, contacts.*, assets.*
FROM logins l
LEFT JOIN login_tags ON login_tags.login_id = l.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
LEFT JOIN clients ON client_id = login_client_id
LEFT JOIN contacts ON contact_id = login_contact_id
LEFT JOIN assets ON asset_id = login_asset_id
"SELECT SQL_CALC_FOUND_ROWS c.credential_id AS c_credential_id, c.*, credential_tags.*, tags.*, clients.*, contacts.*, assets.*
FROM credentials c
LEFT JOIN credential_tags ON credential_tags.credential_id = c.credential_id
LEFT JOIN tags ON tags.tag_id = credential_tags.tag_id
LEFT JOIN clients ON client_id = credential_client_id
LEFT JOIN contacts ON contact_id = credential_contact_id
LEFT JOIN assets ON asset_id = credential_asset_id
$location_query_innerjoin
WHERE l.login_$archive_query
WHERE c.credential_$archive_query
$tag_query
AND (l.login_name LIKE '%$q%' OR l.login_description LIKE '%$q%' OR l.login_uri LIKE '%$q%' OR tag_name LIKE '%$q%' OR client_name LIKE '%$q%')
AND (c.credential_name LIKE '%$q%' OR c.credential_description LIKE '%$q%' OR c.credential_uri LIKE '%$q%' OR tag_name LIKE '%$q%' OR client_name LIKE '%$q%')
$location_query
$access_permission_query
$client_query
GROUP BY l.login_id
ORDER BY l.login_important DESC, $sort $order LIMIT $record_from, $record_to"
GROUP BY c.credential_id
ORDER BY c.credential_important DESC, $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
@@ -92,17 +88,17 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="card-tools">
<?php if (lookupUserPermission("module_credential") >= 2) { ?>
<div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addLoginModal" <?php if (!isset($_COOKIE['user_encryption_session_key'])) { echo "disabled"; } ?>>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addCredentialModal" <?php if (!isset($_COOKIE['user_encryption_session_key'])) { echo "disabled"; } ?>>
<i class="fas fa-plus mr-2"></i>New Credential
</button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu">
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#importLoginModal">
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#importCredentialModal">
<i class="fa fa-fw fa-upload mr-2"></i>Import
</a>
<?php if ($num_rows[0] > 0) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#exportLoginModal">
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#exportCredentialModal">
<i class="fa fa-fw fa-download mr-2"></i>Export
</a>
<?php } ?>
@@ -126,6 +122,32 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
</div>
<div class="col-md-3">
<div class="input-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php
$sql_tags_filter = mysqli_query($mysqli, "
SELECT tags.tag_id, tags.tag_name
FROM tags
LEFT JOIN credential_tags ON credential_tags.tag_id = tags.tag_id
LEFT JOIN credentials ON credential_tags.credential_id = credentials.credential_id
WHERE tag_type = 4
$client_query OR tags.tag_id IN ($tag_filter)
GROUP BY tags.tag_id
HAVING COUNT(credential_tags.credential_id) > 0 OR tags.tag_id IN ($tag_filter)
");
while ($row = mysqli_fetch_array($sql_tags_filter)) {
$tag_id = intval($row['tag_id']);
$tag_name = nullable_htmlentities($row['tag_name']); ?>
<option value="<?php echo $tag_id ?>" <?php if (isset($_GET['tags']) && is_array($_GET['tags']) && in_array($tag_id, $_GET['tags'])) { echo 'selected'; } ?>> <?php echo $tag_name ?> </option>
<?php } ?>
</select>
</div>
</div>
<?php if ($client_url) { ?>
<div class="col-md-2">
@@ -154,7 +176,14 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
$sql_clients_filter = mysqli_query($mysqli, "
SELECT DISTINCT client_id, client_name
FROM clients
JOIN credentials ON credential_client_id = client_id
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_name ASC
");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
@@ -169,31 +198,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
<?php } ?>
<div class="col-md-3">
<div class="input-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php $sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 4");
while ($row = mysqli_fetch_array($sql_tags)) {
$tag_id = intval($row['tag_id']);
$tag_name = nullable_htmlentities($row['tag_name']); ?>
<option value="<?php echo $tag_id ?>" <?php if (isset($_GET['tags']) && is_array($_GET['tags']) && in_array($tag_id, $_GET['tags'])) { echo 'selected'; } ?>> <?php echo $tag_name ?> </option>
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="4">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
<div class="col-md-3">
<div class="btn-group float-right">
<a href="?<?php echo $client_url; ?>&archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
@@ -207,12 +211,12 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="dropdown-menu">
<?php if ($archived) { ?>
<button class="dropdown-item text-info"
type="submit" form="bulkActions" name="bulk_unarchive_logins">
type="submit" form="bulkActions" name="bulk_unarchive_credentials">
<i class="fas fa-fw fa-redo mr-2"></i>Unarchive
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger text-bold"
type="submit" form="bulkActions" name="bulk_delete_logins">
type="submit" form="bulkActions" name="bulk_delete_credentials">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</button>
<?php } else { ?>
@@ -221,7 +225,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</a>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger confirm-link"
type="submit" form="bulkActions" name="bulk_archive_logins">
type="submit" form="bulkActions" name="bulk_archive_credentials">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</button>
<?php } ?>
@@ -246,16 +250,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</td>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=login_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'login_name') { echo $order_icon; } ?>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=credential_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'credential_name') { echo $order_icon; } ?>
</a>
</th>
<th>Username / ID</th>
<th>Password / Key</th>
<th>OTP</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=login_uri&order=<?php echo $disp; ?>">
URI <?php if ($sort == 'login_uri') { echo $order_icon; } ?>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=credential_uri&order=<?php echo $disp; ?>">
URI <?php if ($sort == 'credential_uri') { echo $order_icon; } ?>
</a>
</th>
<th></th>
@@ -275,80 +279,80 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
while ($row = mysqli_fetch_array($sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$login_id = intval($row['l_login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
if (empty($login_uri)) {
$login_uri_display = "-";
$credential_id = intval($row['c_credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
if (empty($credential_uri)) {
$credential_uri_display = "-";
} else {
$login_uri_display = truncate($login_uri,40) . "<button class='btn btn-sm clipboardjs' type='button' data-clipboard-text='$login_uri'><i class='far fa-copy text-secondary'></i></button>";
$credential_uri_display = truncate($credential_uri,40) . "<button class='btn btn-sm clipboardjs' type='button' data-clipboard-text='$credential_uri'><i class='far fa-copy text-secondary'></i></button>";
}
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
if (empty($login_username)) {
$login_username_display = "-";
$credential_uri_2 = nullable_htmlentities($row['credential_uri_2']);
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
if (empty($credential_username)) {
$credential_username_display = "-";
} else {
$login_username_display = "$login_username<button class='btn btn-sm clipboardjs' type='button' data-clipboard-text='$login_username'><i class='far fa-copy text-secondary'></i></button>";
$credential_username_display = "$credential_username<button class='btn btn-sm clipboardjs' type='button' data-clipboard-text='$credential_username'><i class='far fa-copy text-secondary'></i></button>";
}
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_created_at = nullable_htmlentities($row['login_created_at']);
$login_archived_at = nullable_htmlentities($row['login_archived_at']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_created_at = nullable_htmlentities($row['credential_created_at']);
$credential_archived_at = nullable_htmlentities($row['credential_archived_at']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
$login_asset_id = intval($row['login_asset_id']);
$credential_asset_id = intval($row['credential_asset_id']);
$asset_name = nullable_htmlentities($row['asset_name']);
// Tags
$login_tag_name_display_array = array();
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT * FROM login_tags LEFT JOIN tags ON login_tags.tag_id = tags.tag_id WHERE login_id = $login_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$credential_tag_name_display_array = array();
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT * FROM credential_tags LEFT JOIN tags ON credential_tags.tag_id = tags.tag_id WHERE credential_id = $credential_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_name = nullable_htmlentities($row['tag_name']);
$login_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($login_tag_color)) {
$login_tag_color = "dark";
$credential_tag_id = intval($row['tag_id']);
$credential_tag_name = nullable_htmlentities($row['tag_name']);
$credential_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($credential_tag_color)) {
$credential_tag_color = "dark";
}
$login_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($login_tag_icon)) {
$login_tag_icon = "tag";
$credential_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($credential_tag_icon)) {
$credential_tag_icon = "tag";
}
$login_tag_id_array[] = $login_tag_id;
$login_tag_name_display_array[] = "<a href='credentials.php?$client_url tags[]=$login_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $login_tag_color;'><i class='fa fa-fw fa-$login_tag_icon mr-2'></i>$login_tag_name</span></a>";
$credential_tag_id_array[] = $credential_tag_id;
$credential_tag_name_display_array[] = "<a href='credentials.php?$client_url tags[]=$credential_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $credential_tag_color;'><i class='fa fa-fw fa-$credential_tag_icon mr-2'></i>$credential_tag_name</span></a>";
}
$login_tags_display = implode('', $login_tag_name_display_array);
$credential_tags_display = implode('', $credential_tag_name_display_array);
if ($login_contact_id) {
$login_contact_display = "<a href='#' class='mr-2 badge badge-pill badge-dark p-2' title='$contact_name'
if ($credential_contact_id) {
$credential_contact_display = "<a href='#' class='mr-2 badge badge-pill badge-dark p-2' title='$contact_name'
data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_contact_details.php'
data-ajax-id='$login_contact_id'>
data-ajax-id='$credential_contact_id'>
<i class='fas fa-fw fa-user'></i></a>";
} else {
$login_contact_display = '';
$credential_contact_display = '';
}
if ($login_asset_id) {
$login_asset_display = "<a href='#' class='mr-2 badge badge-pill badge-secondary p-2' title='$asset_name' data-toggle='ajax-modal'
if ($credential_asset_id) {
$credential_asset_display = "<a href='#' class='mr-2 badge badge-pill badge-secondary p-2' title='$asset_name' data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_asset_details.php'
data-ajax-id='$login_asset_id'>
data-ajax-id='$credential_asset_id'>
<i class='fas fa-fw fa-desktop'></i></a>";
} else {
$login_asset_display = '';
$credential_asset_display = '';
}
// Check if shared
@@ -359,8 +363,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
AND item_active = 1
AND item_views != item_view_limit
AND item_expire_at > NOW()
AND item_type = 'Login'
AND item_related_id = $login_id
AND item_type = 'Credential'
AND item_related_id = $credential_id
LIMIT 1"
);
if (mysqli_num_rows($sql_shared) > 0) {
@@ -381,41 +385,41 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<tr class="<?php if (!empty($login_important)) { echo "text-bold"; } ?>">
<tr class="<?php if (!empty($credential_important)) { echo "text-bold"; } ?>">
<td class="pr-0">
<div class="form-check">
<input class="form-check-input bulk-select" type="checkbox" name="login_ids[]" value="<?php echo $login_id ?>">
<input class="form-check-input bulk-select" type="checkbox" name="credential_ids[]" value="<?php echo $credential_id ?>">
</div>
</td>
<td>
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_credential_edit.php"
data-ajax-id="<?php echo $login_id; ?>"
data-ajax-id="<?php echo $credential_id; ?>"
>
<div class="media">
<i class="fa fa-fw fa-2x fa-key mr-3"></i>
<div class="media-body">
<div><?php echo $login_name; ?></div>
<div><small class="text-secondary"><?php echo $login_description; ?></small></div>
<div><?php echo $credential_name; ?></div>
<div><small class="text-secondary"><?php echo $credential_description; ?></small></div>
<?php
if (!empty($login_tags_display)) { ?>
if (!empty($credential_tags_display)) { ?>
<div class="mt-1">
<?php echo $login_tags_display; ?>
<?php echo $credential_tags_display; ?>
</div>
<?php } ?>
</div>
</div>
</a>
</td>
<td><?php echo $login_username_display; ?></td>
<td><?php echo $credential_username_display; ?></td>
<td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $login_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" type="button" data-clipboard-text="<?php echo $login_password; ?>"><i class="far fa-copy text-secondary"></i></button>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" type="button" data-clipboard-text="<?php echo $credential_password; ?>"><i class="far fa-copy text-secondary"></i></button>
</td>
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td><?php echo $credential_uri_display; ?></td>
<td>
<?php echo "$login_contact_display$login_asset_display"; ?>
<?php echo "$credential_contact_display$credential_asset_display"; ?>
<?php if (mysqli_num_rows($sql_shared) > 0) { ?>
<div class="media" title="Expires <?php echo $item_expire_at_human; ?>">
<i class="fas fa-link mr-2 mt-1"></i>
@@ -431,21 +435,21 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php } ?>
<td class="text-center">
<div class="btn-group">
<?php if ( !empty($login_uri) || !empty($login_uri_2) ) { ?>
<?php if ( !empty($credential_uri) || !empty($credential_uri_2) ) { ?>
<div class="dropdown dropleft text-center">
<button class="btn btn-default btn-sm" type="button" data-toggle="dropdown">
<i class="fa fa-fw fa-external-link-alt"></i>
</button>
<div class="dropdown-menu">
<?php if ($login_uri) { ?>
<a href="<?php echo $login_uri; ?>" alt="<?php echo $login_uri; ?>" target="_blank" class="dropdown-item" >
<i class="fa fa-fw fa-external-link-alt"></i> <?php echo truncate($login_uri,40); ?>
<?php if ($credential_uri) { ?>
<a href="<?php echo $credential_uri; ?>" alt="<?php echo $credential_uri; ?>" target="_blank" class="dropdown-item" >
<i class="fa fa-fw fa-external-link-alt"></i> <?php echo truncate($credential_uri,40); ?>
</a>
<?php } ?>
<?php if ($login_uri_2) { ?>
<?php if ($credential_uri_2) { ?>
<div class="dropdown-divider"></div>
<a href="<?php echo $login_uri_2; ?>" target="_blank" class="dropdown-item" >
<i class="fa fa-fw fa-external-link-alt"></i> <?php echo truncate($login_uri_2,40); ?>
<a href="<?php echo $credential_uri_2; ?>" target="_blank" class="dropdown-item" >
<i class="fa fa-fw fa-external-link-alt"></i> <?php echo truncate($credential_uri_2,40); ?>
</a>
<?php } ?>
</div>
@@ -459,29 +463,29 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_credential_edit.php"
data-ajax-id="<?php echo $login_id; ?>"
data-ajax-id="<?php echo $credential_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Login', $login_id"; ?>)">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Credential', $credential_id"; ?>)">
<i class="fas fa-fw fa-share mr-2"></i>Share
</a>
<?php if (lookupUserPermission("module_credential") >= 2) { ?>
<?php if ($login_archived_at) { ?>
<?php if ($credential_archived_at) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-info confirm-link" href="post.php?unarchive_login=<?php echo $login_id; ?>">
<a class="dropdown-item text-info confirm-link" href="post.php?unarchive_credential=<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-redo mr-2"></i>Unarchive
</a>
<?php if (lookupUserPermission("module_credential") >= 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_login=<?php echo $login_id; ?>">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_credential=<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
<?php } ?>
</a>
<?php } else { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?archive_login=<?php echo $login_id; ?>">
<a class="dropdown-item text-danger confirm-link" href="post.php?archive_credential=<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
<?php } ?>

View File

@@ -73,11 +73,6 @@ $sql_years_select = mysqli_query($mysqli, "
<?php
if ($user_config_dashboard_financial_enable == 1) {
// Ensure the user has the appropriate role to view the financial dashboard
if ($_SESSION['user_role'] != 3 && $_SESSION['user_role'] != 1) {
exit('<script type="text/javascript">window.location.href = \'dashboard_technical.php\';</script>');
}
// Fetch financial data for the dashboard
// Define variables to avoid errors in logs
$largest_income_month = 0;
@@ -129,11 +124,11 @@ if ($user_config_dashboard_financial_enable == 1) {
");
// Get recurring invoice totals
$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_yearly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'year' AND YEAR(recurring_created_at) <= $year");
$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_invoice_amount) AS recurring_yearly_total FROM recurring_invoices WHERE recurring_invoice_status = 1 AND recurring_invoice_frequency = 'year' AND YEAR(recurring_invoice_created_at) <= $year");
$row = mysqli_fetch_array($sql_recurring_yearly_total);
$recurring_yearly_total = floatval($row['recurring_yearly_total']);
$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_monthly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'month' AND YEAR(recurring_created_at) <= $year");
$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_invoice_amount) AS recurring_monthly_total FROM recurring_invoices WHERE recurring_invoice_status = 1 AND recurring_invoice_frequency = 'month' AND YEAR(recurring_invoice_created_at) <= $year");
$row = mysqli_fetch_array($sql_recurring_monthly_total);
$recurring_monthly_total = floatval($row['recurring_monthly_total']) + ($recurring_yearly_total / 12);

File diff suppressed because it is too large Load Diff

1044
db.sql

File diff suppressed because it is too large Load Diff

View File

@@ -18,8 +18,17 @@ if (isset($_GET['client_id'])) {
// Perms
enforceUserPermission('module_support');
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
if (!$client_url) {
// Client Filter
if (isset($_GET['client']) & !empty($_GET['client'])) {
$client_query = 'AND (domain_client_id = ' . intval($_GET['client']) . ')';
$client = intval($_GET['client']);
} else {
// Default - any
$client_query = '';
$client = '';
}
}
$sql = mysqli_query($mysqli, "SELECT SQL_CALC_FOUND_ROWS domains.*, clients.*,
registrar.vendor_id AS registrar_id,
@@ -79,7 +88,38 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
<div class="col-md-8">
<?php if ($client_url) { ?>
<div class="col-md-2"></div>
<?php } else { ?>
<div class="col-md-2">
<div class="input-group">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "
SELECT DISTINCT client_id, client_name
FROM clients
JOIN domains ON domain_client_id = client_id
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_name ASC
");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<option <?php if ($client == $client_id) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } ?>
<div class="col-md-6">
<div class="btn-group float-right">
<a href="?<?php echo $client_url; ?>archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
class="btn btn-<?php if($archived == 1){ echo "primary"; } else { echo "default"; } ?>">
@@ -261,7 +301,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div><small><?php echo $domain_expire_ago; ?></small></div>
</td>
<?php if (!$client_url) { ?>
<td><?php echo $client_name; ?></td>
<td><a href="domains.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
<?php } ?>
<td>
<div class="dropdown dropleft text-center">

View File

@@ -13,8 +13,7 @@ use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
// Function to generate both crypto & URL safe random strings
function randomString($length = 16)
{
function randomString($length = 16) {
// Generate some cryptographically safe random bytes
// Generate a little more than requested as we'll lose some later converting
$random_bytes = random_bytes($length + 5);
@@ -31,8 +30,7 @@ function randomString($length = 16)
}
// Older keygen function - only used for TOTP currently
function key32gen()
{
function key32gen() {
$chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$chars .= "234567";
while (1) {
@@ -46,25 +44,23 @@ function key32gen()
return $key;
}
function nullable_htmlentities($unsanitizedInput)
{
function nullable_htmlentities($unsanitizedInput) {
//return htmlentities($unsanitizedInput ?? '');
return htmlspecialchars($unsanitizedInput ?? '', ENT_QUOTES, 'UTF-8');
}
function initials($str)
{
if (!empty($str)) {
$ret = '';
foreach (explode(' ', $str) as $word)
$ret .= strtoupper($word[0]);
$ret = substr($ret, 0, 2);
return $ret;
function initials($string) {
if (!empty($string)) {
$return = '';
foreach (explode(' ', $string) as $word) {
$return .= mb_strtoupper($word[0], 'UTF-8'); // Use mb_strtoupper for UTF-8 support
}
$return = substr($return, 0, 2);
return $return;
}
}
function removeDirectory($path)
{
function removeDirectory($path) {
if (!file_exists($path)) {
return;
}
@@ -76,13 +72,11 @@ function removeDirectory($path)
rmdir($path);
}
function getUserAgent()
{
function getUserAgent() {
return $_SERVER['HTTP_USER_AGENT'];
}
function getIP()
{
function getIP() {
if (defined("CONST_GET_IP_METHOD")) {
if (CONST_GET_IP_METHOD == "HTTP_X_FORWARDED_FOR") {
$ip = getenv('HTTP_X_FORWARDED_FOR');
@@ -100,8 +94,7 @@ function getIP()
return $ip;
}
function getWebBrowser($user_browser)
{
function getWebBrowser($user_browser) {
$browser = "-";
$browser_array = array(
'/msie/i' => "<i class='fab fa-fw fa-internet-explorer text-secondary'></i> Internet Explorer",
@@ -120,8 +113,7 @@ function getWebBrowser($user_browser)
return $browser;
}
function getOS($user_os)
{
function getOS($user_os) {
$os_platform = "-";
$os_array = array(
'/windows/i' => "<i class='fab fa-fw fa-windows text-secondary'></i> Windows",
@@ -141,8 +133,7 @@ function getOS($user_os)
return $os_platform;
}
function getDevice()
{
function getDevice() {
$tablet_browser = 0;
$mobile_browser = 0;
if (preg_match('/(tablet|ipad|playbook)|(android(?!.*(mobi|opera mini)))/i', strtolower($_SERVER['HTTP_USER_AGENT']))) {
@@ -189,8 +180,7 @@ function getDevice()
}
}
function truncate($text, $chars)
{
function truncate($text, $chars) {
if (strlen($text) <= $chars) {
return $text;
}
@@ -203,45 +193,147 @@ function truncate($text, $chars)
return $text . "...";
}
function formatPhoneNumber($phoneNumber)
{
global $mysqli;
function formatPhoneNumber($phoneNumber, $country_code = '', $show_country_code = false) {
// Get Phone Mask Option
$phone_mask = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_phone_mask FROM settings WHERE company_id = 1"))[0];
// Remove all non-digit characters
$digits = preg_replace('/\D/', '', $phoneNumber);
$formatted = '';
if ($phone_mask == 0) {
return $phoneNumber;
switch ($country_code) {
case '1': // USA/Canada — (123) 456-7890
if (strlen($digits) === 10) {
$formatted = '(' . substr($digits, 0, 3) . ') ' . substr($digits, 3, 3) . '-' . substr($digits, 6);
}
break;
case '44': // UK — 07123 456 789
if ($digits[0] === '0') $digits = substr($digits, 1);
if (strlen($digits) === 10) {
$formatted = '0' . substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
}
break;
case '61': // Australia — 0412 345 678
if ($digits[0] === '0') $digits = substr($digits, 1);
if (strlen($digits) === 9) {
$formatted = '0' . substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
}
break;
case '91': // India — 91234 56789
if (strlen($digits) === 10) {
$formatted = substr($digits, 0, 5) . ' ' . substr($digits, 5);
}
break;
case '81': // Japan — 03-1234-5678
if ($digits[0] === '0') $digits = substr($digits, 1);
if (strlen($digits) >= 9 && strlen($digits) <= 10) {
$formatted = '0' . substr($digits, 0, 2) . '-' . substr($digits, 2, 4) . '-' . substr($digits, 6);
}
break;
case '49': // Germany — 030 12345678
if ($digits[0] === '0') $digits = substr($digits, 1);
if (strlen($digits) >= 10) {
$formatted = '0' . substr($digits, 0, 3) . ' ' . substr($digits, 3);
}
break;
case '33': // France — 01 23 45 67 89
if ($digits[0] === '0') $digits = substr($digits, 1);
if (strlen($digits) === 9) {
$formatted = '0' . implode(' ', str_split($digits, 2));
}
break;
case '34': // Spain — 612 345 678
if (strlen($digits) === 9) {
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
}
break;
case '39': // Italy — 312 345 6789
if ($digits[0] === '0') $digits = substr($digits, 1);
$formatted = '0' . implode(' ', str_split($digits, 3));
break;
case '55': // Brazil — (11) 91234-5678
if (strlen($digits) === 11) {
$formatted = '(' . substr($digits, 0, 2) . ') ' . substr($digits, 2, 5) . '-' . substr($digits, 7);
}
break;
case '7': // Russia — 8 (912) 345-67-89
if ($digits[0] === '8') $digits = substr($digits, 1);
if (strlen($digits) === 10) {
$formatted = '8 (' . substr($digits, 0, 3) . ') ' . substr($digits, 3, 3) . '-' . substr($digits, 6, 2) . '-' . substr($digits, 8);
}
break;
case '86': // China — 138 0013 8000
if (strlen($digits) === 11) {
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 4) . ' ' . substr($digits, 7);
}
break;
case '82': // South Korea — 010-1234-5678
if (strlen($digits) === 11) {
$formatted = substr($digits, 0, 3) . '-' . substr($digits, 3, 4) . '-' . substr($digits, 7);
}
break;
case '62': // Indonesia — 0812 3456 7890
if ($digits[0] !== '0') $digits = '0' . $digits;
if (strlen($digits) === 12) {
$formatted = substr($digits, 0, 4) . ' ' . substr($digits, 4, 4) . ' ' . substr($digits, 8);
}
break;
case '63': // Philippines — 0912 345 6789
if (strlen($digits) === 11) {
$formatted = substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
}
break;
case '234': // Nigeria — 0801 234 5678
if ($digits[0] !== '0') $digits = '0' . $digits;
if (strlen($digits) === 11) {
$formatted = substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
}
break;
case '27': // South Africa — 082 123 4567
if (strlen($digits) >= 9 && strlen($digits) <= 10) {
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
}
break;
case '971': // UAE — 050 123 4567
if (strlen($digits) === 9) {
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
}
break;
default:
// If no match, do nothing here and use fallback below
break;
}
$phoneNumber = $phoneNumber ? preg_replace('/[^0-9]/', '', $phoneNumber) : "";
if (strlen($phoneNumber) > 10) {
$countryCode = substr($phoneNumber, 0, strlen($phoneNumber) - 10);
$areaCode = substr($phoneNumber, -10, 3);
$nextThree = substr($phoneNumber, -7, 3);
$lastFour = substr($phoneNumber, -4, 4);
$phoneNumber = '+' . $countryCode . ' (' . $areaCode . ') ' . $nextThree . '-' . $lastFour;
} else if (strlen($phoneNumber) == 10) {
$areaCode = substr($phoneNumber, 0, 3);
$nextThree = substr($phoneNumber, 3, 3);
$lastFour = substr($phoneNumber, 6, 4);
$phoneNumber = '(' . $areaCode . ') ' . $nextThree . '-' . $lastFour;
} else if (strlen($phoneNumber) == 7) {
$nextThree = substr($phoneNumber, 0, 3);
$lastFour = substr($phoneNumber, 3, 4);
$phoneNumber = $nextThree . '-' . $lastFour;
// Fallback if formatting failed
if (!$formatted && strlen($digits) >= 7) {
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
}
return $phoneNumber;
// Still no formatting? Use raw digits
if (!$formatted) {
$formatted = $digits ?: $phoneNumber; // Use original input if digits are empty
}
return $show_country_code && $country_code ? "+$country_code $formatted" : $formatted;
}
function mkdirMissing($dir)
{
function mkdirMissing($dir) {
if (!is_dir($dir)) {
mkdir($dir);
}
@@ -249,8 +341,7 @@ function mkdirMissing($dir)
// Called during initial setup
// Encrypts the master key with the user's password
function setupFirstUserSpecificKey($user_password, $site_encryption_master_key)
{
function setupFirstUserSpecificKey($user_password, $site_encryption_master_key) {
$iv = randomString();
$salt = randomString();
@@ -268,8 +359,7 @@ function setupFirstUserSpecificKey($user_password, $site_encryption_master_key)
* New Users: Requires the admin setting up their account have a Specific/Session key configured
* Password Changes: Will use the current info in the session.
*/
function encryptUserSpecificKey($user_password)
{
function encryptUserSpecificKey($user_password) {
$iv = randomString();
$salt = randomString();
@@ -334,13 +424,13 @@ function generateUserSessionKey($site_encryption_master_key)
}
}
// Decrypts an encrypted password (website/asset login), returns it as a string
function decryptLoginEntry($login_password_ciphertext)
// Decrypts an encrypted password (website/asset credentials), returns it as a string
function decryptCredentialEntry($credential_password_ciphertext)
{
// Split the login into IV and Ciphertext
$login_iv = substr($login_password_ciphertext, 0, 16);
$login_ciphertext = $salt = substr($login_password_ciphertext, 16);
// Split the credential into IV and Ciphertext
$credential_iv = substr($credential_password_ciphertext, 0, 16);
$credential_ciphertext = $salt = substr($credential_password_ciphertext, 16);
// Get the user session info.
$user_encryption_session_ciphertext = $_SESSION['user_encryption_session_ciphertext'];
@@ -350,12 +440,12 @@ function decryptLoginEntry($login_password_ciphertext)
// Decrypt the session key to get the master key
$site_encryption_master_key = openssl_decrypt($user_encryption_session_ciphertext, 'aes-128-cbc', $user_encryption_session_key, 0, $user_encryption_session_iv);
// Decrypt the login password using the master key
return openssl_decrypt($login_ciphertext, 'aes-128-cbc', $site_encryption_master_key, 0, $login_iv);
// Decrypt the credential password using the master key
return openssl_decrypt($credential_ciphertext, 'aes-128-cbc', $site_encryption_master_key, 0, $credential_iv);
}
// Encrypts a website/asset login password
function encryptLoginEntry($login_password_cleartext)
// Encrypts a website/asset credential password
function encryptCredentialEntry($credential_password_cleartext)
{
$iv = randomString();
@@ -367,26 +457,26 @@ function encryptLoginEntry($login_password_cleartext)
//Decrypt the session key to get the master key
$site_encryption_master_key = openssl_decrypt($user_encryption_session_ciphertext, 'aes-128-cbc', $user_encryption_session_key, 0, $user_encryption_session_iv);
//Encrypt the website/asset login using the master key
$ciphertext = openssl_encrypt($login_password_cleartext, 'aes-128-cbc', $site_encryption_master_key, 0, $iv);
//Encrypt the website/asset credential using the master key
$ciphertext = openssl_encrypt($credential_password_cleartext, 'aes-128-cbc', $site_encryption_master_key, 0, $iv);
return $iv . $ciphertext;
}
function apiDecryptLoginEntry($login_ciphertext, $api_key_decrypt_hash, #[\SensitiveParameter]$api_key_decrypt_password)
function apiDecryptCredentialEntry($credential_ciphertext, $api_key_decrypt_hash, #[\SensitiveParameter]$api_key_decrypt_password)
{
// Split the login entry (username/password) into IV and Ciphertext
$login_iv = substr($login_ciphertext, 0, 16);
$login_ciphertext = $salt = substr($login_ciphertext, 16);
// Split the Credential entry (username/password) into IV and Ciphertext
$credential_iv = substr($credential_ciphertext, 0, 16);
$credential_ciphertext = $salt = substr($credential_ciphertext, 16);
// Decrypt the api hash to get the master key
$site_encryption_master_key = decryptUserSpecificKey($api_key_decrypt_hash, $api_key_decrypt_password);
// Decrypt the login password using the master key
return openssl_decrypt($login_ciphertext, 'aes-128-cbc', $site_encryption_master_key, 0, $login_iv);
// Decrypt the credential password using the master key
return openssl_decrypt($credential_ciphertext, 'aes-128-cbc', $site_encryption_master_key, 0, $credential_iv);
}
function apiEncryptLoginEntry(#[\SensitiveParameter]$credential_cleartext, $api_key_decrypt_hash, #[\SensitiveParameter]$api_key_decrypt_password)
function apiEncryptCredentialEntry(#[\SensitiveParameter]$credential_cleartext, $api_key_decrypt_hash, #[\SensitiveParameter]$api_key_decrypt_password)
{
$iv = randomString();
@@ -539,9 +629,9 @@ function validateCSRFToken($token)
* Accountant - 1
*/
function validateAdminRole()
{
if (!isset($_SESSION['user_role']) || $_SESSION['user_role'] != 3) {
function validateAdminRole() {
global $session_user_role;
if (!isset($session_user_role) || $session_user_role != 3) {
$_SESSION['alert_type'] = "danger";
$_SESSION['alert_message'] = WORDING_ROLECHECK_FAILED;
header("Location: " . $_SERVER["HTTP_REFERER"]);
@@ -551,9 +641,9 @@ function validateAdminRole()
// LEGACY
// Validates a user is a tech (or admin). Stops page load and attempts to direct away from the page if not (i.e. user is an accountant)
function validateTechRole()
{
if (!isset($_SESSION['user_role']) || $_SESSION['user_role'] == 1) {
function validateTechRole() {
global $session_user_role;
if (!isset($session_user_role) || $session_user_role == 1) {
$_SESSION['alert_type'] = "danger";
$_SESSION['alert_message'] = WORDING_ROLECHECK_FAILED;
header("Location: " . $_SERVER["HTTP_REFERER"]);
@@ -563,9 +653,9 @@ function validateTechRole()
// LEGACY
// Validates a user is an accountant (or admin). Stops page load and attempts to direct away from the page if not (i.e. user is a tech)
function validateAccountantRole()
{
if (!isset($_SESSION['user_role']) || $_SESSION['user_role'] == 2) {
function validateAccountantRole() {
global $session_user_role;
if (!isset($session_user_role) || $session_user_role == 2) {
$_SESSION['alert_type'] = "danger";
$_SESSION['alert_message'] = WORDING_ROLECHECK_FAILED;
header("Location: " . $_SERVER["HTTP_REFERER"]);
@@ -765,7 +855,7 @@ function checkFileUpload($file, $allowed_extensions)
$fileContent = file_get_contents($tmp);
// Hash the file content using SHA-256
$hashedContent = hash('sha256', $fileContent);
$hashedContent = hash('md5', $fileContent);
// Generate a secure filename using the hashed content
$secureFilename = $hashedContent . randomString(2) . '.' . $extension;
@@ -1321,15 +1411,15 @@ function lookupUserPermission($module) {
$sql = mysqli_query(
$mysqli,
"SELECT
urp.user_role_permission_level
user_role_permissions.user_role_permission_level
FROM
modules AS m
modules
JOIN
user_role_permissions AS urp
user_role_permissions
ON
m.module_id = urp.module_id
modules.module_id = user_role_permissions.module_id
WHERE
m.module_name = '$module' AND urp.user_role_id = $session_user_role"
module_name = '$module' AND user_role_permissions.user_role_id = $session_user_role"
);
$row = mysqli_fetch_array($sql);
@@ -1420,5 +1510,117 @@ function logAuth($status, $details) {
// Helper function for missing data fallback
function getFallback($data) {
return !empty($data) ? $data : '<span class="text-muted">N/A</span>';
return !empty($data) ? $data : '-';
}
/**
* Retrieves a specified field's value from a table based on the record's id.
* It validates the table and field names, automatically determines the primary key (or uses the first column as fallback),
* and returns the field value with an appropriate escaping method.
*
* @param string $table The name of the table.
* @param int $id The record's id.
* @param string $field The field (column) to retrieve.
* @param string $escape_method The escape method: 'sql' (default, auto-detects int), 'html', 'json', or 'int'.
*
* @return mixed The escaped field value, or null if not found or invalid input.
*/
function getFieldById($table, $id, $field, $escape_method = 'sql') {
global $mysqli; // Use the global MySQLi connection
// Validate table and field names to allow only letters, numbers, and underscores
if (!preg_match('/^[a-zA-Z0-9_]+$/', $table) || !preg_match('/^[a-zA-Z0-9_]+$/', $field)) {
return null; // Invalid table or field name
}
// Sanitize id as an integer
$id = (int)$id;
// Get the list of columns and their details from the table
$columns_result = mysqli_query($mysqli, "SHOW COLUMNS FROM `$table`");
if (!$columns_result || mysqli_num_rows($columns_result) == 0) {
return null; // Table not found or has no columns
}
// Build an associative array with column details
$columns = [];
while ($row = mysqli_fetch_assoc($columns_result)) {
$columns[$row['Field']] = [
'type' => $row['Type'],
'key' => $row['Key']
];
}
// Find the primary key field if available
$id_field = null;
foreach ($columns as $col => $details) {
if ($details['key'] === 'PRI') {
$id_field = $col;
break;
}
}
// Fallback: if no primary key is found, use the first column
if (!$id_field) {
reset($columns);
$id_field = key($columns);
}
// Ensure the requested field exists; if not, default to the id field
if (!array_key_exists($field, $columns)) {
$field = $id_field;
}
// Build and execute the query to fetch the specified field value
$query = "SELECT `$field` FROM `$table` WHERE `$id_field` = $id";
$sql = mysqli_query($mysqli, $query);
if ($sql && mysqli_num_rows($sql) > 0) {
$row = mysqli_fetch_assoc($sql);
$value = $row[$field];
// Apply the desired escaping method or auto-detect integer type if using SQL escaping
switch ($escape_method) {
case 'html':
return htmlspecialchars($value ?? '', ENT_QUOTES, 'UTF-8'); // Escape for HTML
case 'json':
return json_encode($value); // Escape for JSON
case 'int':
return (int)$value; // Explicitly cast value to integer
case 'sql':
default:
// Auto-detect if the field type is integer
if (stripos($columns[$field]['type'], 'int') !== false) {
return (int)$value;
} else {
return sanitizeInput($value); // Escape for SQL using a custom function
}
}
}
return null; // Return null if no record was found
}
// Recursive function to display folder options - Used in folders files and documents
function display_folder_options($parent_folder_id, $client_id, $indent = 0) {
global $mysqli;
$sql_folders = mysqli_query($mysqli, "SELECT * FROM folders WHERE parent_folder = $parent_folder_id AND folder_location = 1 AND folder_client_id = $client_id ORDER BY folder_name ASC");
while ($row = mysqli_fetch_array($sql_folders)) {
$folder_id = intval($row['folder_id']);
$folder_name = nullable_htmlentities($row['folder_name']);
// Indentation for subfolders
$indentation = str_repeat('&nbsp;', $indent * 4);
// Check if this folder is selected
$selected = '';
if ((isset($_GET['folder_id']) && $_GET['folder_id'] == $folder_id) || (isset($_POST['folder']) && $_POST['folder'] == $folder_id)) {
$selected = 'selected';
}
echo "<option value=\"$folder_id\" $selected>$indentation$folder_name</option>";
// Recursively display subfolders
display_folder_options($folder_id, $client_id, $indent + 1);
}
}

View File

@@ -23,7 +23,7 @@ if (isset($_GET['query'])) {
$sql_clients = mysqli_query($mysqli, "SELECT * FROM clients
LEFT JOIN locations ON clients.client_id = locations.location_client_id AND location_primary = 1
WHERE client_archived_at IS NULL
AND client_name LIKE '%$query%'
AND (client_name LIKE '%$query%' OR client_abbreviation LIKE '%$query%')
$access_permission_query
ORDER BY client_id DESC LIMIT 5"
);
@@ -91,21 +91,21 @@ if (isset($_GET['query'])) {
ORDER BY ticket_id DESC LIMIT 5"
);
$sql_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
LEFT JOIN clients ON scheduled_ticket_client_id = client_id
WHERE (scheduled_ticket_subject LIKE '%$query%'
OR scheduled_ticket_details LIKE '%$query%')
$sql_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
LEFT JOIN clients ON recurring_ticket_client_id = client_id
WHERE (recurring_ticket_subject LIKE '%$query%'
OR recurring_ticket_details LIKE '%$query%')
$access_permission_query
ORDER BY scheduled_ticket_id DESC LIMIT 5"
ORDER BY recurring_ticket_id DESC LIMIT 5"
);
$sql_logins = mysqli_query($mysqli, "SELECT * FROM logins
LEFT JOIN contacts ON login_contact_id = contact_id
LEFT JOIN clients ON login_client_id = client_id
WHERE login_archived_at IS NULL
AND (login_name LIKE '%$query%' OR login_description LIKE '%$query%')
$sql_credentials = mysqli_query($mysqli, "SELECT * FROM credentials
LEFT JOIN contacts ON credential_contact_id = contact_id
LEFT JOIN clients ON credential_client_id = client_id
WHERE credential_archived_at IS NULL
AND (credential_name LIKE '%$query%' OR credential_description LIKE '%$query%')
$access_permission_query
ORDER BY login_id DESC LIMIT 5"
ORDER BY credential_id DESC LIMIT 5"
);
$sql_invoices = mysqli_query($mysqli, "SELECT * FROM invoices
@@ -172,7 +172,8 @@ if (isset($_GET['query'])) {
while ($row = mysqli_fetch_array($sql_clients)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$location_phone = formatPhoneNumber($row['location_phone']);
$location_phone_country_code = nullable_htmlentities($row['location_phone_country_code']);
$location_phone = nullable_htmlentities(formatPhoneNumber($row['location_phone'], $location_phone_country_code));
$client_website = nullable_htmlentities($row['client_website']);
?>
@@ -218,9 +219,11 @@ if (isset($_GET['query'])) {
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
$contact_email = nullable_htmlentities($row['contact_email']);
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
@@ -272,7 +275,8 @@ if (isset($_GET['query'])) {
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_name = nullable_htmlentities($row['vendor_name']);
$vendor_description = nullable_htmlentities($row['vendor_description']);
$vendor_phone = formatPhoneNumber($row['vendor_phone']);
$vendor_phone_country_code = nullable_htmlentities($row['vendor_phone_country_code']);
$vendor_phone = nullable_htmlentities(formatPhoneNumber($row['vendor_phone'], $vendor_phone_country_code));
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
@@ -544,18 +548,18 @@ if (isset($_GET['query'])) {
<?php
while ($row = mysqli_fetch_array($sql_recurring_tickets)) {
$scheduled_ticket_id = intval($row['scheduled_ticket_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$recurring_ticket_id = intval($row['recurring_ticket_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
$client_name = nullable_htmlentities($row['client_name']);
$client_id = intval($row['client_id']);
?>
<tr>
<td><a href="recurring_tickets.php"><?php echo $scheduled_ticket_subject; ?></a></td>
<td><?php echo $scheduled_ticket_frequency; ?></td>
<td><?php echo $scheduled_ticket_next_run; ?></td>
<td><a href="recurring_tickets.php"><?php echo $recurring_ticket_subject; ?></a></td>
<td><?php echo $recurring_ticket_frequency; ?></td>
<td><?php echo $recurring_ticket_next_run; ?></td>
<td><a href="recurring_tickets.php?client_id=<?php echo $client_id ?>"><?php echo $client_name; ?></a></td>
</tr>
@@ -571,9 +575,9 @@ if (isset($_GET['query'])) {
<?php } ?>
<?php if (mysqli_num_rows($sql_logins) > 0) { ?>
<?php if (mysqli_num_rows($sql_credentials) > 0) { ?>
<!-- Logins -->
<!-- Credentials -->
<div class="col-sm-6">
<div class="card card-dark mb-3">
<div class="card-header">
@@ -593,21 +597,21 @@ if (isset($_GET['query'])) {
<tbody>
<?php
while ($row = mysqli_fetch_array($sql_logins)) {
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_client_id = intval($row['login_client_id']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
while ($row = mysqli_fetch_array($sql_credentials)) {
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_client_id = intval($row['credential_client_id']);
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<tr>
<td><a href="credentials.php?client_id=<?php echo $login_client_id ?>&q=<?php echo $q ?>"><?php echo $login_name; ?></a></td>
<td><?php echo $login_description; ?></td>
<td><?php echo $login_username; ?></td>
<td><a tabindex="0" class="btn btn-sm" data-toggle="popover" data-trigger="focus" data-placement="left" data-content="<?php echo $login_password; ?>"><i class="far fa-eye text-secondary"></i></a><button class="btn btn-sm clipboardjs" data-clipboard-text="<?php echo $login_password; ?>"><i class="far fa-copy text-secondary"></i></button>
<td><a href="credentials.php?client_id=<?php echo $credential_client_id ?>&q=<?php echo $q ?>"><?php echo $credential_name; ?></a></td>
<td><?php echo $credential_description; ?></td>
<td><?php echo $credential_username; ?></td>
<td><a tabindex="0" class="btn btn-sm" data-toggle="popover" data-trigger="focus" data-placement="left" data-content="<?php echo $credential_password; ?>"><i class="far fa-eye text-secondary"></i></a><button class="btn btn-sm clipboardjs" data-clipboard-text="<?php echo $credential_password; ?>"><i class="far fa-copy text-secondary"></i></button>
</td>
<td><a href="credentials.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
</tr>

View File

@@ -9,7 +9,7 @@
require_once "../config.php";
// Set Timezone
require_once "../inc_set_timezone.php";
require_once "../includes/inc_set_timezone.php";
require_once "../functions.php";
require_once "../plugins/totp/totp.php";

View File

@@ -3,7 +3,7 @@
require_once "../config.php";
// Set Timezone
require_once "../inc_set_timezone.php";
require_once "../includes/inc_set_timezone.php";
require_once "../functions.php";

View File

@@ -1,6 +1,6 @@
<?php
require_once 'guest_header.php';
require_once 'includes/guest_header.php';
// Define wording
DEFINE("WORDING_PAYMENT_FAILED", "<br><h2>There was an error verifying your payment. Please contact us for more information before attempting payment again.</h2>");
@@ -19,7 +19,7 @@ $config_stripe_flat_fee = floatval($stripe_vars['config_stripe_flat_fee']);
// Check Stripe is configured
if ($config_stripe_enable == 0 || $config_stripe_account == 0 || empty($config_stripe_publishable) || empty($config_stripe_secret)) {
echo "<br><h2>Stripe payments not enabled/configured</h2>";
require_once 'guest_footer.php';
require_once 'includes/guest_footer.php';
error_log("Stripe payment error - disabled. Check payments are enabled, Expense account is set, Stripe publishable and secret keys are configured.");
exit();
}
@@ -47,7 +47,7 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
// Ensure we have a valid invoice
if (!$sql || mysqli_num_rows($sql) !== 1) {
echo "<br><h2>Oops, something went wrong! Please ensure you have the correct URL and have not already paid this invoice.</h2>";
require_once 'guest_footer.php';
require_once 'includes/guest_footer.php';
error_log("Stripe payment error - Invoice with ID $invoice_id is unknown/not eligible to be paid.");
exit();
}
@@ -357,4 +357,4 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
}
require_once 'guest_footer.php';
require_once 'includes/guest_footer.php';

View File

@@ -5,7 +5,7 @@ require_once "../functions.php";
session_start();
require_once "../inc_set_timezone.php"; // Must be included after session_start to work
require_once "../includes/inc_set_timezone.php"; // Must be included after session_start to work
if (isset($_GET['accept_quote'], $_GET['url_key'])) {
$quote_id = intval($_GET['accept_quote']);

View File

@@ -1,10 +1,10 @@
<?php
require_once "guest_header.php";
require_once "includes/guest_header.php";
if (!isset($_GET['invoice_id'], $_GET['url_key'])) {
echo "<br><h2>Oops, something went wrong! Please raise a ticket if you believe this is an error.</h2>";
require_once "guest_footer.php";
require_once "includes/guest_footer.php";
exit();
}
@@ -25,7 +25,7 @@ $sql = mysqli_query(
if (mysqli_num_rows($sql) !== 1) {
// Invalid invoice/key
echo "<br><h2>Oops, something went wrong! Please raise a ticket if you believe this is an error.</h2>";
require_once "guest_footer.php";
require_once "includes/guest_footer.php";
exit();
}
@@ -51,9 +51,11 @@ $location_city = nullable_htmlentities($row['location_city']);
$location_state = nullable_htmlentities($row['location_state']);
$location_zip = nullable_htmlentities($row['location_zip']);
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
$client_website = nullable_htmlentities($row['client_website']);
$client_currency_code = nullable_htmlentities($row['client_currency_code']);
$client_net_terms = intval($row['client_net_terms']);
@@ -69,7 +71,8 @@ $company_address = nullable_htmlentities($row['company_address']);
$company_city = nullable_htmlentities($row['company_city']);
$company_state = nullable_htmlentities($row['company_state']);
$company_zip = nullable_htmlentities($row['company_zip']);
$company_phone = formatPhoneNumber($row['company_phone']);
$company_phone_country_code = nullable_htmlentities($row['company_phone_country_code']);
$company_phone = nullable_htmlentities(formatPhoneNumber($row['company_phone'], $company_phone_country_code));
$company_email = nullable_htmlentities($row['company_email']);
$company_website = nullable_htmlentities($row['company_website']);
$company_logo = nullable_htmlentities($row['company_logo']);
@@ -931,4 +934,4 @@ if ($outstanding_invoices_count > 0) { ?>
<?php } // End previous unpaid invoices
require_once "guest_footer.php";
require_once "includes/guest_footer.php";

View File

@@ -4,7 +4,7 @@ header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
require_once "guest_header.php";
require_once "includes/guest_header.php";
//Initialize the HTML Purifier to prevent XSS
@@ -23,7 +23,8 @@ $company_address = nullable_htmlentities($row['company_address']);
$company_city = nullable_htmlentities($row['company_city']);
$company_state = nullable_htmlentities($row['company_state']);
$company_zip = nullable_htmlentities($row['company_zip']);
$company_phone = formatPhoneNumber($row['company_phone']);
$company_phone_country_code = nullable_htmlentities($row['company_phone_country_code']);
$company_phone = nullable_htmlentities(formatPhoneNumber($row['company_phone'], $company_phone_country_code));
$company_email = nullable_htmlentities($row['company_email']);
$company_website = nullable_htmlentities($row['company_website']);
$company_logo = nullable_htmlentities($row['company_logo']);
@@ -38,7 +39,7 @@ $currency_format = numfmt_create($company_locale, NumberFormatter::CURRENCY);
<?php
if (!isset($_GET['id']) || !isset($_GET['key'])) {
echo "<div class='alert alert-danger'>Incorrect URL.</div>";
include "guest_footer.php";
include "includes/guest_footer.php";
exit();
}
@@ -52,7 +53,7 @@ $row = mysqli_fetch_array($sql);
// Check we got a result
if (mysqli_num_rows($sql) !== 1 || !$row) {
echo "<div class='alert alert-danger' >No item to view. Check with the person that sent you this link to ensure it is correct and has not expired.</div>";
include "guest_footer.php";
include "includes/guest_footer.php";
exit();
}
@@ -60,7 +61,7 @@ if (mysqli_num_rows($sql) !== 1 || !$row) {
// Check item share is active & hasn't been viewed too many times but allow 0 views as that is consider infinite views
if ($row['item_active'] !== "1" || ($row['item_view_limit'] > 0 && $row['item_views'] >= $row['item_view_limit'])) {
echo "<div class='alert alert-danger'>Item cannot be viewed at this time. Check with the person that sent you this link to ensure it is correct and has not expired.</div>";
include "guest_footer.php";
include "includes/guest_footer.php";
exit();
}
@@ -122,7 +123,7 @@ if ($item_type == "Document") {
if (mysqli_num_rows($doc_sql) !== 1 || !$doc_row) {
echo "<div class='alert alert-danger'>Error retrieving document to view.</div>";
require_once "guest_footer.php";
require_once "includes/guest_footer.php";
exit();
}
@@ -149,7 +150,7 @@ if ($item_type == "Document") {
if (mysqli_num_rows($file_sql) !== 1 || !$file_row) {
echo "<div class='alert alert-danger'>Error retrieving file.</div>";
include "guest_footer.php";
include "includes/guest_footer.php";
exit();
}
@@ -163,61 +164,61 @@ if ($item_type == "Document") {
echo "<a href='guest_download_file.php?id=$item_id&key=$item_key'>Download $file_name</a>";
} elseif ($item_type == "Login") {
} elseif ($item_type == "Credential") {
$encryption_key = $_GET['ek'];
$login_sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = $item_related_id AND login_client_id = $client_id LIMIT 1");
$login_row = mysqli_fetch_array($login_sql);
if (mysqli_num_rows($login_sql) !== 1 || !$login_row) {
$credential_sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = $item_related_id AND credential_client_id = $client_id LIMIT 1");
$credential_row = mysqli_fetch_array($credential_sql);
if (mysqli_num_rows($credential_sql) !== 1 || !$credential_row) {
echo "<div class='alert alert-danger'>Error retrieving login.</div>";
include "guest_footer.php";
include "includes/guest_footer.php";
exit();
}
$login_id = intval($login_row['login_id']);
$login_name = nullable_htmlentities($login_row['login_name']);
$login_uri = nullable_htmlentities($login_row['login_uri']);
$credential_id = intval($credential_row['credential_id']);
$credential_name = nullable_htmlentities($credential_row['credential_name']);
$credential_uri = nullable_htmlentities($credential_row['credential_uri']);
$username_iv = substr($row['item_encrypted_username'], 0, 16);
$username_ciphertext = substr($row['item_encrypted_username'], 16);
$login_username = nullable_htmlentities(openssl_decrypt($username_ciphertext, 'aes-128-cbc', $encryption_key, 0, $username_iv));
$credential_username = nullable_htmlentities(openssl_decrypt($username_ciphertext, 'aes-128-cbc', $encryption_key, 0, $username_iv));
$password_iv = substr($row['item_encrypted_credential'], 0, 16);
$password_ciphertext = substr($row['item_encrypted_credential'], 16);
$login_password = nullable_htmlentities(openssl_decrypt($password_ciphertext, 'aes-128-cbc', $encryption_key, 0, $password_iv));
$credential_password = nullable_htmlentities(openssl_decrypt($password_ciphertext, 'aes-128-cbc', $encryption_key, 0, $password_iv));
$login_otp = nullable_htmlentities($login_row['login_otp_secret']);
$credential_otp = nullable_htmlentities($credential_row['credential_otp_secret']);
$login_otp_secret = nullable_htmlentities($login_row['login_otp_secret']);
$login_id_with_secret = '"' . $login_row['login_id'] . '","' . $login_row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_otp_secret = nullable_htmlentities($credential_row['credential_otp_secret']);
$credential_id_with_secret = '"' . $credential_row['credential_id'] . '","' . $credential_row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTP($login_id_with_secret)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTP($credential_id_with_secret)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_notes = nullable_htmlentities($login_row['login_note']);
$credential_notes = nullable_htmlentities($credential_row['credential_note']);
?>
<h5><?php echo $login_name; ?></h5>
<h5><?php echo $credential_name; ?></h5>
<table class="table col-md-3">
<tr>
<th>URL</th>
<td><?php echo $login_uri; ?></td>
<td><?php echo $credential_uri; ?></td>
</tr>
<tr>
<th>Username</th>
<td><?php echo $login_username ?></td>
<td><?php echo $credential_username ?></td>
</tr>
<tr>
<th>Password</th>
<td><?php echo $login_password ?></td>
<td><?php echo $credential_password ?></td>
</tr>
<?php if(!empty($login_otp_secret)){ ?>
<?php if(!empty($credential_otp_secret)){ ?>
<tr>
<th>2FA (TOTP)</th>
<td><?php echo $otp_display ?></td>
@@ -250,12 +251,12 @@ if ($item_type == "Document") {
<?php
// Update login view count
// Update credential view count
$new_item_views = $item_views + 1;
mysqli_query($mysqli, "UPDATE shared_items SET item_views = $new_item_views WHERE item_id = $item_id");
// Logging
$name = sanitizeInput($login_row['login_name']);
$name = sanitizeInput($credential_row['credential_name']);
logAction("Share", "View", "Viewed shared $item_type $name via link", $client_id);
}
@@ -273,6 +274,6 @@ if ($item_type == "Document") {
</div>
<?php
require_once "guest_footer.php";
require_once "includes/guest_footer.php";
?>

View File

@@ -1,11 +1,11 @@
<?php
require_once "guest_header.php";
require_once "includes/guest_header.php";
if (!isset($_GET['quote_id'], $_GET['url_key'])) {
echo "<br><h2>Oops, something went wrong! Please raise a ticket if you believe this is an error.</h2>";
require_once "guest_footer.php";
require_once "includes/guest_footer.php";
exit();
}
@@ -27,7 +27,7 @@ $sql = mysqli_query(
if (mysqli_num_rows($sql) !== 1) {
// Invalid quote/key
echo "<br><h2>Oops, something went wrong! Please raise a ticket if you believe this is an error.</h2>";
require_once "guest_footer.php";
require_once "includes/guest_footer.php";
exit();
}
@@ -52,9 +52,11 @@ $location_city = nullable_htmlentities($row['location_city']);
$location_state = nullable_htmlentities($row['location_state']);
$location_zip = nullable_htmlentities($row['location_zip']);
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
$client_website = nullable_htmlentities($row['client_website']);
$client_currency_code = nullable_htmlentities($row['client_currency_code']);
$client_net_terms = intval($row['client_net_terms']);
@@ -69,7 +71,8 @@ $company_address = nullable_htmlentities($row['company_address']);
$company_city = nullable_htmlentities($row['company_city']);
$company_state = nullable_htmlentities($row['company_state']);
$company_zip = nullable_htmlentities($row['company_zip']);
$company_phone = formatPhoneNumber($row['company_phone']);
$company_phone_country_code = nullable_htmlentities($row['company_phone_country_code']);
$company_phone = nullable_htmlentities(formatPhoneNumber($row['company_phone'], $company_phone_country_code));
$company_email = nullable_htmlentities($row['company_email']);
$company_website = nullable_htmlentities($row['company_website']);
$company_logo = nullable_htmlentities($row['company_logo']);
@@ -717,5 +720,5 @@ if ($quote_status == "Draft" || $quote_status == "Sent" || $quote_status == "Vie
<?php
require_once "guest_quote_upload_file_modal.php";
require_once "guest_footer.php";
require_once "includes/guest_footer.php";

View File

@@ -1,6 +1,6 @@
<?php
require_once "guest_header.php";
require_once "includes/guest_header.php";
//Initialize the HTML Purifier to prevent XSS
require "../plugins/htmlpurifier/HTMLPurifier.standalone.php";
@@ -12,13 +12,14 @@ $purifier = new HTMLPurifier($purifier_config);
if (!isset($_GET['ticket_id'], $_GET['url_key'])) {
echo "<br><h2>Oops, something went wrong! Please raise a ticket if you believe this is an error.</h2>";
require_once "guest_footer.php";
require_once "includes/guest_footer.php";
exit();
}
// Company info
$company_sql_row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT company_phone, company_website FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1"));
$company_phone = formatPhoneNumber($company_sql_row['company_phone']);
$company_phone_country_code = nullable_htmlentities($company_sql_row['company_phone_country_code']);
$company_phone = nullable_htmlentities(formatPhoneNumber($company_sql_row['company_phone'], $company_phone_country_code));
$company_website = nullable_htmlentities($company_sql_row['company_website']);
$url_key = sanitizeInput($_GET['url_key']);
@@ -34,7 +35,7 @@ $ticket_sql = mysqli_query($mysqli,
if (mysqli_num_rows($ticket_sql) !== 1) {
// Invalid invoice/key
echo "<br><h2>Oops, something went wrong! Please raise a ticket if you believe this is an error.</h2>";
require_once "guest_footer.php";
require_once "includes/guest_footer.php";
exit();
}
@@ -208,4 +209,4 @@ if ($ticket_row) {
</div>
<?php
require_once "guest_footer.php";
require_once "includes/guest_footer.php";

View File

@@ -6,7 +6,7 @@ require_once "../functions.php";
session_start();
// Set Timezone
require_once "../inc_set_timezone.php";
require_once "../includes/inc_set_timezone.php";
$ip = sanitizeInput(getIP());
$user_agent = sanitizeInput($_SERVER['HTTP_USER_AGENT']);

View File

@@ -2,7 +2,7 @@
require_once "../config.php";
require_once "../functions.php";
require_once "../check_login.php";
require_once "check_login.php";
header('Content-Type: application/json');

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.3");
DEFINE("APP_VERSION", "25.03");

View File

@@ -13,31 +13,25 @@ if (!isset($_SESSION)) {
// Check to see if setup is enabled
if (!isset($config_enable_setup) || $config_enable_setup == 1) {
header("Location: setup.php");
header("Location: ../setup.php");
exit;
}
// Check user is logged in with a valid session
if (!isset($_SESSION['logged']) || !$_SESSION['logged']) {
if ($_SERVER["REQUEST_URI"] == "/") {
header("Location: login.php");
header("Location: ../login.php");
} else {
header("Location: login.php?last_visited=" . base64_encode($_SERVER["REQUEST_URI"]) );
header("Location: ../login.php?last_visited=" . base64_encode($_SERVER["REQUEST_URI"]) );
}
exit;
}
// Check user type
if ($_SESSION['user_type'] !== 1) {
header("Location: login.php");
exit();
}
// Set Timezone
require_once "inc_set_timezone.php";
// User IP & UA
// User Vars and User Settings
$session_ip = sanitizeInput(getIP());
$session_user_agent = sanitizeInput($_SERVER['HTTP_USER_AGENT']);
@@ -47,7 +41,7 @@ $sql = mysqli_query(
$mysqli,
"SELECT * FROM users
LEFT JOIN user_settings ON users.user_id = user_settings.user_id
LEFT JOIN user_roles ON user_settings.user_role = user_roles.user_role_id
LEFT JOIN user_roles ON user_role_id = role_id
WHERE users.user_id = $session_user_id");
$row = mysqli_fetch_array($sql);
@@ -55,9 +49,10 @@ $session_name = sanitizeInput($row['user_name']);
$session_email = $row['user_email'];
$session_avatar = $row['user_avatar'];
$session_token = $row['user_token']; // MFA Token
$session_user_role = intval($row['user_role']);
$session_user_role_display = sanitizeInput($row['user_role_name']);
if (isset($row['user_role_is_admin']) && $row['user_role_is_admin'] == 1) {
$session_user_type = intval($row['user_type']);
$session_user_role = intval($row['user_role_id']);
$session_user_role_display = sanitizeInput($row['role_name']);
if (isset($row['role_is_admin']) && $row['role_is_admin'] == 1) {
$session_is_admin = true;
} else {
$session_is_admin = false;
@@ -65,6 +60,15 @@ if (isset($row['user_role_is_admin']) && $row['user_role_is_admin'] == 1) {
$session_user_config_force_mfa = intval($row['user_config_force_mfa']);
$user_config_records_per_page = intval($row['user_config_records_per_page']);
// Check user type
if ($session_user_type !== 1) {
session_unset();
session_destroy();
header("Location: login.php");
exit();
}
// Company Vars and Company Settings
$sql = mysqli_query($mysqli, "SELECT * FROM companies, settings WHERE settings.company_id = companies.company_id AND companies.company_id = 1");
$row = mysqli_fetch_array($sql);
@@ -78,7 +82,7 @@ $session_company_currency = $row['company_currency'];
$currency_format = numfmt_create($session_company_locale, NumberFormatter::CURRENCY);
// Get User Client Access Permissions
$user_client_access_sql = "SELECT client_id FROM user_permissions WHERE user_id = $session_user_id";
$user_client_access_sql = "SELECT client_id FROM user_client_permissions WHERE user_id = $session_user_id";
$user_client_access_result = mysqli_query($mysqli, $user_client_access_sql);
$client_access_array = [];

View File

@@ -74,14 +74,26 @@
<p>
Recurring Tickets
<?php
if ($num_scheduled_tickets) { ?>
<span class="right badge"><?php echo $num_scheduled_tickets; ?></span>
if ($num_recurring_tickets) { ?>
<span class="right badge"><?php echo $num_recurring_tickets; ?></span>
<?php } ?>
</p>
</a>
</li>
<li class="nav-item">
<a href="projects.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "projects.php" || basename($_SERVER["PHP_SELF"]) == "project_details.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-project-diagram"></i>
<p>
Projects
<?php if ($num_active_projects) { ?>
<span class="right badge text-light" data-toggle="tooltip" title="Open Projects"><?php echo $num_active_projects; ?></span>
<?php } ?>
</p>
</a>
</li>
<?php } ?>
<li class="nav-item">
@@ -103,8 +115,8 @@
<p>
Calendar
<?php
if ($num_events > 0) { ?>
<span class="right badge text-light"><?php echo $num_events; ?></span>
if ($num_calendar_events > 0) { ?>
<span class="right badge text-light"><?php echo $num_calendar_events; ?></span>
<?php } ?>
</p>
</a>
@@ -147,8 +159,8 @@
<p>
Credentials
<?php
if ($num_logins > 0) { ?>
<span class="right badge text-light"><?php echo $num_logins; ?></span>
if ($num_credentials > 0) { ?>
<span class="right badge text-light"><?php echo $num_credentials; ?></span>
<?php } ?>
</p>
</a>
@@ -277,8 +289,8 @@
<p>
Recurring Invoices
<?php
if ($num_recurring > 0) { ?>
<span class="right badge"><?php echo $num_recurring; ?></span>
if ($num_recurring_invoices) { ?>
<span class="right badge"><?php echo $num_recurring_invoices; ?></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.7");
DEFINE("LATEST_DATABASE_VERSION", "2.1.2");

View File

@@ -33,7 +33,7 @@ if (str_contains(basename($_SERVER["PHP_SELF"]), "admin_")) { ?>
<script src="plugins/clipboardjs/clipboard.min.js"></script>
<script src="js/keepalive.js"></script>
<script src="plugins/DataTables/datatables.min.js"></script>
<script src="plugins/intl-tel-input/js/intlTelInput.min.js"></script>
<!-- AdminLTE App -->
<script src="plugins/adminlte/js/adminlte.min.js"></script>

View File

@@ -49,8 +49,8 @@ $config_invoice_late_fee_percent = floatval($row['config_invoice_late_fee_percen
$config_invoice_paid_notification_email = $row['config_invoice_paid_notification_email'];
// Recurring Invoices
$config_recurring_prefix = $row['config_recurring_prefix'];
$config_recurring_next_number = intval($row['config_recurring_next_number']);
$config_recurring_invoice_prefix = $row['config_recurring_invoice_prefix'];
$config_recurring_invoice_next_number = intval($row['config_recurring_invoice_next_number']);
// Quotes
$config_quote_prefix = $row['config_quote_prefix'];
@@ -142,21 +142,22 @@ $config_whitelabel_key = $row['config_whitelabel_key'];
$theme_colors_array = array (
'lightblue',
'blue',
'green',
'cyan',
'yellow',
'red',
'black',
'gray',
'indigo',
'navy',
'purple',
'fuchsia',
'pink',
'maroon',
'orange',
'green',
'olive',
'teal',
'olive'
'red',
'maroon',
'pink',
'purple',
'indigo',
'fuchsia',
'yellow',
'orange',
'yellow',
'black',
'navy',
'gray'
);
$colors_array = array (

View File

@@ -10,7 +10,7 @@ $row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('ticket_id') AS nu
$num_active_tickets = $row['num'];
// Recurring Ticket Count
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('scheduled_ticket_id') AS num FROM scheduled_tickets LEFT JOIN clients ON client_id = scheduled_ticket_client_id WHERE 1 = 1 $access_permission_query"));
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_ticket_id') AS num FROM recurring_tickets LEFT JOIN clients ON client_id = recurring_ticket_client_id WHERE 1 = 1 $access_permission_query"));
$num_recurring_tickets = $row['num'];
// Active Project Count
@@ -22,7 +22,7 @@ $row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('invoice_id') AS n
$num_open_invoices = $row['num'];
// Recurring Invoice Count
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_id') AS num FROM recurring WHERE recurring_archived_at IS NULL"));
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_invoice_id') AS num FROM recurring_invoices WHERE recurring_invoice_archived_at IS NULL"));
$num_recurring_invoices = $row['num'];
// Open Quotes Count

View File

@@ -39,6 +39,7 @@ header("X-Frame-Options: DENY");
<link href='plugins/daterangepicker/daterangepicker.css' rel='stylesheet' />
<link href="plugins/toastr/toastr.min.css" rel="stylesheet">
<link href="plugins/DataTables/datatables.min.css" rel="stylesheet">
<link href="plugins/intl-tel-input/css/intlTelInput.min.css" rel="stylesheet">
<!-- CSS to allow regular button to show as block button in mobile response view using the class btn-responsive -->
<link href="css/itflow_custom.css" rel="stylesheet">

View File

@@ -61,9 +61,11 @@ if (isset($_GET['client_id'])) {
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
$contact_primary = intval($row['contact_primary']);
$location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
@@ -72,7 +74,8 @@ if (isset($_GET['client_id'])) {
$location_state = nullable_htmlentities($row['location_state']);
$location_zip = nullable_htmlentities($row['location_zip']);
$location_country = nullable_htmlentities($row['location_country']);
$location_phone = formatPhoneNumber($row['location_phone']);
$location_phone_country_code = nullable_htmlentities($row['location_phone_country_code']);
$location_phone = nullable_htmlentities(formatPhoneNumber($row['location_phone'], $location_phone_country_code));
$location_primary = intval($row['location_primary']);
// Tab Title // No Sanitizing needed
@@ -115,13 +118,13 @@ if (isset($_GET['client_id'])) {
$balance = $invoice_amounts - $amount_paid;
//Get Monthly Recurring Total
$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_monthly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'month' AND recurring_client_id = $client_id");
$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_invoice_amount) AS recurring_monthly_total FROM recurring_invoices WHERE recurring_invoice_status = 1 AND recurring_invoice_frequency = 'month' AND recurring_invoice_client_id = $client_id");
$row = mysqli_fetch_array($sql_recurring_monthly_total);
$recurring_monthly_total = floatval($row['recurring_monthly_total']);
//Get Yearly Recurring Total
$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_yearly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'year' AND recurring_client_id = $client_id");
$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_invoice_amount) AS recurring_yearly_total FROM recurring_invoices WHERE recurring_invoice_status = 1 AND recurring_invoice_frequency = 'year' AND recurring_invoice_client_id = $client_id");
$row = mysqli_fetch_array($sql_recurring_yearly_total);
$recurring_yearly_total = floatval($row['recurring_yearly_total']) / 12;
@@ -145,8 +148,12 @@ if (isset($_GET['client_id'])) {
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('ticket_id') AS num FROM tickets WHERE ticket_archived_at IS NULL AND ticket_closed_at IS NOT NULL AND ticket_client_id = $client_id"));
$num_closed_tickets = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('scheduled_ticket_id') AS num FROM scheduled_tickets WHERE scheduled_ticket_client_id = $client_id"));
$num_scheduled_tickets = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_ticket_id') AS num FROM recurring_tickets WHERE recurring_ticket_client_id = $client_id"));
$num_recurring_tickets = $row['num'];
// Active Project Count
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('project_id') AS num FROM projects WHERE project_archived_at IS NULL AND project_completed_at IS NULL AND project_client_id = $client_id"));
$num_active_projects = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('service_id') AS num FROM services WHERE service_client_id = $client_id"));
$num_services = $row['num'];
@@ -154,8 +161,8 @@ if (isset($_GET['client_id'])) {
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('vendor_id') AS num FROM vendors WHERE vendor_archived_at IS NULL AND vendor_client_id = $client_id AND vendor_template = 0"));
$num_vendors = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('login_id') AS num FROM logins WHERE login_archived_at IS NULL AND login_client_id = $client_id"));
$num_logins = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('credential_id') AS num FROM credentials WHERE credential_archived_at IS NULL AND credential_client_id = $client_id"));
$num_credentials = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('network_id') AS num FROM networks WHERE network_archived_at IS NULL AND network_client_id = $client_id"));
$num_networks = $row['num'];
@@ -196,8 +203,8 @@ if (isset($_GET['client_id'])) {
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('quote_id') AS num FROM quotes WHERE quote_archived_at IS NULL AND quote_client_id = $client_id"));
$num_quotes = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_id') AS num FROM recurring WHERE recurring_archived_at IS NULL AND recurring_client_id = $client_id"));
$num_recurring = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_invoice_id') AS num FROM recurring_invoices WHERE recurring_invoice_archived_at IS NULL AND recurring_invoice_client_id = $client_id"));
$num_recurring_invoices = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('payment_id') AS num FROM payments, invoices WHERE payment_invoice_id = invoice_id AND invoice_client_id = $client_id"));
$num_payments = $row['num'];
@@ -208,8 +215,8 @@ if (isset($_GET['client_id'])) {
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('document_id') AS num FROM documents WHERE document_archived_at IS NULL AND document_client_id = $client_id"));
$num_documents = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('event_id') AS num FROM events WHERE event_client_id = $client_id"));
$num_events = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('event_id') AS num FROM calendar_events WHERE event_client_id = $client_id"));
$num_calendar_events = $row['num'];
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('trip_id') AS num FROM trips WHERE trip_archived_at IS NULL AND trip_client_id = $client_id"));
$num_trips = $row['num'];
@@ -241,13 +248,13 @@ if (isset($_GET['client_id'])) {
));
$num_domains_urgent = intval($row['num']);
// Count Certificates Expiring within 45 Days
// Count Certificates Expiring within 7 Days
$row = mysqli_fetch_assoc(mysqli_query(
$mysqli,
"SELECT COUNT('certificate_id') AS num FROM certificates
WHERE certificate_client_id = $client_id
AND certificate_expire IS NOT NULL
AND certificate_expire < CURRENT_DATE + INTERVAL 45 DAY
AND certificate_expire < CURRENT_DATE + INTERVAL 7 DAY
AND certificate_archived_at IS NULL"
));
$num_certificates_expiring = intval($row['num']);
@@ -260,7 +267,7 @@ if (isset($_GET['client_id'])) {
AND certificate_expire IS NOT NULL
AND (
certificate_expire < CURRENT_DATE
OR certificate_expire < CURRENT_DATE + INTERVAL 7 DAY
OR certificate_expire < CURRENT_DATE + INTERVAL 1 DAY
)
AND certificate_archived_at IS NULL"
));

View File

@@ -96,6 +96,13 @@
<p>Tickets by Client</p>
</a>
</li>
<li class="nav-item">
<a href="report_time_by_tech.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "report_time_by_tech.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-life-ring"></i>
<p>Time by Technician</p>
</a>
</li>
<?php } ?>
<?php if (lookupUserPermission("module_credential") >= 1) { ?>
<li class="nav-item">

View File

@@ -54,9 +54,11 @@ if (isset($_GET['invoice_id'])) {
$location_state = nullable_htmlentities($row['location_state']);
$location_zip = nullable_htmlentities($row['location_zip']);
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
$client_website = nullable_htmlentities($row['client_website']);
$client_currency_code = nullable_htmlentities($row['client_currency_code']);
$client_net_terms = intval($row['client_net_terms']);
@@ -77,7 +79,8 @@ if (isset($_GET['invoice_id'])) {
$company_city = nullable_htmlentities($row['company_city']);
$company_state = nullable_htmlentities($row['company_state']);
$company_zip = nullable_htmlentities($row['company_zip']);
$company_phone = formatPhoneNumber($row['company_phone']);
$company_phone_country_code = nullable_htmlentities($row['company_phone_country_code']);
$company_phone = nullable_htmlentities(formatPhoneNumber($row['company_phone'], $company_phone_country_code));
$company_email = nullable_htmlentities($row['company_email']);
$company_website = nullable_htmlentities($row['company_website']);
$company_logo = nullable_htmlentities($row['company_logo']);

View File

@@ -180,9 +180,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
</div>
<div class="col-sm-8">
<div class="btn-group float-right">
<div class="col-md-8">
<?php if ($client_url) { ?>
<div class="float-right">
<div class="btn-group float-right">
<?php if ($balance > 0) { ?>
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#addBulkPaymentModal"><i class="fa fa-credit-card mr-2"></i>Batch Payment</button>
<?php } ?>
</div>
</div>
<?php } ?>
</div>
</div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter">
@@ -380,7 +387,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
require_once "modals/invoice_add_modal.php";
if ($client_url) { require_once "modals/invoice_payment_add_bulk_modal.php"; }
require_once "modals/invoice_export_modal.php";
require_once "includes/footer.php";

View File

@@ -1,5 +1,5 @@
document.getElementById('rewordButton').addEventListener('click', function() {
var textInput = document.getElementById('textInput');
var textInput = this.closest('form').querySelector('textarea');
var ticketDescription = document.getElementById('ticketDescription');
var rewordButton = document.getElementById('rewordButton');
var undoButton = document.getElementById('undoButton');

View File

@@ -27,7 +27,6 @@ $(document).on('click', '[data-toggle="ajax-modal"]', function (e) {
method: 'GET',
data: { id: ajaxId },
dataType: 'json',
cache: false, // Prevent caching if necessary
success: function (response) {
if (response.error) {
alert(response.error);
@@ -42,7 +41,7 @@ $(document).on('click', '[data-toggle="ajax-modal"]', function (e) {
// Build the modal HTML using the returned title and content.
var modalHtml =
'<div class="modal fade text-sm" id="' + modalId + '" tabindex="-1">' +
'<div class="modal fade" id="' + modalId + '" tabindex="-1">' +
' <div class="modal-dialog modal-'+ modalSize +'">' +
' <div class="modal-content bg-dark">'
+ response.content +
@@ -51,7 +50,7 @@ $(document).on('click', '[data-toggle="ajax-modal"]', function (e) {
'</div>';
// Append the modal to the body and show it.
$('body').append(modalHtml);
$('.content-wrapper').append(modalHtml);
var $modal = $('#' + modalId);
$modal.modal('show');

612
js/app.js
View File

@@ -1,156 +1,157 @@
//Prevents resubmit on forms
if(window.history.replaceState){
window.history.replaceState(null, null, window.location.href);
}
$(document).ready(function() {
//Prevents resubmit on forms
if(window.history.replaceState){
window.history.replaceState(null, null, window.location.href);
}
// Slide alert up after 4 secs
$("#alert").fadeTo(5000, 500).slideUp(500, function(){
$("#alert").slideUp(500);
});
// Slide alert up after 4 secs
$("#alert").fadeTo(5000, 500).slideUp(500, function(){
$("#alert").slideUp(500);
});
// Initialize Select2 Elements
$('.select2').select2({
theme: 'bootstrap4',
});
// Initialize Select2 Elements
$('.select2').select2({
theme: 'bootstrap4',
});
// Initialize TinyMCE
tinymce.init({
selector: '.tinymce',
browser_spellcheck: true,
contextmenu: false,
resize: true,
min_height: 300,
max_height: 600,
promotion: false,
branding: false,
menubar: false,
statusbar: false,
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' ] },
{ name: 'table', items: [ 'table' ] },
{ name: 'extra', items: [ 'code', 'fullscreen' ] }
],
mobile: {
menubar: false,
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code codesample fullscreen autoresize',
license_key: 'gpl'
});
// Initialize TinyMCE
tinymce.init({
selector: '.tinymce',
browser_spellcheck: true,
contextmenu: false,
resize: true,
min_height: 300,
max_height: 600,
promotion: false,
branding: false,
menubar: false,
statusbar: false,
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' ] },
{ name: 'table', items: [ 'table' ] },
{ name: 'extra', items: [ 'code', 'fullscreen' ] }
],
mobile: {
menubar: false,
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code codesample fullscreen autoresize',
license_key: 'gpl'
});
// Initialize TinyMCE
tinymce.init({
selector: '.tinymceAI',
browser_spellcheck: true,
contextmenu: false,
resize: true,
min_height: 300,
max_height: 600,
promotion: false,
branding: false,
menubar: false,
statusbar: false,
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' ] },
{ name: 'table', items: [ 'table' ] },
{ name: 'extra', items: [ 'code', 'fullscreen' ] },
{ name: 'ai', items: [ 'reword', 'undo', 'redo' ] }
],
mobile: {
menubar: false,
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code codesample fullscreen autoresize',
license_key: 'gpl',
setup: function(editor) {
var rewordButtonApi;
// Initialize TinyMCE
tinymce.init({
selector: '.tinymceAI',
browser_spellcheck: true,
contextmenu: false,
resize: true,
min_height: 300,
max_height: 600,
promotion: false,
branding: false,
menubar: false,
statusbar: false,
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' ] },
{ name: 'table', items: [ 'table' ] },
{ name: 'extra', items: [ 'code', 'fullscreen' ] },
{ name: 'ai', items: [ 'reword', 'undo', 'redo' ] }
],
mobile: {
menubar: false,
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code codesample fullscreen autoresize',
license_key: 'gpl',
setup: function(editor) {
var rewordButtonApi;
editor.ui.registry.addButton('reword', {
icon: 'ai',
tooltip: 'Reword Text',
onAction: function() {
var content = editor.getContent();
editor.ui.registry.addButton('reword', {
icon: 'ai',
tooltip: 'Reword Text',
onAction: function() {
var content = editor.getContent();
// Disable the Reword button
rewordButtonApi.setEnabled(false);
// Disable the Reword button
rewordButtonApi.setEnabled(false);
// Show the progress indicator
editor.setProgressState(true);
// Show the progress indicator
editor.setProgressState(true);
fetch('post.php?ai_reword', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: content }),
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
editor.undoManager.transact(function() {
editor.setContent(data.rewordedText || 'Error: Could not reword the text.');
});
fetch('post.php?ai_reword', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: content }),
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
editor.undoManager.transact(function() {
editor.setContent(data.rewordedText || 'Error: Could not reword the text.');
});
// Hide the progress indicator
editor.setProgressState(false);
// Hide the progress indicator
editor.setProgressState(false);
// Re-enable the Reword button
rewordButtonApi.setEnabled(true);
// Re-enable the Reword button
rewordButtonApi.setEnabled(true);
// Optional: Show a success notification
editor.notificationManager.open({
text: 'Text reworded successfully!',
type: 'success',
timeout: 3000
});
})
.catch(error => {
console.error('Error:', error);
// Optional: Show a success notification
editor.notificationManager.open({
text: 'Text reworded successfully!',
type: 'success',
timeout: 3000
});
})
.catch(error => {
console.error('Error:', error);
// Hide the progress indicator
editor.setProgressState(false);
// Hide the progress indicator
editor.setProgressState(false);
// Re-enable the Reword button
rewordButtonApi.setEnabled(true);
// Re-enable the Reword button
rewordButtonApi.setEnabled(true);
// Show an error notification
editor.notificationManager.open({
text: 'An error occurred while rewording the text.',
type: 'error',
timeout: 5000
});
});
},
onSetup: function(buttonApi) {
rewordButtonApi = buttonApi;
return function() {
// Cleanup when the editor is destroyed (if necessary)
};
}
});
}
});
// Show an error notification
editor.notificationManager.open({
text: 'An error occurred while rewording the text.',
type: 'error',
timeout: 5000
});
});
},
onSetup: function(buttonApi) {
rewordButtonApi = buttonApi;
return function() {
// Cleanup when the editor is destroyed (if necessary)
};
}
});
}
});
tinymce.init({
selector: '.tinymceTicket',
tinymce.init({
selector: '.tinymceTicket', // Your selector
browser_spellcheck: true,
contextmenu: false,
resize: true,
@@ -165,20 +166,41 @@ tinymce.init({
{ name: 'formatting', items: [ 'bold', 'italic', 'forecolor'] },
{ name: 'link', items: [ 'link'] },
{ name: 'lists', items: [ 'bullist', 'numlist' ] },
{ name: 'indentation', items: [ 'outdent', 'indent' ] }
{ name: 'indentation', items: [ 'outdent', 'indent' ] },
{ name: 'custom', items: ['redactButton'] } // Add custom button to toolbar
],
mobile: {
menubar: false,
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
menubar: false,
plugins: 'autosave lists autolink',
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code fullscreen autoresize',
license_key: 'gpl'
});
license_key: 'gpl',
setup: function(editor) {
// Add custom toolbar button with Font Awesome icon
editor.ui.registry.addButton('redactButton', {
icon: 'permanent-pen',
tooltip: 'Redact', // Tooltip text for the button
onAction: function() {
var selectedText = editor.selection.getContent({ format: 'text' });
// Initialize TinyMCE AI
tinymce.init({
if (selectedText) {
// Replace the selected text with [REDACTED] in bold red
var newContent = '<span style="font-weight: bold; color: red;">[REDACTED]</span>';
// Replace selected content with the new content
editor.selection.setContent(newContent);
} else {
alert('Please select a word to redact');
}
}
});
}
});
// Initialize TinyMCE AI
tinymce.init({
selector: '.tinymceTicketAI',
browser_spellcheck: true,
contextmenu: false,
@@ -190,143 +212,217 @@ tinymce.init({
menubar: false,
statusbar: false,
toolbar: [
{ name: 'styles', items: [ 'styles' ] },
{ name: 'formatting', items: [ 'bold', 'italic', 'forecolor'] },
{ name: 'link', items: [ 'link'] },
{ name: 'lists', items: [ 'bullist', 'numlist' ] },
{ name: 'indentation', items: [ 'outdent', 'indent' ] },
{ name: 'ai', items: [ 'reword', 'undo', 'redo' ] }
{ name: 'styles', items: ['styles'] },
{ name: 'formatting', items: ['bold', 'italic', 'forecolor'] },
{ name: 'link', items: ['link'] },
{ name: 'lists', items: ['bullist', 'numlist'] },
{ name: 'indentation', items: ['outdent', 'indent'] },
{ name: 'ai', items: ['reword', 'undo', 'redo'] },
{ name: 'custom', items: ['redactButton'] } // Add custom redact button to toolbar
],
mobile: {
menubar: false,
toolbar: 'bold italic styles'
menubar: false,
toolbar: 'bold italic styles'
},
convert_urls: false,
plugins: 'link image lists table code codesample fullscreen autoresize',
license_key: 'gpl',
setup: function(editor) {
var rewordButtonApi;
var rewordButtonApi;
editor.ui.registry.addButton('reword', {
icon: 'ai',
tooltip: 'Reword Text',
onAction: function() {
var content = editor.getContent();
// Define the Reword button (AI-related button)
editor.ui.registry.addButton('reword', {
icon: 'ai', // Example icon for AI rewording
tooltip: 'Reword Text',
onAction: function() {
var content = editor.getContent();
// Disable the Reword button
rewordButtonApi.setEnabled(false);
// Disable the Reword button
rewordButtonApi.setEnabled(false);
// Show the progress indicator
editor.setProgressState(true);
// Show the progress indicator
editor.setProgressState(true);
fetch('post.php?ai_reword', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: content }),
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
editor.undoManager.transact(function() {
editor.setContent(data.rewordedText || 'Error: Could not reword the text.');
});
// Hide the progress indicator
editor.setProgressState(false);
// Re-enable the Reword button
rewordButtonApi.setEnabled(true);
// Optional: Show a success notification
editor.notificationManager.open({
text: 'Text reworded successfully!',
type: 'success',
timeout: 3000
});
})
.catch(error => {
console.error('Error:', error);
// Hide the progress indicator
editor.setProgressState(false);
// Re-enable the Reword button
rewordButtonApi.setEnabled(true);
// Show an error notification
editor.notificationManager.open({
text: 'An error occurred while rewording the text.',
type: 'error',
timeout: 5000
});
});
fetch('post.php?ai_reword', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
onSetup: function(buttonApi) {
rewordButtonApi = buttonApi;
return function() {
// Cleanup when the editor is destroyed (if necessary)
};
body: JSON.stringify({ text: content }),
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
});
return response.json();
})
.then(data => {
editor.undoManager.transact(function() {
editor.setContent(data.rewordedText || 'Error: Could not reword the text.');
});
// Hide the progress indicator
editor.setProgressState(false);
// Re-enable the Reword button
rewordButtonApi.setEnabled(true);
// Optional: Show a success notification
editor.notificationManager.open({
text: 'Text reworded successfully!',
type: 'success',
timeout: 3000
});
})
.catch(error => {
console.error('Error:', error);
// Hide the progress indicator
editor.setProgressState(false);
// Re-enable the Reword button
rewordButtonApi.setEnabled(true);
// Show an error notification
editor.notificationManager.open({
text: 'An error occurred while rewording the text.',
type: 'error',
timeout: 5000
});
});
},
onSetup: function(buttonApi) {
rewordButtonApi = buttonApi;
return function() {
// Cleanup when the editor is destroyed (if necessary)
};
}
});
// Add the Redact button
editor.ui.registry.addButton('redactButton', {
icon: 'permanent-pen',
tooltip: 'Redact Text', // Tooltip text for the button
onAction: function() {
var selectedText = editor.selection.getContent({ format: 'text' });
if (selectedText) {
// Replace the selected text with [REDACTED] in bold red
var newContent = '<span style="font-weight: bold; color: red;">[REDACTED]</span>';
// Replace selected content with the new content
editor.selection.setContent(newContent);
} else {
alert('Please select a word to redact');
}
}
});
}
});
});
// DateTime
$('.datetimepicker').datetimepicker({
});
tinymce.init({
selector: '.tinymceRedact', // Your selector
browser_spellcheck: true,
contextmenu: false,
resize: true,
min_height: 300,
max_height: 600,
promotion: false,
branding: false,
menubar: false,
statusbar: false,
toolbar: 'redactButton', // Only the redact button in the toolbar
mobile: {
menubar: false,
plugins: 'autosave lists autolink',
toolbar: 'redactButton' // Only the redact button on mobile
},
convert_urls: false,
plugins: 'link image lists table code fullscreen autoresize',
license_key: 'gpl',
setup: function(editor) {
// Disable all text input and backspace/delete actions
editor.on('keydown', function(e) {
// Prevent all key events (including backspace and delete)
e.preventDefault();
});
// Data Input Mask
$('[data-mask]').inputmask();
// Add custom toolbar button with Font Awesome icon and label
editor.ui.registry.addButton('redactButton', {
icon: 'permanent-pen',
tooltip: 'Redact', // Tooltip text for the button
text: 'REDACT', // Add the text next to the icon
onAction: function() {
var selectedText = editor.selection.getContent({ format: 'text' });
// ClipboardJS
if (selectedText) {
// Replace the selected text with [REDACTED] in bold red
var newContent = '<span style="font-weight: bold; color: red;">[REDACTED]</span>';
// Replace selected content with the new content
editor.selection.setContent(newContent);
} else {
alert('Please select a word to redact');
}
}
});
}
});
//Fix to allow Clipboard Copying within Bootstrap Modals
//For use in Bootstrap Modals or with any other library that changes the focus you'll want to set the focused element as the container value.
$.fn.modal.Constructor.prototype._enforceFocus = function() {};
// Tooltip
$('button').tooltip({
trigger: 'click',
placement: 'bottom'
});
// DateTime
$('.datetimepicker').datetimepicker({
});
function setTooltip(btn, message) {
$(btn).tooltip('hide')
.attr('data-original-title', message)
.tooltip('show');
}
// Data Input Mask
$('[data-mask]').inputmask();
function hideTooltip(btn) {
setTimeout(function() {
$(btn).tooltip('hide');
}, 1000);
}
// ClipboardJS
// Clipboard
//Fix to allow Clipboard Copying within Bootstrap Modals
//For use in Bootstrap Modals or with any other library that changes the focus you'll want to set the focused element as the container value.
$.fn.modal.Constructor.prototype._enforceFocus = function() {};
var clipboard = new ClipboardJS('.clipboardjs');
// Tooltip
clipboard.on('success', function(e) {
setTooltip(e.trigger, 'Copied!');
hideTooltip(e.trigger);
});
$('button').tooltip({
trigger: 'click',
placement: 'bottom'
});
clipboard.on('error', function(e) {
setTooltip(e.trigger, 'Failed!');
hideTooltip(e.trigger);
});
function setTooltip(btn, message) {
$(btn).tooltip('hide')
.attr('data-original-title', message)
.tooltip('show');
}
// Enable Popovers
$(function () {
$('[data-toggle="popover"]').popover()
});
function hideTooltip(btn) {
setTimeout(function() {
$(btn).tooltip('hide');
}, 1000);
}
// Data Tables
new DataTable('.dataTables');
// Clipboard
var clipboard = new ClipboardJS('.clipboardjs');
clipboard.on('success', function(e) {
setTooltip(e.trigger, 'Copied!');
hideTooltip(e.trigger);
});
clipboard.on('error', function(e) {
setTooltip(e.trigger, 'Failed!');
hideTooltip(e.trigger);
});
// Enable Popovers
$(function () {
$('[data-toggle="popover"]').popover()
});
// Data Tables
new DataTable('.dataTables');
});

View File

@@ -1,15 +1,15 @@
function showOTPViaLoginID(login_id) {
// Send a GET request to ajax.php as ajax.php?get_totp_token_via_id=true&login_id=ID
function showOTPViaCredentialID(credential_id) {
// Send a GET request to ajax.php as ajax.php?get_totp_token_via_id=true&credential_id=ID
jQuery.get(
"ajax.php", {
get_totp_token_via_id: 'true',
login_id: login_id
credential_id: credential_id
},
function(data) {
//If we get a response from post.php, parse it as JSON
const token = JSON.parse(data);
document.getElementById("otp_" + login_id).innerText = token
document.getElementById("otp_" + credential_id).innerText = token
}
);

View File

@@ -15,24 +15,29 @@ if (isset($_GET['client_id'])) {
$client_url = '';
}
// Tags Filter
if (isset($_GET['tags']) && is_array($_GET['tags']) && !empty($_GET['tags'])) {
// Sanitize each element of the status array
$sanitizedTags = array();
foreach ($_GET['tags'] as $tag) {
// Escape each status to prevent SQL injection
$sanitizedTags[] = "'" . intval($tag) . "'";
if (!$client_url) {
// Client Filter
if (isset($_GET['client']) & !empty($_GET['client'])) {
$client_query = 'AND (location_client_id = ' . intval($_GET['client']) . ')';
$client = intval($_GET['client']);
} else {
// Default - any
$client_query = '';
$client = '';
}
// Convert the sanitized tags into a comma-separated string
$sanitizedTagsString = implode(",", $sanitizedTags);
$tag_query = "AND tags.tag_id IN ($sanitizedTagsString)";
} else {
$tag_query = '';
}
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
// Tags Filter
if (isset($_GET['tags']) && is_array($_GET['tags']) && !empty($_GET['tags'])) {
// Sanitize each element of the tags array
$sanitizedTags = array_map('intval', $_GET['tags']);
// Convert the sanitized tags into a comma-separated string
$tag_filter = implode(",", $sanitizedTags);
$tag_query = "AND tags.tag_id IN ($tag_filter)";
} else {
$tag_filter = 0;
$tag_query = '';
}
$sql = mysqli_query(
$mysqli,
@@ -96,8 +101,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="col-md-3">
<div class="input-group">
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
<?php $sql_tags = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 2");
while ($row = mysqli_fetch_array($sql_tags)) {
<?php
$sql_tags_filter = mysqli_query($mysqli, "
SELECT tags.tag_id, tags.tag_name, tag_type
FROM tags
LEFT JOIN location_tags ON location_tags.tag_id = tags.tag_id
LEFT JOIN locations ON location_tags.location_id = locations.location_id
WHERE tag_type = 2
$client_query OR tags.tag_id IN ($tag_filter)
GROUP BY tags.tag_id
HAVING COUNT(location_tags.location_id) > 0 OR tags.tag_id IN ($tag_filter)
");
while ($row = mysqli_fetch_array($sql_tags_filter)) {
$tag_id = intval($row['tag_id']);
$tag_name = nullable_htmlentities($row['tag_name']); ?>
@@ -105,19 +120,40 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_tag_add.php"
data-ajax-id="3">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
<?php if ($client_url) { ?>
<div class="col-md-2"></div>
<?php } else { ?>
<div class="col-md-2">
<div class="input-group">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<div class="col-md-5">
<?php
$sql_clients_filter = mysqli_query($mysqli, "
SELECT DISTINCT client_id, client_name
FROM clients
JOIN locations ON location_client_id = client_id
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_name ASC
");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<option <?php if ($client == $client_id) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } ?>
<div class="col-md-3">
<div class="btn-group float-right">
<a href="?<?php echo $client_url; ?>archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
class="btn btn-<?php if($archived == 1){ echo "primary"; } else { echo "default"; } ?>">
@@ -213,13 +249,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$location_city = nullable_htmlentities($row['location_city']);
$location_state = nullable_htmlentities($row['location_state']);
$location_zip = nullable_htmlentities($row['location_zip']);
$location_phone = formatPhoneNumber($row['location_phone']);
$location_phone_country_code = nullable_htmlentities($row['location_phone_country_code']);
$location_phone = nullable_htmlentities(formatPhoneNumber($row['location_phone'], $location_phone_country_code));
if (empty($location_phone)) {
$location_phone_display = "-";
} else {
$location_phone_display = $location_phone;
}
$location_fax = formatPhoneNumber($row['location_fax']);
$location_fax_country_code = nullable_htmlentities($row['location_fax_country_code']);
$location_fax = nullable_htmlentities(formatPhoneNumber($row['location_fax'], $location_fax_country_code));
if ($location_fax) {
$location_fax_display = "<div class='text-secondary'>Fax: $location_fax</div>";
} else {

View File

@@ -11,7 +11,7 @@ if (!file_exists('config.php')) {
require_once "config.php";
// Set Timezone
require_once "inc_set_timezone.php";
require_once "includes/inc_set_timezone.php";
// Check if the application is configured for HTTPS-only access
if ($config_https_only && (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') && (!isset($_SERVER['HTTP_X_FORWARDED_PROTO']) || $_SERVER['HTTP_X_FORWARDED_PROTO'] !== 'https')) {
@@ -117,7 +117,7 @@ if (isset($_POST['login'])) {
$user_email = sanitizeInput($row['user_email']);
$token = sanitizeInput($row['user_token']);
$force_mfa = intval($row['user_config_force_mfa']);
$user_role = intval($row['user_role']);
$user_role_id = intval($row['user_role_id']);
$user_encryption_ciphertext = $row['user_specific_encryption_ciphertext'];
$user_extension_key = $row['user_extension_key'];
@@ -193,9 +193,6 @@ if (isset($_POST['login'])) {
// Session info
$_SESSION['user_id'] = $user_id;
$_SESSION['user_name'] = $user_name;
$_SESSION['user_type'] = 1;
$_SESSION['user_role'] = $user_role;
$_SESSION['csrf_token'] = randomString(156);
$_SESSION['logged'] = true;

View File

@@ -31,7 +31,7 @@
</div>
<div class="form-group">
<textarea class="form-control tinymceTicket<?php if($config_ai_enable) { echo "AI"; } ?>" id="detailsInput" name="details"></textarea>
<textarea class="form-control tinymceTicket<?php if($config_ai_enable) { echo "AI"; } ?>" name="details"></textarea>
</div>
<div class="form-group">

View File

@@ -33,7 +33,7 @@
</div>
<div class="form-group">
<textarea class="form-control tinymceTicket<?php if($config_ai_enable) { echo "AI"; } ?>" id="detailsInput" name="details"><?php echo $ticket_template_details; ?></textarea>
<textarea class="form-control tinymceTicket<?php if($config_ai_enable) { echo "AI"; } ?>" name="details"><?php echo $ticket_template_details; ?></textarea>
</div>
<div class="form-group">

View File

@@ -71,13 +71,13 @@
<select class="form-control select2" name="role" required>
<option value="">- Role -</option>
<?php
$sql_user_roles = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE user_role_archived_at IS NULL");
$sql_user_roles = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE role_archived_at IS NULL");
while ($row = mysqli_fetch_array($sql_user_roles)) {
$user_role_id = intval($row['user_role_id']);
$user_role_name = nullable_htmlentities($row['user_role_name']);
$role_id = intval($row['role_id']);
$role_name = nullable_htmlentities($row['role_name']);
?>
<option value="<?php echo $user_role_id; ?>"><?php echo $user_role_name; ?></option>
<option value="<?php echo $role_id; ?>"><?php echo $role_name; ?></option>
<?php } ?>
</select>
</div>

View File

@@ -15,22 +15,22 @@
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-details">Details</a>
<a class="nav-link active" data-toggle="pill" href="#pills-asset-details">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-network">Network</a>
<a class="nav-link" data-toggle="pill" href="#pills-asset-network">Network</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-assignment">Assignment</a>
<a class="nav-link" data-toggle="pill" href="#pills-asset-assignment">Assignment</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-purchase">Purchase</a>
<a class="nav-link" data-toggle="pill" href="#pills-asset-purchase">Purchase</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-login">Login</a>
<a class="nav-link" data-toggle="pill" href="#pills-asset-login">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-notes">Notes</a>
<a class="nav-link" data-toggle="pill" href="#pills-asset-notes">Notes</a>
</li>
</ul>
@@ -38,7 +38,7 @@
<div class="tab-content">
<div class="tab-pane fade show active" id="pills-details">
<div class="tab-pane fade show active" id="pills-asset-details">
<?php if ($client_url) { ?>
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
@@ -58,7 +58,7 @@
while ($row = mysqli_fetch_array($sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']); ?>
<option value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<option <?php if ($client_id == isset($_GET['client'])) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php } ?>
</select>
@@ -149,7 +149,7 @@
</div>
<div class="tab-pane fade" id="pills-network">
<div class="tab-pane fade" id="pills-asset-network">
<?php if ($client_url) { ?>
<div class="form-group">
<label>Network</label>
@@ -243,7 +243,7 @@
</div>
<div class="tab-pane fade" id="pills-assignment">
<div class="tab-pane fade" id="pills-asset-assignment">
<div class="form-group">
<label>Physical Location</label>
@@ -293,7 +293,12 @@
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
?>
<option value="<?php echo $contact_id; ?>"><?php echo $contact_name; ?></option>
<option
<?php if (isset($_GET['contact_id']) && $contact_id == intval($_GET['contact_id'])) {
echo "selected"; }
?>
value="<?php echo $contact_id; ?>"><?php echo $contact_name; ?>
</option>
<?php } ?>
@@ -319,7 +324,7 @@
</div>
<div class="tab-pane fade" id="pills-purchase">
<div class="tab-pane fade" id="pills-asset-purchase">
<?php if ($client_url) { ?>
<div class="form-group">
@@ -391,7 +396,7 @@
</div>
<div class="tab-pane fade" id="pills-login">
<div class="tab-pane fade" id="pills-asset-login">
<div class="form-group">
<label>Username</label>
@@ -415,7 +420,7 @@
</div>
<div class="tab-pane fade" id="pills-notes">
<div class="tab-pane fade" id="pills-asset-notes">
<div class="form-group">
<label>Upload Photo</label>

View File

@@ -82,9 +82,8 @@
$sql = mysqli_query(
$mysqli,
"SELECT users.user_id, user_name FROM users
LEFT JOIN user_settings on users.user_id = user_settings.user_id
WHERE user_role > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
"SELECT user_id, user_name FROM users
WHERE user_role_id > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
);
while ($row = mysqli_fetch_array($sql)) {
$user_id = intval($row['user_id']);

View File

@@ -21,7 +21,7 @@
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-ethernet"></i></span>
</div>
<input type="number" id="interface_start" class="form-control" name="interface_start" placeholder="e.g., 1" min="1" required>
<input type="number" id="interface_start" class="form-control" name="interface_start" placeholder="e.g., 1" min="0" required>
</div>
</div>

View File

@@ -16,23 +16,23 @@
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<select class="form-control select2" name="login_id">
<select class="form-control select2" name="credential_id">
<option value="">- Select a Credential -</option>
<?php
$sql_logins_select = mysqli_query($mysqli, "SELECT login_id, login_name FROM logins
WHERE login_client_id = $client_id
AND login_asset_id != $contact_id
AND login_asset_id = 0
AND login_archived_at IS NULL
ORDER BY login_name ASC"
$sql_credentials_select = mysqli_query($mysqli, "SELECT credential_id, credential_name FROM credentials
WHERE credential_client_id = $client_id
AND credential_asset_id != $contact_id
AND credential_asset_id = 0
AND credential_archived_at IS NULL
ORDER BY credential_name ASC"
);
while ($row = mysqli_fetch_array($sql_logins_select)) {
$login_id = intval($row['login_id']);
$login_name = nullable_htmlentities($row['login_name']);
while ($row = mysqli_fetch_array($sql_credentials_select)) {
$credential_id = intval($row['credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
?>
<option value="<?php echo $login_id ?>"><?php echo $login_name; ?></option>
<option value="<?php echo $credential_id ?>"><?php echo $credential_name; ?></option>
<?php
}
?>

View File

@@ -46,7 +46,7 @@
while ($row = mysqli_fetch_array($sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']); ?>
<option value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<option <?php if ($client_id == isset($_GET['client'])) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php } ?>
</select>

View File

@@ -116,7 +116,7 @@
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tags"></i></span>
</div>
<select class="form-control select2" name="tags[]" multiple>
<select class="form-control select2" name="tags[]" data-placeholder="- Select Tags -"multiple>
<?php
$sql_tags_select = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 1 ORDER BY tag_name ASC");
@@ -144,26 +144,6 @@
<div class="tab-pane fade" id="pills-location">
<div class="form-group">
<label>Location Phone</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="text" class="form-control" name="location_phone" placeholder="Location's Phone Number" maxlength="200">
</div>
</div>
<div class="form-group">
<label>Location Fax</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-fax"></i></span>
</div>
<input type="text" class="form-control" name="location_fax" placeholder="Location's Fax Number" maxlength="200">
</div>
</div>
<div class="form-group">
<label>Address</label>
<div class="input-group">
@@ -219,6 +199,42 @@
</div>
</div>
<label>Location Phone / <span class="text-secondary">Extension</span></label>
<div class="form-row">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="tel" class="form-control col-2" name="location_phone_country_code" value="+1" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="location_phone" placeholder="Phone Number" maxlength="200">
</div>
</div>
</div>
<div class="col-3">
<div class="form-group">
<input type="text" class="form-control" name="location_extension" placeholder="ext." maxlength="200">
</div>
</div>
</div>
<label>Location Fax</label>
<div class="form-row">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-fax"></i></span>
</div>
<input type="tel" class="form-control col-2" name="location_fax_country_code" value="+1" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="location_fax" placeholder="Fax Number">
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-contact">
@@ -243,31 +259,38 @@
</div>
</div>
<label>Contact Phone</label>
<label>Contact Phone / <span class="text-secondary">Extension</span></label>
<div class="form-row">
<div class="col-8">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="text" class="form-control" name="contact_phone" placeholder="Contact's Phone Number" maxlength="200">
<input type="tel" class="form-control col-2" name="contact_phone_country_code" value="+1" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="contact_phone" placeholder="Phone Number" maxlength="200">
</div>
</div>
</div>
<div class="col-4">
<input type="text" class="form-control" name="contact_extension" placeholder="Extension" maxlength="200">
<div class="col-3">
<div class="form-group">
<input type="text" class="form-control" name="contact_extension" placeholder="ext." maxlength="200">
</div>
</div>
</div>
<label>Contact Mobile</label>
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
<label>Mobile</label>
<div class="form-row">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
</div>
<input type="tel" class="form-control col-2" name="contact_mobile_country_code" value="+1" placeholder="Code" maxlength="4">
<input type="tel" class="form-control" name="contact_mobile" placeholder="Mobile Phone Number">
</div>
</div>
<input type="text" class="form-control" name="contact_mobile" placeholder="Contact's Mobile Number" maxlength="200">
</div>
</div>

View File

@@ -9,6 +9,12 @@
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php if (isset($_GET['contact_id'])) { ?>
<input type="hidden" name="contact" value="<?php echo intval($_GET['contact_id']); ?>">
<?php } ?>
<?php if (isset($_GET['asset_id'])) { ?>
<input type="hidden" name="asset" value="<?php echo intval($_GET['asset_id']); ?>">
<?php } ?>
<div class="modal-body bg-white">
<div class="form-group">
@@ -16,43 +22,18 @@
</div>
<div class="form-group">
<textarea class="form-control tinymce<?php if($config_ai_enable) { echo "AI"; } ?>" id="textInput" name="content"></textarea>
<textarea class="form-control tinymce<?php if($config_ai_enable) { echo "AI"; } ?>" name="content"></textarea>
</div>
<div class="form-group">
<label for="folderSelect">Select Folder</label>
<label>Select Folder</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-folder"></i></span>
</div>
<select class="form-control select2" name="folder" id="folderSelect">
<select class="form-control select2" name="folder">
<option value="0">/</option>
<?php
// Recursive function to display folder options
function display_folder_options($parent_folder_id, $client_id, $indent = 0) {
global $mysqli;
$sql_folders = mysqli_query($mysqli, "SELECT * FROM folders WHERE parent_folder = $parent_folder_id AND folder_location = 0 AND folder_client_id = $client_id ORDER BY folder_name ASC");
while ($row = mysqli_fetch_array($sql_folders)) {
$folder_id = intval($row['folder_id']);
$folder_name = nullable_htmlentities($row['folder_name']);
// Indentation for subfolders
$indentation = str_repeat('&nbsp;', $indent * 4);
// Check if this folder is selected
$selected = '';
if ((isset($_GET['folder_id']) && $_GET['folder_id'] == $folder_id) || (isset($_POST['folder']) && $_POST['folder'] == $folder_id)) {
$selected = 'selected';
}
echo "<option value=\"$folder_id\" $selected>$indentation$folder_name</option>";
// Recursively display subfolders
display_folder_options($folder_id, $client_id, $indent + 1);
}
}
// Start displaying folder options from the root (parent_folder = 0)
display_folder_options(0, $client_id);
?>
@@ -61,12 +42,12 @@
</div>
<div class="form-group">
<label for="descriptionInput">Description</label>
<label>Description</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-file"></i></span>
</div>
<input type="text" class="form-control" name="description" id="descriptionInput" placeholder="Short summary of the document">
<input type="text" class="form-control" name="description" placeholder="Short summary of the document">
</div>
</div>
</div>

View File

@@ -52,8 +52,8 @@
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="logins" name="export_logins" value="1">
<label for="logins" class="custom-control-label">
<input class="custom-control-input" type="checkbox" id="credentials" name="export_credentials" value="1">
<label for="credentials" class="custom-control-label">
<i class='fas fa-fw fa-key mr-2'></i>Credentials
</label>
</div>
@@ -101,9 +101,9 @@
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="scheduled_tickets" name="export_scheduled_tickets" value="1" checked>
<label for="scheduled_tickets" class="custom-control-label">
<i class='fas fa-fw fa-clock mr-2'></i>Scheduled Tickets
<input class="custom-control-input" type="checkbox" id="recurring_tickets" name="export_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>
@@ -128,8 +128,8 @@
<li class="list-group-item">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="recurring" name="export_recurring" value="1" checked>
<label for="recurring" class="custom-control-label">
<input class="custom-control-input" type="checkbox" id="recurring_invoices" name="export_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>

View File

@@ -9,9 +9,14 @@
</div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php if (isset($_GET['contact_id'])) { ?>
<input type="hidden" name="contact" value="<?php echo intval($_GET['contact_id']); ?>">
<?php } ?>
<?php if (isset($_GET['asset_id'])) { ?>
<input type="hidden" name="asset" value="<?php echo intval($_GET['asset_id']); ?>">
<?php } ?>
<div class="modal-body bg-white">
<div class="form-group">
<label>Description</label>
<div class="input-group">
@@ -31,31 +36,6 @@
<select class="form-control select2" name="folder_id">
<option value="0">/</option>
<?php
// Recursive function to display folder options
function display_folder_options($parent_folder_id, $client_id, $indent = 0) {
global $mysqli;
$sql_folders = mysqli_query($mysqli, "SELECT * FROM folders WHERE parent_folder = $parent_folder_id AND folder_location = 1 AND folder_client_id = $client_id ORDER BY folder_name ASC");
while ($row = mysqli_fetch_array($sql_folders)) {
$folder_id = intval($row['folder_id']);
$folder_name = nullable_htmlentities($row['folder_name']);
// Indentation for subfolders
$indentation = str_repeat('&nbsp;', $indent * 4);
// Check if this folder is selected
$selected = '';
if ((isset($_GET['folder_id']) && $_GET['folder_id'] == $folder_id) || (isset($_POST['folder']) && $_POST['folder'] == $folder_id)) {
$selected = 'selected';
}
echo "<option value=\"$folder_id\" $selected>$indentation$folder_name</option>";
// Recursively display subfolders
display_folder_options($folder_id, $client_id, $indent + 1);
}
}
// Start displaying folder options from the root (parent_folder = 0)
display_folder_options(0, $client_id);
?>

Some files were not shown because too many files have changed in this diff Show More