mirror of
https://github.com/itflow-org/itflow
synced 2026-03-10 07:44:50 +00:00
Compare commits
301 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
939b07422d | ||
|
|
88369d480a | ||
|
|
cf083e94e6 | ||
|
|
11e8f5acfc | ||
|
|
77b3a89eb2 | ||
|
|
f572f4265a | ||
|
|
0b66c8e1be | ||
|
|
a8328a3f56 | ||
|
|
8b42b17121 | ||
|
|
db418ce662 | ||
|
|
96fe566e08 | ||
|
|
a00f26d8a4 | ||
|
|
eeef63d1c3 | ||
|
|
0b88ea85ae | ||
|
|
c564118156 | ||
|
|
01a7dc2068 | ||
|
|
bb44ecec3f | ||
|
|
b7b24d7de6 | ||
|
|
dcca93e34f | ||
|
|
4124188505 | ||
|
|
eb5d59623b | ||
|
|
8631c06731 | ||
|
|
40eb40fd86 | ||
|
|
c486682a0e | ||
|
|
336da073f1 | ||
|
|
d2e187a239 | ||
|
|
f69de29353 | ||
|
|
61de8bc792 | ||
|
|
d31f19707b | ||
|
|
811312466f | ||
|
|
5ecfb3e962 | ||
|
|
77be5af4e5 | ||
|
|
c512a716d2 | ||
|
|
14f5630caf | ||
|
|
8532bdc172 | ||
|
|
9d74bf8e19 | ||
|
|
f75445b4d0 | ||
|
|
e04fa1b696 | ||
|
|
e07dfb5f67 | ||
|
|
3d1af05fc2 | ||
|
|
0e38925d74 | ||
|
|
c0f3343412 | ||
|
|
6a368840fa | ||
|
|
5361391b3b | ||
|
|
b80662bb24 | ||
|
|
4c272b6b8d | ||
|
|
96abdef3ad | ||
|
|
0b04bc79e9 | ||
|
|
cefbbdc3a8 | ||
|
|
83ffe05a99 | ||
|
|
b6f73083ef | ||
|
|
693736023e | ||
|
|
fed87c93ab | ||
|
|
f53b77b556 | ||
|
|
b858d82b0b | ||
|
|
ccb2af6d17 | ||
|
|
8d937ac8f5 | ||
|
|
2786fb65ed | ||
|
|
025532f579 | ||
|
|
5bd03be1ad | ||
|
|
40086f1ce0 | ||
|
|
be66ad9a4c | ||
|
|
0df5c01bb7 | ||
|
|
b85fa38b67 | ||
|
|
546246d7c5 | ||
|
|
d5536e78f4 | ||
|
|
908738b7ca | ||
|
|
797e02bffa | ||
|
|
d856685782 | ||
|
|
1400983d8c | ||
|
|
2a43c5d868 | ||
|
|
a67675c649 | ||
|
|
fc344ef636 | ||
|
|
2ffb2be083 | ||
|
|
069772f27d | ||
|
|
241ec50802 | ||
|
|
b943c9cd89 | ||
|
|
80625f8c3f | ||
|
|
58435d3460 | ||
|
|
7a7ac4a47f | ||
|
|
429dfa5ca4 | ||
|
|
e1f212d30d | ||
|
|
670450bcfb | ||
|
|
83e15e9e4a | ||
|
|
b309081d75 | ||
|
|
f1a7b35aa6 | ||
|
|
469c5ef06d | ||
|
|
07cbe561bd | ||
|
|
b69a70cfc3 | ||
|
|
923001928c | ||
|
|
75ed461c67 | ||
|
|
691aebce91 | ||
|
|
846947ff49 | ||
|
|
65e107d154 | ||
|
|
19b809b699 | ||
|
|
60fe02bb47 | ||
|
|
3e708059c6 | ||
|
|
424104bb66 | ||
|
|
62696b9ebe | ||
|
|
87403e8c2d | ||
|
|
7a5a607ff6 | ||
|
|
a195774726 | ||
|
|
8d0da7b55b | ||
|
|
58c315cd09 | ||
|
|
dd6c4602db | ||
|
|
d413e0c8ff | ||
|
|
b356658635 | ||
|
|
d92f0fc49b | ||
|
|
f206a28cf7 | ||
|
|
70cb0ac635 | ||
|
|
a0ece18876 | ||
|
|
4a22b03952 | ||
|
|
5ebf797c90 | ||
|
|
a20759f1f2 | ||
|
|
c273cab36e | ||
|
|
8306a04eda | ||
|
|
f078203136 | ||
|
|
15e89c3c4e | ||
|
|
595c4f1440 | ||
|
|
91a523dc23 | ||
|
|
8567c97c09 | ||
|
|
3621e99c61 | ||
|
|
d99b9cbe68 | ||
|
|
e319768fd3 | ||
|
|
c30ffcf096 | ||
|
|
7286248fef | ||
|
|
dc49f80cc3 | ||
|
|
1ae2da8054 | ||
|
|
090f4cb560 | ||
|
|
0914716b8e | ||
|
|
ab463c1773 | ||
|
|
36af4d11fc | ||
|
|
14d8dc6fa6 | ||
|
|
2032b48ad3 | ||
|
|
2af795f548 | ||
|
|
7b4edb2948 | ||
|
|
17a906fd03 | ||
|
|
af46a1fd96 | ||
|
|
393c0b8c11 | ||
|
|
e92f2f714d | ||
|
|
42606067c0 | ||
|
|
98bb65509d | ||
|
|
a2599e5d43 | ||
|
|
0390b1bc2a | ||
|
|
531f3ec741 | ||
|
|
127afdca0d | ||
|
|
c4df5bf988 | ||
|
|
30234e044d | ||
|
|
1e98ee8916 | ||
|
|
d5665c2577 | ||
|
|
762ec51a19 | ||
|
|
309ad724ec | ||
|
|
34397fe468 | ||
|
|
2f82647f5e | ||
|
|
7d7854424c | ||
|
|
eaeadbe933 | ||
|
|
cf3f0cee6c | ||
|
|
a5f7b7fa9c | ||
|
|
9f7c289e94 | ||
|
|
c2bba7a919 | ||
|
|
4bb37a7198 | ||
|
|
231694aabe | ||
|
|
2fb75e6d67 | ||
|
|
810af638a3 | ||
|
|
9223b8cfb1 | ||
|
|
b7df21a663 | ||
|
|
7d47ed4dbd | ||
|
|
65eaf92862 | ||
|
|
8a01bc0d7d | ||
|
|
1a8a3781dc | ||
|
|
eadfdc41c4 | ||
|
|
421abd4c5b | ||
|
|
ae1a0dcc73 | ||
|
|
63b8804e2d | ||
|
|
634afcc089 | ||
|
|
90f5c8ad57 | ||
|
|
12fd45c144 | ||
|
|
382258a27c | ||
|
|
b5fa8ab4de | ||
|
|
bbb0db2f4f | ||
|
|
5b89e3dbee | ||
|
|
07b29a7bdc | ||
|
|
3286343026 | ||
|
|
6a26b611fa | ||
|
|
218fd2dcdc | ||
|
|
4c85db5e49 | ||
|
|
85ae42190a | ||
|
|
df8a755462 | ||
|
|
53713a0318 | ||
|
|
61aa477cbf | ||
|
|
c2adb92d28 | ||
|
|
19b2b08eac | ||
|
|
504346256f | ||
|
|
34e92d2223 | ||
|
|
573953704c | ||
|
|
0b9f10985d | ||
|
|
8e3dd42a32 | ||
|
|
0647933df7 | ||
|
|
93f4da3962 | ||
|
|
f72351ea88 | ||
|
|
d3c4c8c846 | ||
|
|
cf047024a1 | ||
|
|
ad3ed68932 | ||
|
|
62b8ee9d30 | ||
|
|
eedd92c894 | ||
|
|
622d5e5a44 | ||
|
|
475d653979 | ||
|
|
19a6f8f422 | ||
|
|
e69d69760d | ||
|
|
06de349fac | ||
|
|
c3ec83f640 | ||
|
|
37c20e4e0d | ||
|
|
400ba5bb20 | ||
|
|
a1ea5214a9 | ||
|
|
aae633c4ac | ||
|
|
ec8d7a36a8 | ||
|
|
21dc26b06f | ||
|
|
6a8d2cf1d4 | ||
|
|
b803ba4c55 | ||
|
|
4378fc2719 | ||
|
|
244e1290b4 | ||
|
|
5a64bd3a32 | ||
|
|
cc0b2126ba | ||
|
|
97f92e508e | ||
|
|
09fbe4e4ad | ||
|
|
508af6a80f | ||
|
|
073f816dbd | ||
|
|
bf327afd19 | ||
|
|
8fb8ce319e | ||
|
|
eabfef22be | ||
|
|
06c31e0808 | ||
|
|
509fb5cfed | ||
|
|
f1aa66119a | ||
|
|
7150b1545a | ||
|
|
59bbbe4a8d | ||
|
|
f64641cfdd | ||
|
|
f1783a6110 | ||
|
|
c8c1155c9c | ||
|
|
338a08da6c | ||
|
|
15aed891f4 | ||
|
|
c1c54780cb | ||
|
|
e93704bbdb | ||
|
|
c0db914213 | ||
|
|
b78e31e518 | ||
|
|
2533f0ced1 | ||
|
|
c7f4e48a27 | ||
|
|
87c1a95b06 | ||
|
|
4efb39358a | ||
|
|
619b93a545 | ||
|
|
a0598997d7 | ||
|
|
d0b8095bba | ||
|
|
daab1bca3d | ||
|
|
a0a2fddd90 | ||
|
|
f61c30bd5a | ||
|
|
4921d1eb19 | ||
|
|
28c8b1a6da | ||
|
|
3f0a6df717 | ||
|
|
07c8398e0d | ||
|
|
82c7a64a25 | ||
|
|
164a6a5604 | ||
|
|
9b6ea851e7 | ||
|
|
3804e18e53 | ||
|
|
244a47efad | ||
|
|
89e59b2448 | ||
|
|
bf9c2f6de7 | ||
|
|
ff80a3db3f | ||
|
|
c7d00d7b0d | ||
|
|
1c6e74b08e | ||
|
|
f8d054f8aa | ||
|
|
e5dc50ec35 | ||
|
|
e0dfaf2d22 | ||
|
|
757a62c35b | ||
|
|
52a62fc23c | ||
|
|
44b70d7161 | ||
|
|
ad9e4b4fb4 | ||
|
|
4fdd5ae769 | ||
|
|
9f2b9e3b3e | ||
|
|
2c074e9dc4 | ||
|
|
0fad31d683 | ||
|
|
b154930a4c | ||
|
|
359b04e7d1 | ||
|
|
cc00e3bf75 | ||
|
|
0454685039 | ||
|
|
b5eb325c5e | ||
|
|
ed6276a3e4 | ||
|
|
5da1310e34 | ||
|
|
a69b09c9e6 | ||
|
|
8da3bb15e9 | ||
|
|
8488445bf4 | ||
|
|
546d21adac | ||
|
|
580f50b187 | ||
|
|
4744276f2a | ||
|
|
6106b8aebb | ||
|
|
dd2b203321 | ||
|
|
7994c9c7a8 | ||
|
|
ae59aa3326 | ||
|
|
0ab9a1c97d | ||
|
|
2908568e2a | ||
|
|
2b673a1b6c | ||
|
|
bece8abfe2 | ||
|
|
ac2b355399 |
212
CHANGELOG.md
212
CHANGELOG.md
@@ -2,6 +2,182 @@
|
||||
|
||||
This file documents all notable changes made to ITFlow.
|
||||
|
||||
## [25.05]
|
||||
|
||||
### Added / Changed
|
||||
- Expanded file upload allow-list to include .bat and .stk file types.
|
||||
- Added full backup/restore functionality. Backup downloads a zip that includes the SQL dump and uploads folder, setup now has option to restore from zip backup.
|
||||
- Migrated Asset and Contact Links to modals to resolve variable overlap issue.
|
||||
- Added Pagination to Notification Modal.
|
||||
- Removed 500 Records Per Page option.
|
||||
- Removed unused old DB checks in the top nav.
|
||||
- Clients can now use the portal to setup Stripe automatic payments themselves for recurring invoices
|
||||
- Automatic payments are now disabled for all recurring invoices if the saved payment method is removed
|
||||
- Added Card Details and Payment added to Client Stripe.
|
||||
- UI / UX updates to guest pay Make use of cards.
|
||||
- Don't show Checkbox columns when ticket is closed, compact ticket list now matches round pills for status and priority.
|
||||
- Ticket UI/UX update allow the ticket toolbar to be a little more mobile-friendly
|
||||
- UI / UX Updates to Expenses - Combine Category and Description into 1 column.
|
||||
- Country information is now displayed in Invoices, Quotes, Recurring Invoices, Clients, Locations, and the client top header.
|
||||
- Added country-based search filters in Locations and Clients sections.
|
||||
- Changed the settings name from Integrations to Identity Providers to make room for future iDPs (e.g. Google).
|
||||
- Bump FullCalendar from 6.1.15 to 6.1.17.
|
||||
- Bump DataTables from 2.2.2 to 2.3.1.
|
||||
- Bump TCPDF from 6.8.2 to 6.9.4.
|
||||
- Bump tinyMCE from 7.7.1 to 7.9.0.
|
||||
- Bump phpMailer from 6.9.2 to 6.10.0.
|
||||
- Bump stripe-php from 16.4.0 to 17.2.1.
|
||||
|
||||
|
||||
### Fixed
|
||||
- "None" option for SMTP encryption now functions correctly.
|
||||
- Debug table row counts now reflect actual counts instead of relying on SHOW TABLE STATUS.
|
||||
- Archived Categories now display properly.
|
||||
- Stripe saved payment methods are now limited to credit/debit cards only.
|
||||
|
||||
## [25.03.6]
|
||||
|
||||
### Fixed
|
||||
- Set default to date to 2035-12-31 as 9999-12-31 and 2999-12-31 broke certain browsers.
|
||||
- Update Client PDF Export, add header added company logo.
|
||||
- Present Larger clearer Warning about updates on update page.
|
||||
- Allow to search by project reference.
|
||||
|
||||
## [25.03.5]
|
||||
|
||||
### Fixed
|
||||
- Fixed the user listing issue when copying a trip.
|
||||
- Corrected the display of recurring invoice amounts on the dashboard.
|
||||
- Fixed the linking of entities with assets and contacts.
|
||||
- Resolved the issue with displaying the correct mobile country code in the contact listing.
|
||||
- Set the default date to `9999-12-31` to ensure future items (like invoices) are displayed by default.
|
||||
- Fixed the display issue where file folders were not showing properly during document creation.
|
||||
- Migrated from Dragula to SortableJS for a more modern, mobile-friendly solution.
|
||||
- Added Handlebars icons for drag-and-drop items.
|
||||
- Changed behavior to open Contact and Asset Details pages directly instead of using a modal.
|
||||
|
||||
## [25.03.4]
|
||||
|
||||
### Fixed
|
||||
- Ability to remove additional assets from the ticket details screen.
|
||||
- Fix the ability to remove assets from edit ticket not working when only 1 asset exists.
|
||||
- Fix Database Backup corruption.
|
||||
- Client Portal - show ticket number instead of ticket id in ticket listing.
|
||||
- Add Purchase Reference to copy asset.
|
||||
- Add Link to asset details from the global search.
|
||||
- Fix Bulk assign ticket only showing contacts instead of ITFlow users.
|
||||
|
||||
|
||||
## [25.03.3]
|
||||
|
||||
### Fixed
|
||||
- Fix adding ITFlow user.
|
||||
- Do not alert on inactive recurring invoices.
|
||||
- Fix ticket user assignment including bulk assignment.
|
||||
- Fix adding a location phone extension.
|
||||
- Do not default to +1 Country code, instead default to null.
|
||||
- Do not format numbers unless a country code is entered.
|
||||
- Fix editing network location.
|
||||
- Fix ticket redaction on client replies.
|
||||
- Remove more from user activity as it requires admin privledges.
|
||||
- Fix MFA Enforcement page.
|
||||
|
||||
## [25.03.2]
|
||||
|
||||
### Fixed
|
||||
- Revert DB.sql change
|
||||
|
||||
## [25.03.1]
|
||||
|
||||
### Fixed
|
||||
- Phone number missing in various sections.
|
||||
- Match Database.
|
||||
- Client Export Only display licenses users and assets from the selected client only.
|
||||
|
||||
## [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
|
||||
- Fixed notifications being reversed as dismissed notifications.
|
||||
|
||||
## [25.02.2]
|
||||
|
||||
### Fixed
|
||||
- Corrected some edit modals not showing notes correctly.
|
||||
- Bugfix: When exporting to CSV, the first asset wasn't being shown.
|
||||
- Fix broken create / edit credentials.
|
||||
- Fixed missing Notificatons link.
|
||||
- Fixed a few dead links.
|
||||
- Fixed Overdue count also counting Non-Billable Invoices.
|
||||
- Fix Edit Client Notes.
|
||||
|
||||
### Added / Changed
|
||||
- Implemented SSL certificate history tracking.
|
||||
- Added Inactive / Active Filter to Recurring Invoices.
|
||||
- Merged Dismissed notifications and notification in one.
|
||||
- Added Link Button to addd / edit Document WYSIWYG.
|
||||
- Added Physical location to the asset export / import.
|
||||
|
||||
## [25.02.1]
|
||||
### Fixed
|
||||
- Resolved broken links in the client overview, project and client listings, and rack details.
|
||||
@@ -24,33 +200,33 @@ This file documents all notable changes made to ITFlow.
|
||||
- Added a Vendor Quick Details Modal.
|
||||
- Enabled vendor linking and added a License Purchase Reference in the Software Licenses section.
|
||||
- Added download original, optimized and thumbnail option for images.
|
||||
- Added Paid status to the top corner of Invoice PDFs
|
||||
- Added Paid status to the top corner of Invoice PDFs.
|
||||
|
||||
## [25.02]
|
||||
### Fixed
|
||||
- Migrated several reports to the new permissions/roles system
|
||||
- Resolved issue with empty task box showing for closed/resolved tickets
|
||||
- Corrected ticket priority sorting
|
||||
- Cloned asset interfaces when transferring assets between clients
|
||||
- Migrated several reports to the new permissions/roles system.
|
||||
- Resolved issue with empty task box showing for closed/resolved tickets.
|
||||
- Corrected ticket priority sorting.
|
||||
- Cloned asset interfaces when transferring assets between clients.
|
||||
|
||||
### Added / Changed
|
||||
- Restored max number of records per page option back to 500 since we dont have repeating modals.
|
||||
- Bulk Categorize Tickets feature
|
||||
- Renamed "Interface port" to "Interface Description." "Interface Name" should now refer to port name and/or number
|
||||
- Changed "Transfer Asset to Client" from a single action to a bulk action
|
||||
- Updated Filter Footer UI to show "Showing x to x of x records" instead of just the total records
|
||||
- Bulk Categorize Tickets feature.
|
||||
- Renamed "Interface port" to "Interface Description." "Interface Name" should now refer to port name and/or number.
|
||||
- Changed "Transfer Asset to Client" from a single action to a bulk action.
|
||||
- Updated Filter Footer UI to show "Showing x to x of x records" instead of just the total records.
|
||||
- Added Client Overview section to view client assets, contacts, licenses, credentials, etc.
|
||||
- Introduced Quick Peek for asset details, contact information, and document viewing throughout the ITFlow App, all made possible by AJAX
|
||||
- Enabled Simple Drag-and-Drop Ordering for Invoices, Recurring Invoices, Quotes, Ticket Tasks, and Ticket Template Tasks
|
||||
- Added new Ticket View options: Kanban and Simple View
|
||||
- Migrated all repeating modals to the new AJAX modal function for faster loading times and quicker development
|
||||
- Allowed clients to upload PDF documents to accepted quotes
|
||||
- Client Portal now shows ticket category
|
||||
- Custom links can now be added to the Client Portal navbar
|
||||
- Introduced Quick Peek for asset details, contact information, and document viewing throughout the ITFlow App, all made possible by AJAX.
|
||||
- Enabled Simple Drag-and-Drop Ordering for Invoices, Recurring Invoices, Quotes, Ticket Tasks, and Ticket Template Tasks.
|
||||
- Added new Ticket View options: Kanban and Simple View.
|
||||
- Migrated all repeating modals to the new AJAX modal function for faster loading times and quicker development.
|
||||
- Allowed clients to upload PDF documents to accepted quotes.
|
||||
- Client Portal now shows ticket category.
|
||||
- Custom links can now be added to the Client Portal navbar.
|
||||
- Lots of little tweaks to UI, performance, bugs, etc.
|
||||
|
||||
### Breaking Changes
|
||||
- Cron scripts have officially been moved to the /scripts folder and are no longer in the root directory; they must be updated to function properly
|
||||
- Cron scripts have officially been moved to the /scripts folder and are no longer in the root directory; they must be updated to function properly.
|
||||
|
||||
## [25.01.3]
|
||||
### Fixed
|
||||
@@ -137,4 +313,4 @@ This file documents all notable changes made to ITFlow.
|
||||
## [24.12]
|
||||
|
||||
### Added / Changed
|
||||
- Introduced versioned releases for the first time!
|
||||
- Introduced versioned releases for the first time!
|
||||
|
||||
@@ -93,6 +93,7 @@ If you want to improve ITFlow, feel free to fork the repo and create a pull requ
|
||||
We’re incredibly grateful to the organizations and individuals who support the project - a big thank you to:
|
||||
- CompuMatter
|
||||
- F1 for HELP
|
||||
- JetBrains (PhpStorm)
|
||||
|
||||
## License
|
||||
ITFlow is distributed "as is" under the GPL License, WITHOUT WARRANTY OF ANY KIND. See [`LICENSE`](https://github.com/itflow-org/itflow/blob/master/LICENSE) for details.
|
||||
|
||||
@@ -12,10 +12,8 @@
|
||||
We operate a rolling release model. Any bug fixes will be released into latest version of ITFlow, so you must stay up-to-date.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| Beta | :x: |
|
||||
| 24.12 | :white_check_mark: |
|
||||
| 25.1 | :white_check_mark: (When released) |
|
||||
|---------| ------------------ |
|
||||
| 25.05 | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability via GitHub Security Advisories
|
||||
|
||||
|
||||
@@ -48,14 +48,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-history mr-2"></i>App Logs</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-4" autocomplete="off">
|
||||
<form autocomplete="off">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search app logs">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search app logs">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -75,7 +75,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<form class="mb-4" autocomplete="off">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search audit logs">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
@@ -85,7 +85,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="client" onchange="this.form.submit()">
|
||||
<option value="">- All Clients -</option>
|
||||
|
||||
@@ -105,7 +105,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="user" onchange="this.form.submit()">
|
||||
<option value="">- All Users -</option>
|
||||
|
||||
@@ -125,7 +125,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="type" onchange="this.form.submit()">
|
||||
<option value="">- All Types -</option>
|
||||
|
||||
@@ -144,7 +144,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="action" onchange="this.form.submit()">
|
||||
<option value="">- All Actions -</option>
|
||||
|
||||
@@ -198,7 +198,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-sm table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_created_at&order=<?php echo $disp; ?>">
|
||||
|
||||
@@ -8,7 +8,7 @@ require_once "includes/inc_all_admin.php";
|
||||
</div>
|
||||
<div class="card-body" style="text-align: center;">
|
||||
<div class="alert alert-secondary">If you are unable to back up the entire VM, you'll need to back up the files & database individually. There is no built-in restore. See the <a href="https://docs.itflow.org/backups" target="_blank">docs here</a>.</div>
|
||||
<a class="btn btn-primary btn-lg p-3" href="post.php?download_database&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-4x fa-download"></i><br><br>Download database</a>
|
||||
<a class="btn btn-primary btn-lg p-3" href="post.php?download_backup&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-4x fa-download"></i><br><br>Download Backup</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,12 +20,12 @@ require_once "includes/inc_all_admin.php";
|
||||
<div class="card-body">
|
||||
<form action="post.php" method="POST">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="input-group col-4">
|
||||
<div class="input-group-prepend">
|
||||
<input type="password" class="form-control" placeholder="Enter your account password" name="password" autocomplete="new-password" required>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="input-group col-sm-4">
|
||||
<input type="password" class="form-control" placeholder="Enter your account password" name="password" autocomplete="new-password" required>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary" type="submit" name="backup_master_key"><i class="fas fa-key"></i></button>
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit" name="backup_master_key"><i class="fas fa-fw fa-key mr-2"></i>Get Master Key</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -27,10 +27,6 @@ $sql = mysqli_query(
|
||||
);
|
||||
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
if (isset($_GET['archived'])) {
|
||||
$category = "Archived";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
@@ -98,7 +94,7 @@ if (isset($_GET['archived'])) {
|
||||
} else {
|
||||
echo 'btn-default';
|
||||
} ?>">Ticket</a>
|
||||
<a href="?archived=1"
|
||||
<a href="?<?php echo $url_query_strings_sort ?>&archived=1"
|
||||
class="btn <?php if (isset($_GET['archived'])) {
|
||||
echo 'btn-primary';
|
||||
} else {
|
||||
@@ -150,7 +146,7 @@ if (isset($_GET['archived'])) {
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php
|
||||
if ($category == "Archived") {
|
||||
if ($archived) {
|
||||
?>
|
||||
<a class="dropdown-item text-success confirm-link"
|
||||
href="post.php?unarchive_category=<?php echo $category_id; ?>">
|
||||
|
||||
400
admin_debug.php
400
admin_debug.php
@@ -296,7 +296,13 @@ if ($tablesResult) {
|
||||
|
||||
while ($table = $tablesResult->fetch_assoc()) {
|
||||
$tableName = $table['Name'];
|
||||
$tableRows = $table['Rows'];
|
||||
|
||||
// Accurate row count
|
||||
$countResult = $mysqli->query("SELECT COUNT(*) AS cnt FROM `$tableName`");
|
||||
$countRow = $countResult->fetch_assoc();
|
||||
$tableRows = $countRow['cnt'];
|
||||
$countResult->free();
|
||||
|
||||
$dataLength = $table['Data_length'];
|
||||
$indexLength = $table['Index_length'];
|
||||
$tableSize = ($dataLength + $indexLength) / (1024 * 1024); // Size in MB
|
||||
@@ -336,11 +342,6 @@ if ($tablesResult) {
|
||||
'name' => 'Total database size (MB)',
|
||||
'value' => round($totalSize, 2) . ' MB',
|
||||
];
|
||||
} else {
|
||||
$databaseStats[] = [
|
||||
'name' => 'Database connection error',
|
||||
'value' => $mysqli->error,
|
||||
];
|
||||
}
|
||||
|
||||
// Section: Database Structure Comparison
|
||||
@@ -518,24 +519,26 @@ $mysqli->close();
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<table class="table table-bordered mb-3">
|
||||
<tr>
|
||||
<th>ITFlow release version</th>
|
||||
<th><?php echo APP_VERSION; ?></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current DB Version</td>
|
||||
<td><?php echo CURRENT_DATABASE_VERSION; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Code Commit</td>
|
||||
<td><?php echo $commitHash; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Branch</td>
|
||||
<td><?php echo $gitBranch; ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered mb-3">
|
||||
<tr>
|
||||
<th>ITFlow release version</th>
|
||||
<th><?php echo APP_VERSION; ?></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current DB Version</td>
|
||||
<td><?php echo CURRENT_DATABASE_VERSION; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Code Commit</td>
|
||||
<td><?php echo $commitHash; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Branch</td>
|
||||
<td><?php echo $gitBranch; ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- System Information Table -->
|
||||
<h3>System Information</h3>
|
||||
@@ -552,200 +555,209 @@ $mysqli->close();
|
||||
|
||||
<!-- PHP Extensions and Configuration Table -->
|
||||
<h3 class="mt-3">PHP Extensions and Configuration</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<!-- PHP Extensions Section -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">PHP Extensions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($phpExtensions as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<!-- PHP Extensions Section -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">PHP Extensions</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<!-- PHP Configuration Section -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">PHP Configuration</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($phpConfig as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($phpExtensions as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<!-- PHP Configuration Section -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">PHP Configuration</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">Shell Commands</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($shellCommands as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($phpConfig as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">Shell Commands</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">SSL Checks</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($sslChecks as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($shellCommands as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">SSL Checks</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">Domain Checks</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($domainChecks as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($sslChecks as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">Domain Checks</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($domainChecks as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
|
||||
<!-- File Permissions Table -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">File Permissions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($filePermissions as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
<!-- File Permissions Table -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">File Permissions</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($filePermissions as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Database Structure Comparison Table -->
|
||||
<h3 class="mt-3">Database Structure Comparison</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php if (!empty($dbComparison)): ?>
|
||||
<?php foreach ($dbComparison as $issue): ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php if (!empty($dbComparison)): ?>
|
||||
<?php foreach ($dbComparison as $issue): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($issue['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($issue['status']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($issue['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($issue['status']); ?></td>
|
||||
<td colspan="3">No discrepancies found between the database and db.sql file.</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td colspan="3">No discrepancies found between the database and db.sql file.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Uploads Directory Stats Table -->
|
||||
<h3 class="mt-3">Uploads Directory Stats</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php foreach ($uploadsStats as $stat): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($stat['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php foreach ($uploadsStats as $stat): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($stat['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Database Stats Table -->
|
||||
<h3 class="mt-3">Database Stats</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php foreach ($databaseStats as $stat): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($stat['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php foreach ($databaseStats as $stat): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($stat['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Table Stats Table -->
|
||||
<h3 class="mt-3">Table Stats</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Table Name</th>
|
||||
<th>Fields / Rows</th>
|
||||
<th>Size (MB)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($tableDetails as $table): ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($table['name']); ?></td>
|
||||
<td><?= htmlspecialchars("Fields: {$table['fields']}, Rows: {$table['rows']}"); ?></td>
|
||||
<td><?= htmlspecialchars($table['size'] . ' MB'); ?></td>
|
||||
<th>Table Name</th>
|
||||
<th>Fields / Rows</th>
|
||||
<th>Size (MB)</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($tableDetails as $table): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($table['name']); ?></td>
|
||||
<td><?= htmlspecialchars("Fields: {$table['fields']}, Rows: {$table['rows']}"); ?></td>
|
||||
<td><?= htmlspecialchars($table['size'] . ' MB'); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,13 +4,29 @@ require_once "includes/inc_all_admin.php";
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-3">
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-plug mr-2"></i>Integration Settings</h3>
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-fingerprint mr-2"></i>Identity Providers</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<h4>Client Portal SSO via Microsoft Entra</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Identity Provider <small class='text-secondary'>(Currently only works with Microsft Entra)</small></label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-fingerprint"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" readonly>
|
||||
<option <?php if (empty($config_azure_client_id)) { echo "selected"; } ?>>Disabled</option>
|
||||
<option <?php if ($config_azure_client_id) { echo "selected"; } ?>>Microsoft Entra</option>
|
||||
<option>Google (WIP)</option>
|
||||
<option>Custom SSO (WIP)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>MS Entra OAuth App (Client) ID</label>
|
||||
<div class="input-group">
|
||||
@@ -33,11 +49,10 @@ require_once "includes/inc_all_admin.php";
|
||||
|
||||
<hr>
|
||||
|
||||
<button type="submit" name="edit_integrations_settings" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
||||
<button type="submit" name="edit_identity_provider" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
|
||||
@@ -50,17 +50,17 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<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 = "-";
|
||||
|
||||
@@ -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-md-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="+" 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";
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -295,7 +295,7 @@ require_once "includes/inc_all_admin.php";
|
||||
<option value="4"><?php echo nullable_htmlentities($config_ticket_from_name); ?> (<?php echo nullable_htmlentities($config_ticket_from_email); ?>)</option>
|
||||
<?php } ?>
|
||||
|
||||
|
||||
|
||||
</select>
|
||||
<input type="email" class="form-control " name="email_to" placeholder="Email address to send to">
|
||||
<div class="input-group-append">
|
||||
@@ -319,7 +319,7 @@ require_once "includes/inc_all_admin.php";
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<div class="input-group-append">
|
||||
<button type="submit" name="test_email_imap" class="btn btn-success"><i class="fas fa-fw fa-inbox mr-2"></i>Test</button>
|
||||
<button type="submit" name="test_email_imap" class="btn btn-success" disabled><i class="fas fa-fw fa-inbox mr-2"></i>Test (WIP)</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -18,158 +18,159 @@ require_once "includes/inc_all_admin.php";
|
||||
<label class="custom-control-label" for="enableCronSwitch">Enable Cron (recommended) <small>(several cron scripts must also be added to cron with correct schedules, <a href="https://docs.itflow.org/cron">docs</a>)</small></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Notification</th>
|
||||
<th>App Notify</th>
|
||||
<th>Tech Email Notify</th>
|
||||
<th>Client Email Notify</th>
|
||||
<th>Create Ticket</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th colspan=5>Expirations</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-globe mr-2"></i>Domain Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when a domain is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_enable_alert_domain_expire" id="customCheck1" <?php if ($config_enable_alert_domain_expire == 1) { echo "checked"; } ?> value="1">
|
||||
<label class="custom-control-label" for="customCheck1"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-lock mr-2"></i>Certificate Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when a certificate is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-desktop mr-2"></i>Asset Warranty Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when an asset is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan=5>Billing</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Reminders</div>
|
||||
<small class="text-muted">
|
||||
(This will automatically dispatch a reminder email for the invoice to the primary contact's email every 30 days following the invoice's due date.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_send_invoice_reminders" <?php if ($config_send_invoice_reminders == 1) { echo "checked"; } ?> value="1" id="sendInvoiceRemindersSwitch">
|
||||
<label class="custom-control-label" for="sendInvoiceRemindersSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-redo-alt mr-2"></i>Send Recurring Invoice</div>
|
||||
<small class="text-muted">
|
||||
(This will notify all primary and billing contacts of a client that a new invoice was generated from recurring invoices)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_recurring_auto_send_invoice" <?php if ($config_recurring_auto_send_invoice == 1) { echo "checked"; } ?> value="1" id="sendRecurringSwitch">
|
||||
<label class="custom-control-label" for="sendRecurringSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan=5>Operational</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-bell mr-2"></i>Send clients general notification emails</div>
|
||||
<small class="text-secondary">(Should clients receive automatic emails when tickets are raised/closed?)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_ticket_client_general_notifications" <?php if($config_ticket_client_general_notifications == 1){ echo "checked"; } ?> value="1" id="ticketNotificationSwitch">
|
||||
<label class="custom-control-label" for="ticketNotificationSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-link mr-2"></i>Shared Item View</div>
|
||||
<small class="text-secondary">(Notify when Shared items are viewed)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-clock mr-2"></i>Cron Execution</div>
|
||||
<small class="text-secondary">(Notify when the nightly cron job ran)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-download mr-2"></i>ITFlow Updates</div>
|
||||
<small class="text-secondary">(Notify when ITFlow has an update)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Notification</th>
|
||||
<th>App Notify</th>
|
||||
<th>Tech Email Notify</th>
|
||||
<th>Client Email Notify</th>
|
||||
<th>Create Ticket</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th colspan=5>Expirations</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-globe mr-2"></i>Domain Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when a domain is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_enable_alert_domain_expire" id="customCheck1" <?php if ($config_enable_alert_domain_expire == 1) { echo "checked"; } ?> value="1">
|
||||
<label class="custom-control-label" for="customCheck1"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-lock mr-2"></i>Certificate Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when a certificate is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-desktop mr-2"></i>Asset Warranty Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when an asset is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan=5>Billing</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Reminders</div>
|
||||
<small class="text-muted">
|
||||
(This will automatically dispatch a reminder email for the invoice to the primary contact's email every 30 days following the invoice's due date.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_send_invoice_reminders" <?php if ($config_send_invoice_reminders == 1) { echo "checked"; } ?> value="1" id="sendInvoiceRemindersSwitch">
|
||||
<label class="custom-control-label" for="sendInvoiceRemindersSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-redo-alt mr-2"></i>Send Recurring Invoice</div>
|
||||
<small class="text-muted">
|
||||
(This will notify all primary and billing contacts of a client that a new invoice was generated from recurring invoices)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_recurring_auto_send_invoice" <?php if ($config_recurring_auto_send_invoice == 1) { echo "checked"; } ?> value="1" id="sendRecurringSwitch">
|
||||
<label class="custom-control-label" for="sendRecurringSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan=5>Operational</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-bell mr-2"></i>Send clients general notification emails</div>
|
||||
<small class="text-secondary">(Should clients receive automatic emails when tickets are raised/closed?)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_ticket_client_general_notifications" <?php if($config_ticket_client_general_notifications == 1){ echo "checked"; } ?> value="1" id="ticketNotificationSwitch">
|
||||
<label class="custom-control-label" for="ticketNotificationSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-link mr-2"></i>Shared Item View</div>
|
||||
<small class="text-secondary">(Notify when Shared items are viewed)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-clock mr-2"></i>Cron Execution</div>
|
||||
<small class="text-secondary">(Notify when the nightly cron job ran)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-download mr-2"></i>ITFlow Updates</div>
|
||||
<small class="text-secondary">(Notify when ITFlow has an update)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
@@ -11,56 +11,63 @@ $stripe_clients_sql = mysqli_query($mysqli, "SELECT * FROM client_stripe LEFT JO
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<table class="table border border-dark">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>Stripe Customer ID</th>
|
||||
<th>Stripe Payment ID</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($stripe_clients_sql)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$stripe_id = nullable_htmlentities($row['stripe_id']);
|
||||
$stripe_pm = nullable_htmlentities($row['stripe_pm']);
|
||||
|
||||
?>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table border border-dark">
|
||||
<thead class="thead-dark text-nowrap">
|
||||
<tr>
|
||||
<td><?php echo "$client_name ($client_id)" ?></td>
|
||||
<td><?php echo $stripe_id; ?></td>
|
||||
<td><?php echo $stripe_pm ?></td>
|
||||
<td>
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-h"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php if (!empty($stripe_pm)) { ?>
|
||||
<a class="dropdown-item text-danger confirm-link" href="post.php?stripe_remove_pm&client_id=<?php echo $client_id ?>&pm=<?php echo $stripe_pm ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-credit-card mr-2"></i>Delete payment method
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<a data-toggle="tooltip" data-placement="left" title="May result in duplicate customer records in Stripe" class="dropdown-item text-danger confirm-link" href="post.php?stripe_reset_customer&client_id=<?php echo $client_id ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Reset Stripe
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<th>Client</th>
|
||||
<th>Stripe Customer ID</th>
|
||||
<th>Stripe Payment ID</th>
|
||||
<th>Payment Details</th>
|
||||
<th>Created</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php } ?>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($stripe_clients_sql)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$stripe_id = nullable_htmlentities($row['stripe_id']);
|
||||
$stripe_pm = nullable_htmlentities($row['stripe_pm']);
|
||||
$stripe_pm_details = nullable_htmlentities($row['stripe_pm_details']);
|
||||
$stripe_pm_created_at = nullable_htmlentities($row['stripe_pm_created_at']);
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo "$client_name ($client_id)"; ?></td>
|
||||
<td><?php echo $stripe_id; ?></td>
|
||||
<td><?php echo $stripe_pm; ?></td>
|
||||
<td><?php echo $stripe_pm_details; ?></td>
|
||||
<td><?php echo $stripe_pm_created_at; ?></td>
|
||||
<td>
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-h"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php if (!empty($stripe_pm)) { ?>
|
||||
<a class="dropdown-item text-danger confirm-link" href="post.php?stripe_remove_pm&client_id=<?php echo $client_id ?>&pm=<?php echo $stripe_pm ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-credit-card mr-2"></i>Delete payment method
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<a data-toggle="tooltip" data-placement="left" title="May result in duplicate customer records in Stripe" class="dropdown-item text-danger confirm-link" href="post.php?stripe_reset_customer&client_id=<?php echo $client_id ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Reset Stripe
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -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"; } ?>>
|
||||
|
||||
@@ -72,6 +72,31 @@ require_once "includes/inc_all_admin.php";
|
||||
<input type="email" class="form-control" name="config_ticket_new_ticket_notification_email" placeholder="Address to notify for new tickets, leave blank for none" value="<?php echo nullable_htmlentities($config_ticket_new_ticket_notification_email); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Tickets Default View</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
|
||||
</div>
|
||||
<select class="form-control" name="config_ticket_default_view">
|
||||
<option value=0 <?php if ($config_ticket_default_view == 0) { echo "selected"; } ?>>List</option>
|
||||
<option value=1 <?php if ($config_ticket_default_view == 1) { echo "selected"; } ?>>Compact</option>
|
||||
<option value=2 <?php if ($config_ticket_default_view == 2) { echo "selected"; } ?>>Kanban</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Kanban Settings</label>
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" name="config_ticket_ordering" <?php if ($config_ticket_ordering == 1) { echo "checked"; } ?> value="1" id="ticketOrderingSwitch">
|
||||
<label class="custom-control-label" for="ticketOrderingSwitch">Allow ticket ordering within its column<small class="text-secondary">(uncheked will result in ordering it by priority and id)</small></label>
|
||||
</div>
|
||||
<div class="custom-control custom-switch">
|
||||
<input type="checkbox" class="custom-control-input" name="config_ticket_moving_columns" <?php if ($config_ticket_moving_columns == 1) { echo "checked"; } ?> value="1" id="ticketMovingColumnsSwitch">
|
||||
<label class="custom-control-label" for="ticketMovingColumnsSwitch">Allow moving columns</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
// Default Column Sortby Filter
|
||||
$sort = "ticket_status_name";
|
||||
$sort = "ticket_status_order";
|
||||
$order = "ASC";
|
||||
|
||||
require_once "includes/inc_all_admin.php";
|
||||
@@ -79,7 +79,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
if ($ticket_status_active) {
|
||||
$ticket_status_display = "<div class='text-success text-bold'>Active</div>";
|
||||
} else {
|
||||
$ticket_status_display = "<div class='text-secondary'>Disabled</div>";
|
||||
$ticket_status_display = "<div class='text-secondary'>Inactive</div>";
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -97,7 +97,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<span class='badge badge-pill text-light p-2' style="background-color: <?php echo $ticket_status_color; ?>"><?php echo $ticket_status_name; ?></span>
|
||||
<td><?php echo $ticket_status_display; ?></td>
|
||||
<td>
|
||||
<?php if ( $ticket_status_id > 5 ) { ?>
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-h"></i>
|
||||
@@ -106,13 +105,14 @@ $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_custom_ticket_status_edit.php" data-ajax-id="<?php echo $ticket_status_id; ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_status=<?php echo $ticket_status_id; ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
<?php if (!$ticket_status_active) { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_status=<?php echo $ticket_status_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token']; ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ $sql_ticket_templates = mysqli_query($mysqli, "SELECT * FROM ticket_templates WH
|
||||
$row = mysqli_fetch_array($sql_ticket_templates);
|
||||
|
||||
$ticket_template_name = nullable_htmlentities($row['ticket_template_name']);
|
||||
$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
|
||||
//$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
|
||||
$ticket_template_subject = nullable_htmlentities($row['ticket_template_subject']);
|
||||
$ticket_template_details = $purifier->purify($row['ticket_template_details']);
|
||||
$ticket_template_created_at = nullable_htmlentities($row['ticket_template_created_at']);
|
||||
@@ -30,156 +30,135 @@ $ticket_template_updated_at = nullable_htmlentities($row['ticket_template_update
|
||||
$sql_task_templates = mysqli_query($mysqli, "SELECT * FROM task_templates WHERE task_template_ticket_template_id = $ticket_template_id ORDER BY task_template_order ASC, task_template_id ASC");
|
||||
|
||||
?>
|
||||
<link rel="stylesheet" href="plugins/dragula/dragula.min.css">
|
||||
|
||||
<ol class="breadcrumb d-print-none">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="clients.php">Home</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="admin_user.php">Admin</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="admin_ticket_template.php">Ticket Templates</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active"><i class="fas fa-life-ring mr-2"></i><?php echo $ticket_template_name; ?></li>
|
||||
</ol>
|
||||
<ol class="breadcrumb d-print-none">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="clients.php">Home</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="admin_user.php">Admin</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="admin_ticket_template.php">Ticket Templates</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active"><i class="fas fa-life-ring mr-2"></i><?php echo $ticket_template_name; ?></li>
|
||||
</ol>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<div class="row">
|
||||
<div class="col-9">
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title mt-2">
|
||||
<div class="media">
|
||||
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
|
||||
<div class="media-body">
|
||||
<h3 class="mb-0"><?php echo $ticket_template_name; ?></h3>
|
||||
<div><small class="text-secondary"><?php echo $ticket_template_description; ?></small></div>
|
||||
</div>
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title mt-2">
|
||||
<div class="media">
|
||||
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
|
||||
<div class="media-body">
|
||||
<h3 class="mb-0"><?php echo $ticket_template_name; ?></h3>
|
||||
<div><small class="text-secondary"><?php //echo $ticket_template_description; ?></small></div>
|
||||
</div>
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#editTicketTemplateModal">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<h5><?php echo $ticket_template_subject; ?></h5>
|
||||
<div class="card-body prettyContent">
|
||||
<?php echo $ticket_template_details; ?>
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#editTicketTemplateModal">
|
||||
<i class="fas fa-edit"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title"><i class="fa fa-fw fa-tasks mr-2"></i>Tasks</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-tasks"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="task_name" placeholder="Create a task" required>
|
||||
<div class="input-group-append">
|
||||
<button type="submit" name="add_ticket_template_task" class="btn btn-primary"><i class="fas fa-fw fa-check"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-striped table-sm">
|
||||
<?php
|
||||
while($row = mysqli_fetch_array($sql_task_templates)){
|
||||
$task_id = intval($row['task_template_id']);
|
||||
$task_name = nullable_htmlentities($row['task_template_name']);
|
||||
$task_completion_estimate = intval($row['task_template_completion_estimate']);
|
||||
$task_description = nullable_htmlentities($row['task_template_description']);
|
||||
?>
|
||||
<tr data-task-id="<?php echo $task_id; ?>">
|
||||
<td><i class="far fa-fw fa-square text-secondary"></i></td>
|
||||
<td>
|
||||
<a href="#" class="grab-cursor">
|
||||
<span class="text-secondary"><?php echo $task_completion_estimate; ?>m</span>
|
||||
<span class="text-dark"> - <?php echo $task_name; ?></span>
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<div class="float-right">
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-link text-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-ellipsis-v"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#"
|
||||
data-toggle = "ajax-modal"
|
||||
data-ajax-url = "ajax/ajax_ticket_template_task_edit.php"
|
||||
data-ajax-id = "<?php echo $task_id; ?>"
|
||||
>
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_task_template=<?php echo $task_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-trash-alt mr-2"></i>Delete
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
<h5><?php echo $ticket_template_subject; ?></h5>
|
||||
<div class="card-body prettyContent">
|
||||
<?php echo $ticket_template_details; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="js/pretty_content.js"></script>
|
||||
<script src="plugins/dragula/dragula.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var container = $('.table tbody')[0];
|
||||
<div class="col-3">
|
||||
|
||||
dragula([container])
|
||||
.on('drop', function (el, target, source, sibling) {
|
||||
// Handle the drop event to update the order in the database
|
||||
var rows = $(container).children();
|
||||
var positions = rows.map(function(index, row) {
|
||||
return {
|
||||
id: $(row).data('taskId'),
|
||||
order: index
|
||||
};
|
||||
}).get();
|
||||
|
||||
// Send the new order to the server
|
||||
$.ajax({
|
||||
url: 'ajax.php',
|
||||
method: 'POST',
|
||||
data: {
|
||||
update_task_templates_order: true, // Adjust the parameter name if needed
|
||||
ticket_template_id: <?php echo $ticket_template_id; ?>,
|
||||
positions: positions
|
||||
},
|
||||
success: function(data) {
|
||||
// Handle success
|
||||
},
|
||||
error: function(error) {
|
||||
console.error('Error updating order:', error);
|
||||
<div class="card card-dark">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title"><i class="fa fa-fw fa-tasks mr-2"></i>Tasks</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
|
||||
<div class="form-group">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control" name="task_name" placeholder="Create a task" required maxlength="200">
|
||||
<div class="input-group-append">
|
||||
<button type="submit" name="add_ticket_template_task" class="btn btn-primary"><i class="fas fa-fw fa-check"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-sm" id="tasks">
|
||||
<?php
|
||||
while($row = mysqli_fetch_array($sql_task_templates)){
|
||||
$task_id = intval($row['task_template_id']);
|
||||
$task_name = nullable_htmlentities($row['task_template_name']);
|
||||
$task_completion_estimate = intval($row['task_template_completion_estimate']);
|
||||
//$task_description = nullable_htmlentities($row['task_template_description']);
|
||||
?>
|
||||
<tr data-task-id="<?php echo $task_id; ?>">
|
||||
<td>
|
||||
<a href="#" class="drag-handle"><i class="fas fa-bars text-muted mr-2"></i></a>
|
||||
<span class="text-dark"><?php echo $task_name; ?></span>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<div class="float-right">
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-light text-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-v"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#"
|
||||
data-toggle = "ajax-modal"
|
||||
data-ajax-url = "ajax/ajax_ticket_template_task_edit.php"
|
||||
data-ajax-id = "<?php echo $task_id; ?>"
|
||||
>
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_task_template=<?php echo $task_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-trash-alt mr-2"></i>Delete
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="js/pretty_content.js"></script>
|
||||
|
||||
<script src="plugins/SortableJS/Sortable.min.js"></script>
|
||||
<script>
|
||||
new Sortable(document.querySelector('table#tasks tbody'), {
|
||||
handle: '.drag-handle',
|
||||
animation: 150,
|
||||
onEnd: function (evt) {
|
||||
const rows = document.querySelectorAll('table#tasks tbody tr');
|
||||
const positions = Array.from(rows).map((row, index) => ({
|
||||
id: row.dataset.taskId,
|
||||
order: index
|
||||
}));
|
||||
|
||||
$.post('ajax.php', {
|
||||
update_task_templates_order: true,
|
||||
ticket_template_id: <?php echo $ticket_template_id; ?>,
|
||||
positions: positions
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
@@ -32,8 +32,11 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
|
||||
<?php } ?>
|
||||
|
||||
<?php if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) { ?>
|
||||
<div class="alert alert-warning">
|
||||
<strong>Ensure you have a current <a href="https://docs.itflow.org/backups">app & database backup</a> before updating!</strong>
|
||||
<div class="alert alert-danger">
|
||||
<h1 class="font-weight-bold text-center">⚠️ DANGER ⚠️</h1>
|
||||
<h2 class="font-weight-bold text-center">Do NOT run updates without first taking a backup</h2>
|
||||
<p>VM Snapshots are highly recommended over other methods - see the <a href="https://docs.itflow.org/backups" class="alert-link" target="_blank">docs</a>. Review the <a href="https://github.com/itflow-org/itflow/blob/master/CHANGELOG.md" class="alert-link" target="_blank">changelog</a> for breaking changes that may require manual remediation.</p>
|
||||
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
|
||||
</div>
|
||||
<br>
|
||||
<a class="btn btn-dark btn-lg my-4" href="post.php?update_db"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update Database</h5></a>
|
||||
@@ -46,9 +49,17 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
|
||||
|
||||
<?php } else {
|
||||
if (!empty($git_log)) { ?>
|
||||
<div class="alert alert-danger">
|
||||
<h1 class="font-weight-bold text-center">⚠️ DANGER ⚠️</h1>
|
||||
<h2 class="font-weight-bold text-center">Do NOT run updates without first taking a backup</h2>
|
||||
<p>VM Snapshots are highly recommended over other methods - see the <a href="https://docs.itflow.org/backups" class="alert-link" target="_blank">docs</a>. Review the <a href="https://github.com/itflow-org/itflow/blob/master/CHANGELOG.md" class="alert-link" target="_blank">changelog</a> for breaking changes that may require manual remediation.</p>
|
||||
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
|
||||
</div>
|
||||
|
||||
<a class="btn btn-primary btn-lg my-4" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
|
||||
<a class="btn btn-danger btn-lg" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>
|
||||
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?no"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>TEST</h5></a>
|
||||
|
||||
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
|
||||
<a class="btn btn-danger btn-lg confirm-link" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>
|
||||
|
||||
<?php } else { ?>
|
||||
<p><strong>Application Release Version:<br><strong class="text-dark"><?php echo APP_VERSION; ?></strong></p>
|
||||
@@ -56,6 +67,17 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
|
||||
<p class="text-secondary">Code Commit:<br><strong class="text-dark"><?php echo $current_version; ?></strong></p>
|
||||
<p class="text-muted">You are up to date!<br>Everything is going to be alright</p>
|
||||
<i class="far fa-3x text-dark fa-smile-wink"></i><br>
|
||||
|
||||
<?php if (rand(1,10) == 1) { ?>
|
||||
<br>
|
||||
<div class="alert alert-info alert-dismissible fade show" role="alert">
|
||||
You're up to date, but when was the last time you checked your ITFlow backup works?
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php }
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
70
ajax.php
70
ajax.php
@@ -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);
|
||||
@@ -294,6 +294,7 @@ if (isset($_GET['get_active_clients'])) {
|
||||
$mysqli,
|
||||
"SELECT client_id, client_name FROM clients
|
||||
WHERE client_archived_at IS NULL
|
||||
$access_permission_query
|
||||
ORDER BY client_accessed_at DESC"
|
||||
);
|
||||
|
||||
@@ -315,7 +316,9 @@ if (isset($_GET['get_client_contacts'])) {
|
||||
$contact_sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT contact_id, contact_name, contact_primary, contact_important, contact_technical FROM contacts
|
||||
LEFT JOIN clients on contact_client_id = client_id
|
||||
WHERE contacts.contact_archived_at IS NULL AND contact_client_id = $client_id
|
||||
$access_permission_query
|
||||
ORDER BY contact_primary DESC, contact_technical DESC, contact_important DESC, contact_name"
|
||||
);
|
||||
|
||||
@@ -333,24 +336,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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -383,7 +386,7 @@ if (isset($_POST['update_kanban_status_position'])) {
|
||||
if (isset($_POST['update_kanban_ticket'])) {
|
||||
// Update ticket kanban order and status
|
||||
enforceUserPermission('module_support', 2);
|
||||
|
||||
|
||||
// all tickets on the column
|
||||
$positions = $_POST['positions'];
|
||||
|
||||
@@ -406,7 +409,7 @@ if (isset($_POST['update_kanban_ticket'])) {
|
||||
// if ticket was not moved, just uptdate the order on kanban
|
||||
mysqli_query($mysqli, "UPDATE tickets SET ticket_order = $kanban WHERE ticket_id = $ticket_id");
|
||||
customAction('ticket_update', $ticket_id);
|
||||
} else {
|
||||
} else {
|
||||
// If the ticket was moved from a resolved status to another status, we need to update ticket_resolved_at
|
||||
if ($oldStatus === $statuses['Resolved']) {
|
||||
mysqli_query($mysqli, "UPDATE tickets SET ticket_order = $kanban, ticket_status = $status, ticket_resolved_at = NULL WHERE ticket_id = $ticket_id");
|
||||
@@ -444,10 +447,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)";
|
||||
@@ -490,7 +493,7 @@ if (isset($_POST['update_kanban_ticket'])) {
|
||||
addToMailQueue($data);
|
||||
}
|
||||
//End Mail IF
|
||||
|
||||
|
||||
} else {
|
||||
// If the ticket was moved from any status to another status
|
||||
mysqli_query($mysqli, "UPDATE tickets SET ticket_order = $kanban, ticket_status = $status WHERE ticket_id = $ticket_id");
|
||||
@@ -512,7 +515,7 @@ if (isset($_POST['update_ticket_tasks_order'])) {
|
||||
$positions = $_POST['positions'];
|
||||
$ticket_id = intval($_POST['ticket_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
@@ -531,7 +534,7 @@ if (isset($_POST['update_task_templates_order'])) {
|
||||
$positions = $_POST['positions'];
|
||||
$ticket_template_id = intval($_POST['ticket_template_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
@@ -550,7 +553,7 @@ if (isset($_POST['update_quote_items_order'])) {
|
||||
$positions = $_POST['positions'];
|
||||
$quote_id = intval($_POST['quote_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
@@ -569,7 +572,7 @@ if (isset($_POST['update_invoice_items_order'])) {
|
||||
$positions = $_POST['positions'];
|
||||
$invoice_id = intval($_POST['invoice_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
@@ -586,17 +589,16 @@ if (isset($_POST['update_recurring_invoice_items_order'])) {
|
||||
enforceUserPermission('module_sales', 2);
|
||||
|
||||
$positions = $_POST['positions'];
|
||||
$recurring_id = intval($_POST['recurring_id']);
|
||||
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
mysqli_query($mysqli, "UPDATE invoice_items SET item_order = $order WHERE item_recurring_id = $recurring_id AND item_id = $id");
|
||||
mysqli_query($mysqli, "UPDATE invoice_items SET item_order = $order WHERE item_recurring_invoice_id = $recurring_invoice_id AND item_id = $id");
|
||||
}
|
||||
|
||||
// return a response
|
||||
echo json_encode(['status' => 'success']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
@@ -364,6 +364,16 @@ ob_start();
|
||||
</div>
|
||||
|
||||
<?php if ($asset_type !== 'Virtual Machine') { ?>
|
||||
<div class="form-group">
|
||||
<label>Purchase Reference</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-shopping-cart"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="purchase_reference" placeholder="eg. Invoice, PO Number" >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Purchase Date</label>
|
||||
<div class="input-group">
|
||||
|
||||
@@ -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>
|
||||
|
||||
69
ajax/ajax_asset_link_credential.php
Normal file
69
ajax/ajax_asset_link_credential.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_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-key mr-2"></i>Link Credential to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<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="credential_id">
|
||||
<option value="">- Select a Credential -</option>
|
||||
<?php
|
||||
$sql_credentials_select = mysqli_query($mysqli, "
|
||||
SELECT credentials.credential_id, credentials.credential_name
|
||||
FROM credentials
|
||||
LEFT JOIN assets ON credentials.credential_asset_id = assets.asset_id
|
||||
AND credentials.credential_asset_id = $asset_id
|
||||
WHERE credentials.credential_client_id = $client_id
|
||||
AND credentials.credential_asset_id = 0
|
||||
AND credentials.credential_archived_at IS NULL
|
||||
ORDER BY credentials.credential_name ASC
|
||||
");
|
||||
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 $credential_id ?>"><?php echo $credential_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
?>
|
||||
70
ajax/ajax_asset_link_document.php
Normal file
70
ajax/ajax_asset_link_document.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_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-folder mr-2"></i>Link Document to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<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="document_id">
|
||||
<option value="">- Select a Document -</option>
|
||||
<?php
|
||||
$sql_documents_select = mysqli_query($mysqli, "
|
||||
SELECT documents.document_id, documents.document_name
|
||||
FROM documents
|
||||
LEFT JOIN asset_documents
|
||||
ON documents.document_id = asset_documents.document_id
|
||||
AND asset_documents.asset_id = $asset_id
|
||||
WHERE documents.document_client_id = $client_id
|
||||
AND documents.document_archived_at IS NULL
|
||||
AND asset_documents.asset_id IS NULL
|
||||
ORDER BY documents.document_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_documents_select)) {
|
||||
$document_id = intval($row['document_id']);
|
||||
$document_name = nullable_htmlentities($row['document_name']);
|
||||
?>
|
||||
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
?>
|
||||
73
ajax/ajax_asset_link_file.php
Normal file
73
ajax/ajax_asset_link_file.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_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-paperclip mr-2"></i>Link File to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="file_id">
|
||||
<option value="">- Select a File -</option>
|
||||
<?php
|
||||
$sql_files_select = mysqli_query($mysqli, "
|
||||
SELECT files.file_id, files.file_name, folders.folder_name
|
||||
FROM files
|
||||
LEFT JOIN asset_files
|
||||
ON files.file_id = asset_files.file_id
|
||||
AND asset_files.asset_id = $asset_id
|
||||
LEFT JOIN folders
|
||||
ON folders.folder_id = files.file_folder_id
|
||||
WHERE files.file_client_id = $client_id
|
||||
AND asset_files.asset_id IS NULL
|
||||
ORDER BY folders.folder_name ASC, files.file_name ASC
|
||||
");
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_files_select)) {
|
||||
$file_id = intval($row['file_id']);
|
||||
$file_name = nullable_htmlentities($row['file_name']);
|
||||
$folder_name = nullable_htmlentities($row['folder_name']);
|
||||
?>
|
||||
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
?>
|
||||
68
ajax/ajax_asset_link_service.php
Normal file
68
ajax/ajax_asset_link_service.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_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-stream mr-2"></i>Link Service to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="service_id">
|
||||
<option value="">- Select a Service -</option>
|
||||
<?php
|
||||
$sql_services_select = mysqli_query($mysqli, "
|
||||
SELECT services.service_id, services.service_name
|
||||
FROM services
|
||||
LEFT JOIN service_assets
|
||||
ON services.service_id = service_assets.service_id
|
||||
AND service_assets.asset_id = $asset_id
|
||||
WHERE services.service_client_id = $client_id
|
||||
AND service_assets.asset_id IS NULL
|
||||
ORDER BY services.service_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_services_select)) {
|
||||
$service_id = intval($row['service_id']);
|
||||
$service_name = nullable_htmlentities($row['service_name']);
|
||||
?>
|
||||
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_service_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
73
ajax/ajax_asset_link_software.php
Normal file
73
ajax/ajax_asset_link_software.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_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-cube mr-2"></i>License Software to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="software_id">
|
||||
<option value="">- Select a Device Software License -</option>
|
||||
<?php
|
||||
$sql_software_select = mysqli_query($mysqli, "
|
||||
SELECT software.software_id, software.software_name
|
||||
FROM software
|
||||
LEFT JOIN software_assets
|
||||
ON software.software_id = software_assets.software_id
|
||||
AND software_assets.asset_id = $asset_id
|
||||
WHERE software.software_client_id = $client_id
|
||||
AND software.software_archived_at IS NULL
|
||||
AND software.software_license_type = 'Device'
|
||||
AND software_assets.asset_id IS NULL
|
||||
ORDER BY software.software_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_software_select)) {
|
||||
$software_id = intval($row['software_id']);
|
||||
$software_name = nullable_htmlentities($row['software_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_software_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
@@ -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']);
|
||||
|
||||
@@ -5,7 +5,7 @@ require_once '../includes/ajax_header.php';
|
||||
$certificate_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_id = $certificate_id LIMIT 1");
|
||||
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$certificate_name = nullable_htmlentities($row['certificate_name']);
|
||||
$certificate_description = nullable_htmlentities($row['certificate_description']);
|
||||
@@ -13,10 +13,13 @@ $certificate_domain = nullable_htmlentities($row['certificate_domain']);
|
||||
$certificate_domain_id = intval($row['certificate_domain_id']);
|
||||
$certificate_issued_by = nullable_htmlentities($row['certificate_issued_by']);
|
||||
$certificate_public_key = nullable_htmlentities($row['certificate_public_key']);
|
||||
$certificate_notes = nullable_htmlentities($row['certificate_notes']);
|
||||
$certificate_expire = nullable_htmlentities($row['certificate_expire']);
|
||||
$certificate_created_at = nullable_htmlentities($row['certificate_created_at']);
|
||||
$client_id = intval($row['certificate_client_id']);
|
||||
|
||||
$history_sql = mysqli_query($mysqli, "SELECT * FROM certificate_history WHERE certificate_history_certificate_id = $certificate_id");
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
?>
|
||||
@@ -42,6 +45,9 @@ ob_start();
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pillsEditNotes<?php echo $certificate_id; ?>">Notes</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pillsEditHistory<?php echo $certificate_id; ?>">History</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
@@ -78,7 +84,7 @@ ob_start();
|
||||
</div>
|
||||
<select class="form-control select2" name="domain_id">
|
||||
<option value="">- Select Domain -</option>
|
||||
<?php
|
||||
<?php
|
||||
$domains_sql = mysqli_query($mysqli, "SELECT domain_id, domain_name FROM domains WHERE domain_client_id = $client_id");
|
||||
while ($row = mysqli_fetch_array($domains_sql)) {
|
||||
$domain_id = intval($row['domain_id']);
|
||||
@@ -141,11 +147,40 @@ ob_start();
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pillsEditNotes<?php echo $certificate_id; ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" name="notes" rows="12" placeholder="Enter some notes"><?php echo $certificate_notes; ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pillsEditHistory<?php echo $certificate_id; ?>">
|
||||
<div class="table-responsive">
|
||||
<table class='table table-sm table-striped border table-hover'>
|
||||
<thead class='thead-dark'>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Field</th>
|
||||
<th>Before</th>
|
||||
<th>After</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($history_sql)) {
|
||||
$certificate_modified_at = nullable_htmlentities($row['certificate_history_modified_at']);
|
||||
$certificate_field = nullable_htmlentities($row['certificate_history_column']);
|
||||
$certificate_before_value = nullable_htmlentities($row['certificate_history_old_value']);
|
||||
$certificate_after_value = nullable_htmlentities($row['certificate_history_new_value']);
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo $certificate_modified_at; ?></td>
|
||||
<td><?php echo $certificate_field; ?></td>
|
||||
<td><?php echo $certificate_before_value; ?></td>
|
||||
<td><?php echo $certificate_after_value; ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -251,9 +251,7 @@ ob_start();
|
||||
<div class="tab-pane fade" id="pills-client-notes<?php echo $client_id; ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="10" placeholder="Enter some notes"
|
||||
name="notes"><?php echo $client_notes; ?>
|
||||
</textarea>
|
||||
<textarea class="form-control" rows="10" placeholder="Enter some notes" name="notes"><?php echo $client_notes; ?></textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -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_mobile'], $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"
|
||||
|
||||
@@ -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_mobile'], $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="+" 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="+" 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>
|
||||
|
||||
|
||||
67
ajax/ajax_contact_link_asset.php
Normal file
67
ajax/ajax_contact_link_asset.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_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-desktop mr-2"></i>Link Asset to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<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="asset_id">
|
||||
<option value="">- Select an Asset -</option>
|
||||
<?php
|
||||
$sql_assets_select = mysqli_query($mysqli, "
|
||||
SELECT asset_id, asset_name
|
||||
FROM assets
|
||||
WHERE asset_client_id = $client_id
|
||||
AND asset_contact_id = 0
|
||||
AND asset_archived_at IS NULL
|
||||
ORDER BY asset_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_assets_select)) {
|
||||
$asset_id = intval($row['asset_id']);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
?>
|
||||
<option value="<?php echo $asset_id ?>"><?php echo $asset_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
?>
|
||||
67
ajax/ajax_contact_link_credential.php
Normal file
67
ajax/ajax_contact_link_credential.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_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-key mr-2"></i>Link Credential to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<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="credential_id">
|
||||
<option value="">- Select a Credential -</option>
|
||||
<?php
|
||||
$sql_credentials_select = mysqli_query($mysqli, "
|
||||
SELECT credential_id, credential_name
|
||||
FROM credentials
|
||||
WHERE credential_client_id = $client_id
|
||||
AND credential_contact_id = 0
|
||||
AND credential_archived_at IS NULL
|
||||
ORDER BY credential_name ASC
|
||||
");
|
||||
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 $credential_id ?>"><?php echo $credential_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
?>
|
||||
70
ajax/ajax_contact_link_document.php
Normal file
70
ajax/ajax_contact_link_document.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_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-folder mr-2"></i>Link Document to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<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="document_id">
|
||||
<option value="">- Select a Document -</option>
|
||||
<?php
|
||||
$sql_documents_select = mysqli_query($mysqli, "
|
||||
SELECT documents.document_id, documents.document_name
|
||||
FROM documents
|
||||
LEFT JOIN contact_documents
|
||||
ON documents.document_id = contact_documents.document_id
|
||||
AND contact_documents.contact_id = $contact_id
|
||||
WHERE documents.document_client_id = $client_id
|
||||
AND documents.document_archived_at IS NULL
|
||||
AND contact_documents.contact_id IS NULL
|
||||
ORDER BY documents.document_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_documents_select)) {
|
||||
$document_id = intval($row['document_id']);
|
||||
$document_name = nullable_htmlentities($row['document_name']);
|
||||
?>
|
||||
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
?>
|
||||
72
ajax/ajax_contact_link_file.php
Normal file
72
ajax/ajax_contact_link_file.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_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-paperclip mr-2"></i>Link File to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="file_id">
|
||||
<option value="">- Select a File -</option>
|
||||
<?php
|
||||
$sql_files_select = mysqli_query($mysqli, "
|
||||
SELECT files.file_id, files.file_name, folders.folder_name
|
||||
FROM files
|
||||
LEFT JOIN contact_files
|
||||
ON files.file_id = contact_files.file_id
|
||||
AND contact_files.contact_id = $contact_id
|
||||
LEFT JOIN folders
|
||||
ON folders.folder_id = files.file_folder_id
|
||||
WHERE files.file_client_id = $client_id
|
||||
AND contact_files.contact_id IS NULL
|
||||
ORDER BY folders.folder_name ASC, files.file_name ASC
|
||||
");
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_files_select)) {
|
||||
$file_id = intval($row['file_id']);
|
||||
$file_name = nullable_htmlentities($row['file_name']);
|
||||
$folder_name = nullable_htmlentities($row['folder_name']);
|
||||
?>
|
||||
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
68
ajax/ajax_contact_link_service.php
Normal file
68
ajax/ajax_contact_link_service.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_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-stream mr-2"></i>Link Service to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="service_id">
|
||||
<option value="">- Select a Service -</option>
|
||||
<?php
|
||||
$sql_services_select = mysqli_query($mysqli, "
|
||||
SELECT services.service_id, services.service_name
|
||||
FROM services
|
||||
LEFT JOIN service_contacts
|
||||
ON services.service_id = service_contacts.service_id
|
||||
AND service_contacts.contact_id = $contact_id
|
||||
WHERE services.service_client_id = $client_id
|
||||
AND service_contacts.contact_id IS NULL
|
||||
ORDER BY services.service_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_services_select)) {
|
||||
$service_id = intval($row['service_id']);
|
||||
$service_name = nullable_htmlentities($row['service_name']);
|
||||
?>
|
||||
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_service_to_contact" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
71
ajax/ajax_contact_link_software.php
Normal file
71
ajax/ajax_contact_link_software.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_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-cube mr-2"></i>License Software to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="software_id">
|
||||
<option value="">- Select a User Software License -</option>
|
||||
<?php
|
||||
$sql_software_select = mysqli_query($mysqli, "
|
||||
SELECT software.software_id, software.software_name
|
||||
FROM software
|
||||
LEFT JOIN software_contacts
|
||||
ON software.software_id = software_contacts.software_id
|
||||
AND software_contacts.contact_id = $contact_id
|
||||
WHERE software.software_client_id = $client_id
|
||||
AND software.software_archived_at IS NULL
|
||||
AND software.software_license_type = 'User'
|
||||
AND software_contacts.contact_id IS NULL
|
||||
ORDER BY software.software_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_software_select)) {
|
||||
$software_id = intval($row['software_id']);
|
||||
$software_name = nullable_htmlentities($row['software_name']);
|
||||
?>
|
||||
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_software_to_contact" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</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";
|
||||
?>
|
||||
@@ -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>×</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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -8,6 +8,7 @@ $sql = mysqli_query($mysqli, "SELECT * FROM ticket_statuses WHERE ticket_status_
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$ticket_status_name = nullable_htmlentities($row['ticket_status_name']);
|
||||
$ticket_status_color = nullable_htmlentities($row['ticket_status_color']);
|
||||
$ticket_status_order = intval($row['ticket_status_order']);
|
||||
$ticket_status_active = intval($row['ticket_status_active']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
@@ -30,7 +31,7 @@ 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="name" maxlength="200" value="<?php echo $ticket_status_name; ?>" required>
|
||||
<input type="text" class="form-control" name="name" maxlength="200" value="<?php echo $ticket_status_name; ?>" required <?php if ($ticket_status_id <= 5) { echo "readonly"; } ?>>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,6 +45,16 @@ ob_start();
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Order</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-sort-numeric-down"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="order" placeholder="Leave blank for no order" value="<?php echo $ticket_status_order; ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Status <strong class="text-danger">*</strong></label>
|
||||
<div class="input-group">
|
||||
@@ -52,7 +63,7 @@ ob_start();
|
||||
</div>
|
||||
<select class="form-control select2" name="status" required>
|
||||
<option <?php if ($ticket_status_active == 1) { echo "selected"; } ?> value="1">Active</option>
|
||||
<option <?php if ($ticket_status_active == 0) { echo "selected"; } ?> value="0">Disabled</option>
|
||||
<option <?php if ($ticket_status_active == 0) { echo "selected"; } ?> value="0" <?php if ($ticket_status_id <= 5) { echo "disabled"; } ?>>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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="+" 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="+" 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>
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ ob_start();
|
||||
$location_id = intval($row['location_id']);
|
||||
$location_name = nullable_htmlentities($row['location_name']);
|
||||
?>
|
||||
<option value="<?php echo $location_id; ?>" <?php if ($location_id = $network_location_id) { echo "selected"; } ?>>
|
||||
<option value="<?php echo $location_id; ?>" <?php if ($location_id == $network_location_id) { echo "selected"; } ?>>
|
||||
<?php echo $location_name; ?>
|
||||
</option>
|
||||
<?php
|
||||
|
||||
@@ -25,54 +25,68 @@ ob_start();
|
||||
|
||||
<div class="modal-body bg-white">
|
||||
<?php if ($num_notifications) { ?>
|
||||
<table class="table table-sm table-hover table-borderless">
|
||||
|
||||
|
||||
<?php while ($row = mysqli_fetch_array($sql)) {
|
||||
<?php while ($row = mysqli_fetch_array($sql)) {
|
||||
|
||||
$notification_id = intval($row["notification_id"]);
|
||||
$notification_type = nullable_htmlentities($row["notification_type"]);
|
||||
$notification_details = nullable_htmlentities($row["notification"]);
|
||||
$notification_action = nullable_htmlentities(
|
||||
$row["notification_action"]
|
||||
);
|
||||
$notification_timestamp_formated = date(
|
||||
"M d g:ia",
|
||||
strtotime($row["notification_timestamp"])
|
||||
);
|
||||
$notification_client_id = intval($row["notification_client_id"]);
|
||||
if (empty($notification_action)) {
|
||||
$notification_action = "#";
|
||||
$notification_id = intval($row["notification_id"]);
|
||||
$notification_type = nullable_htmlentities($row["notification_type"]);
|
||||
$notification_details = nullable_htmlentities($row["notification"]);
|
||||
$notification_action = nullable_htmlentities(
|
||||
$row["notification_action"]
|
||||
);
|
||||
$notification_timestamp_formated = date(
|
||||
"M d g:ia",
|
||||
strtotime($row["notification_timestamp"])
|
||||
);
|
||||
$notification_client_id = intval($row["notification_client_id"]);
|
||||
if (empty($notification_action)) {
|
||||
$notification_action = "#";
|
||||
}
|
||||
?>
|
||||
|
||||
<tr class="notification-item">
|
||||
<th>
|
||||
<a class="text-dark" href="<?php echo $notification_action; ?>">
|
||||
<i class="fas fa-bullhorn mr-2"></i><?php echo $notification_type; ?>
|
||||
<small class="text-muted float-right">
|
||||
<?php echo $notification_timestamp_formated; ?>
|
||||
</small>
|
||||
<br>
|
||||
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
<a class="text-dark dropdown-item px-1" href="<?php echo $notification_action; ?>">
|
||||
<div>
|
||||
<span class="text-bold">
|
||||
<i class="fas fa-bullhorn mr-2"></i><?php echo $notification_type; ?>
|
||||
</span>
|
||||
<small class="text-muted float-right">
|
||||
<?php echo $notification_timestamp_formated; ?>
|
||||
</small>
|
||||
</table>
|
||||
<div class="text-center mt-2">
|
||||
<button id="prev-btn" class="btn btn-sm btn-outline-secondary mr-2"><i class="fas fa-caret-left"></i></button>
|
||||
<button id="next-btn" class="btn btn-sm btn-outline-secondary"><i class="fas fa-caret-right"></i></button>
|
||||
</div>
|
||||
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
|
||||
</a>
|
||||
|
||||
<?php
|
||||
}} else { ?>
|
||||
<div class="text-center text-secondary py-5">
|
||||
<?php } else { ?>
|
||||
<div class="text-center text-secondary pt-3">
|
||||
<i class='far fa-6x fa-bell-slash'></i>
|
||||
<h3 class="mt-3">No Notifications</h3>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="modal-footer bg-white justify-content-end">
|
||||
<div class="modal-footer bg-white">
|
||||
<?php if ($num_notifications) { ?>
|
||||
|
||||
<a href="post.php?dismiss_all_notifications&csrf_token=<?php echo $_SESSION[
|
||||
"csrf_token"
|
||||
]; ?>" class="btn btn-primary">
|
||||
<span class="text-white text-bold"><i class="fas fa-check mr-2"></i>Dismiss all</span>
|
||||
</a>
|
||||
<a href="notifications.php" class="btn btn-secondary">
|
||||
<span class="text-white">See all Notifications</span>
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<a href="notifications_dismissed.php" class="btn btn-dark">
|
||||
<a href="notifications.php?dismissed" class="btn btn-dark">
|
||||
<span class="text-white text-bold">See Dismissed Notifications</span>
|
||||
</a>
|
||||
<?php } ?>
|
||||
@@ -81,4 +95,41 @@ ob_start();
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
var perPage = 8;
|
||||
var $items = $(".notification-item");
|
||||
var totalItems = $items.length;
|
||||
var totalPages = Math.ceil(totalItems / perPage);
|
||||
var currentPage = 0;
|
||||
|
||||
function showPage(page) {
|
||||
$items.hide().slice(page * perPage, (page + 1) * perPage).show();
|
||||
$("#prev-btn").prop("disabled", page === 0);
|
||||
$("#next-btn").prop("disabled", page >= totalPages - 1);
|
||||
$("#page-indicator").text(`Page ${page + 1} of ${totalPages} (${totalItems} total)`);
|
||||
}
|
||||
|
||||
$("#prev-btn").on("click", function () {
|
||||
if (currentPage > 0) {
|
||||
currentPage--;
|
||||
showPage(currentPage);
|
||||
}
|
||||
});
|
||||
|
||||
$("#next-btn").on("click", function () {
|
||||
if (currentPage < totalPages - 1) {
|
||||
currentPage++;
|
||||
showPage(currentPage);
|
||||
}
|
||||
});
|
||||
|
||||
if (totalItems <= perPage) {
|
||||
$("#prev-btn, #next-btn, #page-indicator").hide();
|
||||
}
|
||||
|
||||
showPage(currentPage);
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once "../includes/ajax_footer.php";
|
||||
|
||||
@@ -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']);
|
||||
@@ -86,6 +85,25 @@ ob_start();
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Client</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-users"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="client_id">
|
||||
<option value="0">- No Client -</option>
|
||||
<?php
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$select_client_id = intval($row['client_id']);
|
||||
$select_client_name = nullable_htmlentities($row['client_name']);
|
||||
?>
|
||||
<option value="<?php echo $select_client_id; ?>" <?php if ($client_id == $select_client_id) { echo "selected"; } ?>><?php echo $select_client_name; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="edit_project" class="btn btn-primary text-bold">
|
||||
|
||||
@@ -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>×</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>
|
||||
|
||||
@@ -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>×</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>
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
|
||||
@@ -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>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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">
|
||||
|
||||
47
ajax/ajax_ticket_reply_redact.php
Normal file
47
ajax/ajax_ticket_reply_redact.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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 = 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>×</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; ?>">
|
||||
|
||||
<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="redact_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";
|
||||
@@ -10,7 +10,7 @@ $row = mysqli_fetch_array($sql);
|
||||
$task_template_name = nullable_htmlentities($row['task_template_name']);
|
||||
$task_template_order = intval($row['task_template_order']);
|
||||
$task_template_completion_estimate = intval($row['task_template_completion_estimate']);
|
||||
$task_template_description = nullable_htmlentities($row['task_template_description']);
|
||||
//$task_template_description = nullable_htmlentities($row['task_template_description']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
@@ -115,7 +115,7 @@ ob_start();
|
||||
|
||||
$sql_users = 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_archived_at IS NULL ORDER BY user_name ASC"
|
||||
WHERE user_role_id > 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_users)) {
|
||||
$user_id_select = intval($row['user_id']);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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="+" 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>
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 = '';
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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_source = 'API', 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) {
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
@@ -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 recurring_tickets.* 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(
|
||||
@@ -239,7 +244,7 @@ if (isset($_GET['asset_id'])) {
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fas fa-fw fa-edit"></i>
|
||||
</button>
|
||||
<h3 class="text-bold"><i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-3"></i><?php echo $asset_name; ?></h3>
|
||||
<h4 class="text-bold"><i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-3"></i><?php echo $asset_name; ?></h4>
|
||||
<?php if ($asset_photo) { ?>
|
||||
<img class="img-fluid img-circle p-3" alt="asset_photo" src="<?php echo "uploads/clients/$client_id/$asset_photo"; ?>">
|
||||
<?php } ?>
|
||||
@@ -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>
|
||||
@@ -365,34 +378,47 @@ if (isset($_GET['asset_id'])) {
|
||||
<div class="dropdown dropleft">
|
||||
<button type="button" class="btn btn-outline-primary" data-toggle="dropdown"><i class="fas fa-link mr-2"></i>Link</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkSoftwareModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_software.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-cube mr-2"></i>License
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkCredentialModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_credential.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-key mr-2"></i>Credential
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkServiceModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_service.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-stream mr-2"></i>Service
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkDocumentModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_document.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-folder mr-2"></i>Document
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkFileModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_file.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-paperclip mr-2"></i>File
|
||||
</a>
|
||||
|
||||
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fa fa-fw fa-ethernet mr-2"></i><?php echo $asset_name; ?> Network Interfaces</h3>
|
||||
<h3 class="card-title mt-2"><i class="fa fa-fw fa-ethernet mr-2"></i>Interfaces</h3>
|
||||
<div class="card-tools">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addAssetInterfaceModal">
|
||||
@@ -518,7 +544,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 +565,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 +623,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 +644,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 +712,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 +938,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 +971,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 +1028,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 +1055,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 +1191,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,11 +1202,8 @@ 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/asset_link_software_modal.php";
|
||||
require_once "modals/asset_link_credential_modal.php";
|
||||
require_once "modals/asset_link_service_modal.php";
|
||||
require_once "modals/asset_link_document_modal.php";
|
||||
require_once "modals/asset_link_file_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 "includes/footer.php";
|
||||
|
||||
58
assets.php
58
assets.php
@@ -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
|
||||
@@ -205,12 +205,20 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
</div>
|
||||
<?php if ($client_url) { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="location" onchange="this.form.submit()">
|
||||
<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']);
|
||||
@@ -225,12 +233,19 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<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 * 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"
|
||||
@@ -318,7 +338,7 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table border table-hover">
|
||||
<thead class="thead-light <?php if (!$num_rows[0]) { echo "d-none"; } ?>">
|
||||
<thead class="thead-light <?php if (!$num_rows[0]) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<td class="bg-light pr-0">
|
||||
<div class="form-check">
|
||||
@@ -499,7 +519,7 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
if ($contact_name) {
|
||||
$contact_name_display = "<a href='#'
|
||||
data-toggle='ajax-modal'
|
||||
data-modal-size='lg'
|
||||
data-modal-size='xl'
|
||||
data-ajax-url='ajax/ajax_contact_details.php'
|
||||
data-ajax-id='$asset_contact_id'>
|
||||
$contact_name $contact_archive_display
|
||||
@@ -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>
|
||||
@@ -530,11 +550,7 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-modal-size="lg"
|
||||
data-ajax-url="ajax/ajax_asset_details.php?<?php echo $client_url; ?>"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<a class="text-dark" href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>">
|
||||
<div class="media">
|
||||
<i class="fa fa-fw fa-2x fa-<?php echo $device_icon; ?> mr-3 mt-1"></i>
|
||||
<div class="media-body">
|
||||
@@ -664,14 +680,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 +695,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";
|
||||
|
||||
@@ -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>
|
||||
|
||||
16
calendar.php
16
calendar.php
@@ -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' },";
|
||||
}
|
||||
|
||||
@@ -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 = '';
|
||||
|
||||
@@ -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());
|
||||
@@ -56,6 +56,7 @@ header("X-Frame-Options: DENY"); // Legacy
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown1">
|
||||
<a class="dropdown-item" href="invoices.php">Invoices</a>
|
||||
<a class="dropdown-item" href="recurring_invoices.php">Recurring Invoices</a>
|
||||
<a class="dropdown-item" href="quotes.php">Quotes</a>
|
||||
<a class="dropdown-item" href="autopay.php">Auto Payment</a>
|
||||
</div>
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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']);
|
||||
|
||||
@@ -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']);
|
||||
|
||||
@@ -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'])) {
|
||||
@@ -38,7 +38,7 @@ if (isset($_POST['add_ticket'])) {
|
||||
$new_config_ticket_next_number = $config_ticket_next_number + 1;
|
||||
mysqli_query($mysqli, "UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
|
||||
|
||||
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_category = $category, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_billable = $config_ticket_default_billable, ticket_created_by = 0, ticket_contact_id = $session_contact_id, ticket_url_key = '$url_key', ticket_client_id = $session_client_id");
|
||||
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'Portal', ticket_category = $category, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_billable = $config_ticket_default_billable, ticket_created_by = $session_user_id, ticket_contact_id = $session_contact_id, ticket_url_key = '$url_key', ticket_client_id = $session_client_id");
|
||||
$ticket_id = mysqli_insert_id($mysqli);
|
||||
|
||||
// Notify agent DL of the new ticket, if populated with a valid email
|
||||
@@ -424,7 +424,7 @@ if (isset($_POST['edit_contact'])) {
|
||||
logAction("Contact", "Edit", "Client contact $session_contact_name edited contact $contact_name in the client portal", $session_client_id, $contact_id);
|
||||
|
||||
$_SESSION['alert_message'] = "Contact $contact_name updated";
|
||||
|
||||
|
||||
header('Location: contacts.php');
|
||||
|
||||
customAction('contact_update', $contact_id);
|
||||
@@ -597,14 +597,27 @@ if (isset($_GET['stripe_save_card'])) {
|
||||
|
||||
// Get some card/payment method details for the email/logging
|
||||
$payment_method_details = $stripe->paymentMethods->retrieve($payment_method);
|
||||
$card_info = sanitizeInput($payment_method_details->card->display_brand) . " " . sanitizeInput($payment_method_details->card->last4);
|
||||
$card_type = sanitizeInput($payment_method_details->card->brand);
|
||||
$last4 = sanitizeInput($payment_method_details->card->last4);
|
||||
$expiry_month = sanitizeInput($payment_method_details->card->exp_month);
|
||||
$expiry_year = sanitizeInput($payment_method_details->card->exp_year);
|
||||
|
||||
// Format the payment details string (Visa - 4324 | Exp 12/25)
|
||||
$stripe_pm_details = "$card_type - $last4 | Exp $expiry_month/$expiry_year";
|
||||
|
||||
// Save the formatted payment details into stripe_pm_details
|
||||
$update_query = "
|
||||
UPDATE client_stripe
|
||||
SET stripe_pm_details = '$stripe_pm_details'
|
||||
WHERE client_id = $session_client_id LIMIT 1";
|
||||
mysqli_query($mysqli, $update_query);
|
||||
|
||||
// Send email confirmation
|
||||
|
||||
// Company Details & Settings
|
||||
$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'];
|
||||
@@ -616,7 +629,7 @@ if (isset($_GET['stripe_save_card'])) {
|
||||
|
||||
if (!empty($config_smtp_host)) {
|
||||
$subject = "Payment method saved";
|
||||
$body = "Hello $session_contact_name,<br><br>We’re writing to confirm that your payment details have been securely stored with Stripe, our trusted payment processor.<br><br>By agreeing to save your payment information, you have authorized us to automatically bill your card ($card_info) for any future invoices. The payment details you’ve provided are securely stored with Stripe and will be used solely for invoices. We do not have access to your full card details.<br><br>You may update or remove your payment information at any time using the portal.<br><br>Thank you for your business!<br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
|
||||
$body = "Hello $session_contact_name,<br><br>We’re writing to confirm that your payment details have been securely stored with Stripe, our trusted payment processor.<br><br>By agreeing to save your payment information, you have authorized us to automatically bill your card ($stripe_pm_details) for any future invoices. The payment details you’ve provided are securely stored with Stripe and will be used solely for invoices. We do not have access to your full card details.<br><br>You may update or remove your payment information at any time using the portal.<br><br>Thank you for your business!<br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
|
||||
|
||||
$data = [
|
||||
[
|
||||
@@ -634,12 +647,11 @@ if (isset($_GET['stripe_save_card'])) {
|
||||
}
|
||||
|
||||
// Logging
|
||||
logAction("Stripe", "Update", "$session_contact_name saved payment method ($card_info) for future automatic payments (PM: $payment_method)", $session_client_id, $session_client_id);
|
||||
logAction("Stripe", "Update", "$session_contact_name saved payment method ($stripe_pm_details) for future automatic payments (PM: $payment_method)", $session_client_id, $session_client_id);
|
||||
|
||||
// Redirect
|
||||
$_SESSION['alert_message'] = "Payment method saved - thank you";
|
||||
header('Location: autopay.php');
|
||||
|
||||
}
|
||||
|
||||
if (isset($_GET['stripe_remove_pm'])) {
|
||||
@@ -676,11 +688,65 @@ if (isset($_GET['stripe_remove_pm'])) {
|
||||
}
|
||||
|
||||
// Remove payment method from ITFlow
|
||||
mysqli_query($mysqli, "UPDATE client_stripe SET stripe_pm = NULL WHERE client_id = $session_client_id LIMIT 1");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE client_stripe SET stripe_pm = NULL, stripe_pm_details = NULL WHERE client_id = $session_client_id LIMIT 1");
|
||||
|
||||
// Remove Auto Pay on recurring invoices that are stripe
|
||||
$sql_recurring_invoices = mysqli_query($mysqli, "SELECT recurring_invoice_id FROM recurring_invoices WHERE recurring_invoice_client_id = $session_client_id");
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_recurring_invoices)) {
|
||||
$recurring_invoice_id = intval($row['recurring_invoice_id']);
|
||||
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_method = 'Stripe' AND recurring_payment_recurring_invoice_id = $recurring_invoice_id");
|
||||
}
|
||||
|
||||
// Logging & Redirect
|
||||
logAction("Stripe", "Update", "$session_contact_name deleted saved Stripe payment method (PM: $payment_method)", $session_client_id, $session_client_id);
|
||||
|
||||
$_SESSION['alert_message'] = "Payment method removed";
|
||||
header('Location: autopay.php');
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['add_recurring_payment'])) {
|
||||
|
||||
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
|
||||
|
||||
// Get Recurring Info for logging and alerting
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
|
||||
$recurring_invoice_number = intval($row['recurring_invoice_number']);
|
||||
$recurring_invoice_amount = floatval($row['recurring_invoice_amount']);
|
||||
$recurring_invoice_currency_code = sanitizeInput($row['recurring_invoice_currency_code']);
|
||||
|
||||
mysqli_query($mysqli,"INSERT INTO recurring_payments SET recurring_payment_currency_code = '$recurring_invoice_currency_code', recurring_payment_account_id = $config_stripe_account, recurring_payment_method = 'Stripe', recurring_payment_recurring_invoice_id = $recurring_invoice_id");
|
||||
|
||||
// Get Payment ID for reference
|
||||
$recurring_payment_id = mysqli_insert_id($mysqli);
|
||||
|
||||
// Logging
|
||||
logAction("Recurring Invoice", "Auto Payment", "$session_name created Auto Pay for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number in the amount of " . numfmt_format_currency($currency_format, $recurring_invoice_amount, $recurring_invoice_currency_code), $session_client_id, $recurring_invoice_id);
|
||||
|
||||
|
||||
$_SESSION['alert_message'] = "Automatic Payment enabled for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number";
|
||||
|
||||
header("Location: " . $_SERVER["HTTP_REFERER"]);
|
||||
}
|
||||
|
||||
if (isset($_POST['delete_recurring_payment'])) {
|
||||
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
|
||||
|
||||
// Get the invoice total and details
|
||||
$sql = mysqli_query($mysqli,"SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
|
||||
$recurring_invoice_number = intval($row['recurring_invoice_number']);
|
||||
|
||||
mysqli_query($mysqli,"DELETE FROM recurring_payments WHERE recurring_payment_recurring_invoice_id = $recurring_invoice_id");
|
||||
|
||||
// Logging
|
||||
logAction("Recurring Invoice", "Auto Payment", "$session_name removed auto Pay from Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number", $session_client_id, $recurring_invoice_id);
|
||||
|
||||
$_SESSION['alert_message'] = "Automatic Payment disabled for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number";
|
||||
|
||||
header("Location: " . $_SERVER["HTTP_REFERER"]);
|
||||
|
||||
}
|
||||
|
||||
120
client/recurring_invoices.php
Normal file
120
client/recurring_invoices.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/*
|
||||
* Client Portal
|
||||
* Invoices for PTC
|
||||
*/
|
||||
|
||||
header("Content-Security-Policy: default-src 'self'");
|
||||
|
||||
require_once "includes/inc_all.php";
|
||||
|
||||
|
||||
if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) {
|
||||
header("Location: post.php?logout");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Get client's StripeID from database
|
||||
$stripe_client_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM client_stripe WHERE client_id = $session_client_id LIMIT 1"));
|
||||
if ($stripe_client_details) {
|
||||
$stripe_pm = sanitizeInput($stripe_client_details['stripe_pm']);
|
||||
}
|
||||
|
||||
$recurring_invoices_sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices
|
||||
LEFT JOIN recurring_payments ON recurring_payment_recurring_invoice_id = recurring_invoice_id
|
||||
WHERE recurring_invoice_client_id = $session_client_id
|
||||
AND recurring_invoice_status = 1
|
||||
ORDER BY recurring_invoice_next_date DESC"
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
<h3>Recurring Invoices</h3>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-10">
|
||||
|
||||
<table class="table tabled-bordered border border-dark">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Scope</th>
|
||||
<th>Amount</th>
|
||||
<th>Next Bill Date</th>
|
||||
<th>Frequency</th>
|
||||
<?php if ($config_stripe_enable) { ?>
|
||||
<th>Auto Pay</th>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($recurring_invoices_sql)) {
|
||||
$recurring_invoice_id = intval($row['recurring_invoice_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_status = nullable_htmlentities($row['recurring_invoice_status']);
|
||||
$recurring_invoice_next_date = nullable_htmlentities($row['recurring_invoice_next_date']);
|
||||
$recurring_invoice_frequency = nullable_htmlentities($row['recurring_invoice_frequency']);
|
||||
$recurring_invoice_amount = floatval($row['recurring_invoice_amount']);
|
||||
$recurring_payment_id = intval($row['recurring_payment_id']);
|
||||
$recurring_payment_recurring_invoice_id = intval($row['recurring_payment_recurring_invoice_id']);
|
||||
if ($config_stripe_enable) {
|
||||
if ($recurring_payment_recurring_invoice_id) {
|
||||
$auto_pay_display = "
|
||||
Yes
|
||||
<a href='post.php?delete_recurring_payment=$recurring_payment_id' title='Remove'>
|
||||
<i class='fas fa-fw fa-times-circle'></i>
|
||||
</a>
|
||||
";
|
||||
} else {
|
||||
$auto_pay_display = "
|
||||
<a href='#' data-toggle='modal' data-target='#addRecurringPaymentModal$recurring_invoice_id'>
|
||||
Create
|
||||
</a>
|
||||
";
|
||||
//require "recurring_payment_add_modal.php";
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($recurring_invoice_scope)) {
|
||||
$recurring_invoice_scope_display = "-";
|
||||
} else {
|
||||
$recurring_invoice_scope_display = $recurring_invoice_scope;
|
||||
}
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $recurring_invoice_scope_display; ?></td>
|
||||
<td><?php echo numfmt_format_currency($currency_format, $recurring_invoice_amount, $session_company_currency); ?></td>
|
||||
<td><?php echo $recurring_invoice_next_date; ?></td>
|
||||
<td><?php echo ucwords($recurring_invoice_frequency); ?>ly</td>
|
||||
<?php if ($config_stripe_enable) { ?>
|
||||
<td>
|
||||
<?php if ($stripe_pm) { ?>
|
||||
<form class="form" action="post.php" method="post">
|
||||
<input type="hidden" name="recurring_invoice_id" value="<?php echo $recurring_invoice_id; ?>">
|
||||
<?php if ($recurring_payment_recurring_invoice_id) { ?>
|
||||
<button type="submit" name="delete_recurring_payment" class="btn btn-outline-dark"><i class="fas fa-times mr-2"></i>Disable</button>
|
||||
<?php } else { ?>
|
||||
<button type="submit" name="add_recurring_payment" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Enable</button>
|
||||
<?php } ?>
|
||||
</form>
|
||||
<?php } else { ?>
|
||||
<a href="autopay.php">Add Card Details First</a>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "includes/footer.php";
|
||||
@@ -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>
|
||||
|
||||
@@ -62,7 +62,7 @@ $all_tickets = mysqli_query($mysqli, "SELECT ticket_id, ticket_prefix, ticket_nu
|
||||
$ticket_contact_name = nullable_htmlentities($row['contact_name']);
|
||||
|
||||
echo "<tr>";
|
||||
echo "<td> <a href='ticket.php?id=$ticket_id'> $ticket_prefix$ticket_id</a></td>";
|
||||
echo "<td> <a href='ticket.php?id=$ticket_id'> $ticket_prefix$ticket_number</a></td>";
|
||||
echo "<td> <a href='ticket.php?id=$ticket_id'> $ticket_subject</a></td>";
|
||||
echo "<td>$ticket_contact_name</td>";
|
||||
echo "<td>$ticket_status</td>";
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -9,9 +9,6 @@ require_once "includes/inc_all_client.php";
|
||||
// Perms
|
||||
enforceUserPermission('module_support');
|
||||
|
||||
// Rebuild URL
|
||||
$url_query_strings_sort = http_build_query($get_copy);
|
||||
|
||||
$sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT SQL_CALC_FOUND_ROWS * FROM racks
|
||||
@@ -323,7 +320,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
} else {
|
||||
// No device in this row
|
||||
?>
|
||||
<td class="text-center">No device</td>
|
||||
<td class="text-center text-secondary">--</td>
|
||||
<td></td>
|
||||
<?php
|
||||
}
|
||||
|
||||
62
clients.php
62
clients.php
@@ -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,10 +59,10 @@ $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%'
|
||||
OR location_city LIKE '%$q%' OR location_state LIKE '%$q%' OR location_zip LIKE '%$q%' OR location_country LIKE '%$q%'
|
||||
OR tag_name LIKE '%$q%' OR client_tax_id_number LIKE '%$q%')
|
||||
AND client_$archive_query
|
||||
AND DATE(client_created_at) BETWEEN '$dtf' AND '$dtt'
|
||||
@@ -115,7 +111,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<input type="hidden" name="archived" value="<?php echo $archived; ?>">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-sm-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search <?php if($leads_filter == 0){ echo "clients"; } else { echo "leads"; } ?>" autofocus>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
@@ -130,7 +126,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<a href="?leads=1" class="btn btn-<?php if ($leads_filter == 1){ echo "primary"; } else { echo "default"; } ?>"><i class="fa fa-fw fa-bullhorn mr-2"></i>Leads</a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group mr-2">
|
||||
<div class="btn-group">
|
||||
<a href="?<?php echo $url_query_strings_sort ?>&archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
|
||||
class="btn btn-<?php if ($archived == 1) { echo "primary"; } else { echo "default"; } ?>">
|
||||
<i class="fa fa-fw fa-archive mr-2"></i>Archived
|
||||
@@ -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">
|
||||
@@ -254,7 +248,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-hover table-borderless">
|
||||
<thead class="<?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="<?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
|
||||
@@ -292,14 +286,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
if (empty($location_address) && empty($location_city) && empty($location_state) && empty($location_zip)) {
|
||||
$location_address_display = "-";
|
||||
} else {
|
||||
$location_address_display = "$location_address<br>$location_city $location_state $location_zip";
|
||||
$location_address_display = "<i class='fa fa-fw fa-map-marker-alt text-secondary mr-2'></i>$location_address<br><i class='fa fa-fw mr-2'></i>$location_city $location_state $location_zip<br><i class='fa fa-fw mr-2'></i><small>$location_country</small>";
|
||||
}
|
||||
$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";
|
||||
|
||||
|
||||
@@ -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_mobile'], $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"
|
||||
@@ -276,31 +294,47 @@ if (isset($_GET['contact_id'])) {
|
||||
<div class="dropdown dropleft">
|
||||
<button type="button" class="btn btn-outline-primary" data-toggle="dropdown"><i class="fas fa-link mr-2"></i>Link</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkAssetModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_asset.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-desktop mr-2"></i>Asset
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkSoftwareModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_software.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-cube mr-2"></i>License
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkCredentialModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_credential.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-key mr-2"></i>Credential
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkServiceModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_service.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-stream mr-2"></i>Service
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkDocumentModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_document.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-folder mr-2"></i>Document
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkFileModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_file.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-paperclip mr-2"></i>File
|
||||
</a>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -446,7 +480,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 +501,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 +560,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 +581,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 +717,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 +729,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 +746,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,19 +1196,16 @@ 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/contact_link_asset_modal.php";
|
||||
require_once "modals/contact_link_software_modal.php";
|
||||
require_once "modals/contact_link_credential_modal.php";
|
||||
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 "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 "includes/footer.php";
|
||||
|
||||
110
contacts.php
110
contacts.php
@@ -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
|
||||
@@ -114,38 +110,47 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<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>
|
||||
|
||||
<?php if ($client_url) { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="location" onchange="this.form.submit()">
|
||||
<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']);
|
||||
@@ -160,12 +165,19 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<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 * 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_mobile_country_code']);
|
||||
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
|
||||
if (empty($contact_mobile)) {
|
||||
$contact_mobile_display = "";
|
||||
} else {
|
||||
@@ -351,30 +364,35 @@ $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");
|
||||
$asset_count = mysqli_num_rows($sql_related_assets);
|
||||
if ($asset_count) {
|
||||
$asset_count_display = "<span class='mr-2 badge badge-pill badge-dark p-2' title='$asset_count Assets'><i class='fas fa-fw fa-desktop mr-2'></i>$asset_count</span>";
|
||||
$asset_count_display = "<span class='mr-2 mb-1 badge badge-pill badge-dark p-2' title='$asset_count Assets'><i class='fas fa-fw fa-desktop mr-2'></i>$asset_count</span>";
|
||||
} else {
|
||||
$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 mb-1 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
|
||||
$sql_related_software = mysqli_query($mysqli, "SELECT * FROM software, software_contacts WHERE software.software_id = software_contacts.software_id AND software_contacts.contact_id = $contact_id");
|
||||
$software_count = mysqli_num_rows($sql_related_software);
|
||||
if ($software_count) {
|
||||
$software_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$software_count Licenses'><i class='fas fa-fw fa-cube mr-2'></i>$software_count</span>";
|
||||
$software_count_display = "<span class='mr-2 mb-1 badge badge-pill badge-secondary p-2' title='$software_count Licenses'><i class='fas fa-fw fa-cube mr-2'></i>$software_count</span>";
|
||||
} else {
|
||||
$software_count_display = '';
|
||||
}
|
||||
@@ -383,16 +401,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_contact_id = $contact_id");
|
||||
$ticket_count = mysqli_num_rows($sql_related_tickets);
|
||||
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>";
|
||||
$ticket_count_display = "<span class='mr-2 mb-1 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
|
||||
$sql_related_documents = mysqli_query($mysqli, "SELECT * FROM documents, contact_documents WHERE documents.document_id = contact_documents.document_id AND contact_documents.contact_id = $contact_id");
|
||||
$document_count = mysqli_num_rows($sql_related_documents);
|
||||
if ($document_count) {
|
||||
$document_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$document_count Documents'><i class='fas fa-fw fa-file-alt mr-2'></i>$document_count</span>";
|
||||
$document_count_display = "<span class='mr-2 mb-1 badge badge-pill badge-secondary p-2' title='$document_count Documents'><i class='fas fa-fw fa-file-alt mr-2'></i>$document_count</span>";
|
||||
} else {
|
||||
$document_count_display = '';
|
||||
}
|
||||
@@ -427,11 +445,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-modal-size="lg"
|
||||
data-ajax-url="ajax/ajax_contact_details.php?<?php echo $client_url; ?>"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<a class="text-dark" href="contact_details.php?client_id=<?php echo $client_id; ?>&contact_id=<?php echo $contact_id; ?>">
|
||||
<div class="media">
|
||||
<?php if ($contact_photo) { ?>
|
||||
<span class="fa-stack fa-2x mr-3 text-center">
|
||||
@@ -445,7 +459,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 +477,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>
|
||||
|
||||
282
credentials.php
282
credentials.php
@@ -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,10 +122,36 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<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">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="location" onchange="this.form.submit()">
|
||||
<option value="">- All Asset Locations -</option>
|
||||
|
||||
@@ -149,12 +171,19 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<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 * 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 } ?>
|
||||
@@ -238,7 +242,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
@@ -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 mb-1 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 mb-1 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>
|
||||
<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>
|
||||
<td class="text-nowrap"><?php echo $credential_username_display; ?></td>
|
||||
<td class="text-nowrap">
|
||||
<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 class="text-nowrap"><?php echo $otp_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 } ?>
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.grab-cursor {
|
||||
cursor: grab;
|
||||
.drag-handle {
|
||||
cursor: grab !important;
|
||||
}
|
||||
|
||||
.grab-cursor:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
.drag-handle:active {
|
||||
cursor: grabbing !important;
|
||||
}
|
||||
15
css/quote_dropdowns_fix.css
Normal file
15
css/quote_dropdowns_fix.css
Normal file
@@ -0,0 +1,15 @@
|
||||
/*!
|
||||
* AdminLTE 3.2.0 Specific Dropdown Fix
|
||||
* Targets .fix-quote-dropdown only
|
||||
* Prevents alignment bugs in split button dropdowns going too far left
|
||||
* (ChatGPT)
|
||||
*/
|
||||
|
||||
.fix-quote-dropdown .dropdown-menu {
|
||||
left: auto !important;
|
||||
right: 0 !important;
|
||||
top: calc(100% + 0.25rem) !important;
|
||||
transform: none !important;
|
||||
min-width: max-content;
|
||||
z-index: 1050;
|
||||
}
|
||||
@@ -1,41 +1,83 @@
|
||||
/* General Popover Styling */
|
||||
.popover {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
/* Kanban Board Container */
|
||||
#kanban-board {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
overflow-x: auto;
|
||||
box-sizing: border-box;
|
||||
min-width: 400px;
|
||||
height: calc(100vh - 210px);
|
||||
}
|
||||
|
||||
/* Kanban Column */
|
||||
.kanban-column {
|
||||
flex: 1; /* Allows columns to grow equally */
|
||||
margin: 0 10px; /* Space between columns */
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
max-width: 300px;
|
||||
margin: 0 10px;
|
||||
background: #f4f4f4;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
min-height: calc(100vh - 230px);
|
||||
max-height: calc(100vh - 230px);
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.kanban-column div {
|
||||
max-height: calc(100vh - 280px); /* Set your desired max height */
|
||||
overflow-y: auto; /* Adds a scrollbar when content exceeds max height */
|
||||
/* Column Inner Scrollable Task Area */
|
||||
.kanban-status {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
min-height: 60px;
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Individual Task Cards */
|
||||
.task {
|
||||
background: #fff;
|
||||
margin: 5px 0;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
user-select: none; /* Prevent text selection */
|
||||
border-radius: 4px;
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.drag-handle-class {
|
||||
touch-action: none;
|
||||
float: right;
|
||||
/* Grabbing Cursor State */
|
||||
.task:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* Drag Handle (shown on mobile or with class targeting) */
|
||||
.drag-handle-class {
|
||||
float: right;
|
||||
touch-action: none;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
/* Placeholder shown in empty columns */
|
||||
.empty-placeholder {
|
||||
border: 2px dashed #ccc;
|
||||
background-color: #fcfcfc;
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
padding: 12px;
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Sortable drop zone feedback (optional visual cue) */
|
||||
.kanban-status.sortable-over {
|
||||
background-color: #eaf6ff;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ $sql_years_select = mysqli_query($mysqli, "
|
||||
<input type="hidden" name="enable_technical" value="0">
|
||||
|
||||
<label for="year" class="mr-sm-2">Select Year:</label>
|
||||
<select id="year" onchange="this.form.submit()" class="form-control mr-sm-3 col-sm-2" name="year">
|
||||
<select id="year" onchange="this.form.submit()" class="form-control mr-sm-3 col-sm-2 mb-3 mb-sm-0" name="year">
|
||||
<?php while ($row = mysqli_fetch_array($sql_years_select)) {
|
||||
$year_select = $row['all_years'];
|
||||
if (empty($year_select)) {
|
||||
@@ -55,7 +55,7 @@ $sql_years_select = mysqli_query($mysqli, "
|
||||
</select>
|
||||
|
||||
<?php if ($session_user_role == 1 || ($session_user_role == 3 && $config_module_enable_accounting == 1)) { ?>
|
||||
<div class="custom-control custom-switch mr-sm-3">
|
||||
<div class="custom-control custom-switch mr-3">
|
||||
<input type="checkbox" onchange="this.form.submit()" class="custom-control-input" id="customSwitch1" name="enable_financial" value="1" <?php if ($user_config_dashboard_financial_enable == 1) { echo "checked"; } ?>>
|
||||
<label class="custom-control-label" for="customSwitch1">Financial</label>
|
||||
</div>
|
||||
@@ -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);
|
||||
|
||||
@@ -156,7 +151,7 @@ if ($user_config_dashboard_financial_enable == 1) {
|
||||
$row = mysqli_fetch_array($sql_unbilled_tickets);
|
||||
$unbilled_tickets = intval($row['unbilled_tickets']);
|
||||
} else {
|
||||
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(recurring_id) AS recurring_invoices_added FROM recurring WHERE YEAR(recurring_created_at) = $year"));
|
||||
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(recurring_invoice_id) AS recurring_invoices_added FROM recurring_invoices WHERE YEAR(recurring_invoice_created_at) = $year"));
|
||||
$recurring_invoices_added = intval($row['recurring_invoices_added']);
|
||||
}
|
||||
|
||||
|
||||
1202
database_updates.php
1202
database_updates.php
File diff suppressed because it is too large
Load Diff
50
domains.php
50
domains.php
@@ -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 mb-3 mb-md-0">
|
||||
<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"; } ?>">
|
||||
@@ -122,7 +162,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
|
||||
<?php } ?>
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
@@ -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">
|
||||
|
||||
19
expenses.php
19
expenses.php
@@ -228,19 +228,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
Date <?php if ($sort == 'expense_date') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_name&order=<?php echo $disp; ?>">
|
||||
Vendor <?php if ($sort == 'vendor_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=category_name&order=<?php echo $disp; ?>">
|
||||
Category <?php if ($sort == 'category_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
/
|
||||
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=expense_description&order=<?php echo $disp; ?>">
|
||||
Description <?php if ($sort == 'expense_description') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=expense_description&order=<?php echo $disp; ?>">
|
||||
Description <?php if ($sort == 'expense_description') { echo $order_icon; } ?>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_name&order=<?php echo $disp; ?>">
|
||||
Vendor <?php if ($sort == 'vendor_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-right">
|
||||
@@ -313,9 +312,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<?php echo $expense_date; ?>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $category_name; ?>
|
||||
<div class="text-secondary"><small><?php echo truncate($expense_description, 60); ?></small></div>
|
||||
</td>
|
||||
<td><?php echo $vendor_name; ?></td>
|
||||
<td><?php echo $category_name; ?></td>
|
||||
<td><?php echo truncate($expense_description, 50); ?></td>
|
||||
<td class="text-bold text-right"><?php echo numfmt_format_currency($currency_format, $expense_amount, $expense_currency_code); ?></td>
|
||||
<td><?php echo $account_name; ?></td>
|
||||
<td><?php echo $client_name_display; ?></td>
|
||||
|
||||
428
functions.php
428
functions.php
@@ -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,168 @@ function truncate($text, $chars)
|
||||
return $text . "...";
|
||||
}
|
||||
|
||||
function formatPhoneNumber($phoneNumber)
|
||||
{
|
||||
global $mysqli;
|
||||
function formatPhoneNumber($phoneNumber, $country_code = '', $show_country_code = false) {
|
||||
// Remove all non-digit characters
|
||||
$digits = preg_replace('/\D/', '', $phoneNumber);
|
||||
$formatted = '';
|
||||
|
||||
// Get Phone Mask Option
|
||||
$phone_mask = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_phone_mask FROM settings WHERE company_id = 1"))[0];
|
||||
|
||||
if ($phone_mask == 0) {
|
||||
// If no digits at all, fallback early
|
||||
if (strlen($digits) === 0) {
|
||||
return $phoneNumber;
|
||||
}
|
||||
|
||||
// Helper function to safely check the first digit
|
||||
$startsWith = function($str, $char) {
|
||||
return isset($str[0]) && $str[0] === $char;
|
||||
};
|
||||
|
||||
$phoneNumber = $phoneNumber ? preg_replace('/[^0-9]/', '', $phoneNumber) : "";
|
||||
switch ($country_code) {
|
||||
case '1': // USA/Canada
|
||||
if (strlen($digits) === 10) {
|
||||
$formatted = '(' . substr($digits, 0, 3) . ') ' . substr($digits, 3, 3) . '-' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
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);
|
||||
case '44': // UK
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) === 10) {
|
||||
$formatted = '0' . substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
$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);
|
||||
case '61': // Australia
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) === 9) {
|
||||
$formatted = '0' . substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
$phoneNumber = '(' . $areaCode . ') ' . $nextThree . '-' . $lastFour;
|
||||
} else if (strlen($phoneNumber) == 7) {
|
||||
$nextThree = substr($phoneNumber, 0, 3);
|
||||
$lastFour = substr($phoneNumber, 3, 4);
|
||||
case '91': // India
|
||||
if (strlen($digits) === 10) {
|
||||
$formatted = substr($digits, 0, 5) . ' ' . substr($digits, 5);
|
||||
}
|
||||
break;
|
||||
|
||||
$phoneNumber = $nextThree . '-' . $lastFour;
|
||||
case '81': // Japan
|
||||
if ($startsWith($digits, '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
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) >= 10) {
|
||||
$formatted = '0' . substr($digits, 0, 3) . ' ' . substr($digits, 3);
|
||||
}
|
||||
break;
|
||||
|
||||
case '33': // France
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) === 9) {
|
||||
$formatted = '0' . implode(' ', str_split($digits, 2));
|
||||
}
|
||||
break;
|
||||
|
||||
case '34': // Spain
|
||||
if (strlen($digits) === 9) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
case '39': // Italy
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
$formatted = '0' . implode(' ', str_split($digits, 3));
|
||||
break;
|
||||
|
||||
case '55': // Brazil
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = '(' . substr($digits, 0, 2) . ') ' . substr($digits, 2, 5) . '-' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '7': // Russia
|
||||
if ($startsWith($digits, '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
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 4) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '82': // South Korea
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = substr($digits, 0, 3) . '-' . substr($digits, 3, 4) . '-' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '62': // Indonesia
|
||||
if (!$startsWith($digits, '0')) {
|
||||
$digits = '0' . $digits;
|
||||
}
|
||||
if (strlen($digits) === 12) {
|
||||
$formatted = substr($digits, 0, 4) . ' ' . substr($digits, 4, 4) . ' ' . substr($digits, 8);
|
||||
}
|
||||
break;
|
||||
|
||||
case '63': // Philippines
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '234': // Nigeria
|
||||
if (!$startsWith($digits, '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
|
||||
if (strlen($digits) >= 9 && strlen($digits) <= 10) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
case '971': // UAE
|
||||
if (strlen($digits) === 9) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// fallback — do nothing, use raw digits later
|
||||
break;
|
||||
}
|
||||
|
||||
return $phoneNumber;
|
||||
if (!$formatted) {
|
||||
$formatted = $digits ?: $phoneNumber;
|
||||
}
|
||||
|
||||
return $show_country_code && $country_code ? "+$country_code $formatted" : $formatted;
|
||||
}
|
||||
|
||||
function mkdirMissing($dir)
|
||||
{
|
||||
function mkdirMissing($dir) {
|
||||
if (!is_dir($dir)) {
|
||||
mkdir($dir);
|
||||
}
|
||||
@@ -249,8 +362,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 +380,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 +445,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 +461,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 +478,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 +650,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 +662,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 +674,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"]);
|
||||
@@ -594,7 +705,17 @@ function sendSingleEmail($config_smtp_host, $config_smtp_username, $config_smtp_
|
||||
$mail->SMTPAuth = $smtp_auth; // Enable SMTP authentication
|
||||
$mail->Username = $config_smtp_username; // SMTP username
|
||||
$mail->Password = $config_smtp_password; // SMTP password
|
||||
$mail->SMTPSecure = $config_smtp_encryption; // Enable TLS encryption, `ssl` also accepted
|
||||
if ($config_smtp_encryption == 'None') {
|
||||
$mail->SMTPOptions = array(
|
||||
'ssl' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
));
|
||||
$mail->SMTPSecure = false;
|
||||
$mail->SMTPAutoTLS = false;
|
||||
} else {
|
||||
$mail->SMTPSecure = $config_smtp_encryption; // Enable TLS encryption, `ssl` also accepted
|
||||
}
|
||||
$mail->Port = $config_smtp_port; // TCP port to connect to
|
||||
|
||||
//Recipients
|
||||
@@ -765,7 +886,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;
|
||||
@@ -1313,15 +1434,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);
|
||||
@@ -1376,7 +1497,7 @@ function appNotify($type, $details, $action = null, $client_id = 0, $entity_id =
|
||||
$sql = mysqli_query($mysqli, "SELECT user_id FROM users
|
||||
WHERE user_type = 1 AND user_status = 1 AND user_archived_at IS NULL
|
||||
");
|
||||
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$user_id = intval($row['user_id']);
|
||||
|
||||
@@ -1412,5 +1533,122 @@ 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, $folder_location = 0, $indent = 0) {
|
||||
global $mysqli;
|
||||
|
||||
$folder_location = intval($folder_location);
|
||||
// 0 = Document Folders
|
||||
// 1 = File Folders
|
||||
|
||||
$sql_folders = mysqli_query($mysqli, "SELECT * FROM folders WHERE parent_folder = $parent_folder_id AND folder_location = $folder_location 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(' ', $indent * 4);
|
||||
|
||||
// Check if this folder is selected
|
||||
$selected = '';
|
||||
if ((isset($_GET['folder_id']) && intval($_GET['folder_id']) === $folder_id) ||
|
||||
(isset($_POST['folder']) && intval($_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, $folder_location, $indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -717,7 +721,6 @@ if (isset($_GET['query'])) {
|
||||
} else {
|
||||
$asset_serial_display = $asset_serial;
|
||||
}
|
||||
$asset_mac = nullable_htmlentities($row['asset_mac']);
|
||||
$asset_uri = nullable_htmlentities($row['asset_uri']);
|
||||
$asset_status = nullable_htmlentities($row['asset_status']);
|
||||
$asset_created_at = nullable_htmlentities($row['asset_created_at']);
|
||||
@@ -742,9 +745,9 @@ if (isset($_GET['query'])) {
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-2"></i><?php echo $asset_name; ?>
|
||||
<i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-2"></i><a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>"><?php echo $asset_name; ?></a>
|
||||
<?php if(!empty($asset_uri)){ ?>
|
||||
<a href="<?php echo $asset_uri; ?>" target="_blank"><i class="fas fa-fw fa-external-link-alt ml-2"></i></a>
|
||||
<a href="<?php echo $asset_uri; ?>" target="_blank"><i class="fas fa-fw fa-external-link-alt ml-2"></i></a>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td><?php echo $asset_type; ?></td>
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -97,9 +97,7 @@ if (isset($_GET['stripe_create_pi'])) {
|
||||
'itflow_invoice_number' => $invoice_prefix . $invoice_number,
|
||||
'itflow_invoice_id' => $invoice_id,
|
||||
],
|
||||
'automatic_payment_methods' => [
|
||||
'enabled' => true,
|
||||
],
|
||||
'payment_method_types' => ['card'],
|
||||
]);
|
||||
|
||||
$output = [
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user