mirror of
https://github.com/itflow-org/itflow
synced 2026-03-17 19:24:50 +00:00
Merge branch 'itflow-org:master' into balance-sheet
This commit is contained in:
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,35 +1,22 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Something not working quite right? Create a report to help us improve!
|
about: Please report bugs on the Forum @ https://forum.itflow.org/t/bug
|
||||||
title: ''
|
title: 'Please report bugs on the Forum'
|
||||||
labels: ''
|
labels: Support
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug**
|
We're now using GitHub Issues exclusively for development.
|
||||||
A clear and concise description of what the bug is.
|
-
|
||||||
|
|
||||||
**Can you reproduce this on the demo at demo.itflow.org**
|
Going forward, GitHub Issues will be used to track confirmed bugs & planned features via Github Projects. This allows us to keep GitHub clean & tidy, whilst maintaining an active and relaxed community experience on the Forum.
|
||||||
Yes/No/NA
|
|
||||||
|
|
||||||
**Are you on the latest available version of ITFlow, with an up-to-date database structure?**
|
Please raise bugs on the forum @ https://forum.itflow.org/t/bug. Make sure to mention whether you can replicate the bug on demo.itflow.org.
|
||||||
Yes/No
|
|
||||||
|
|
||||||
**To Reproduce**
|
Thanks,
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
The ITFlow team :)
|
||||||
A clear and concise description of what you expected to happen, if not obvious.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
|
|||||||
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,16 +1,25 @@
|
|||||||
---
|
---
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Please discuss new features on the Forum @ https://forum.itflow.org/t/features
|
about: Please discuss new features on the Forum @ https://forum.itflow.org/t/features
|
||||||
title: ''
|
title: 'Please discuss new features on the Forum'
|
||||||
labels: Support
|
labels: Support
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
We're now using GitHub just to track features we're definitely planning to implement (and bugs!).
|
We're now using GitHub Issues exclusively for development.
|
||||||
|
-
|
||||||
|
|
||||||
Please discuss new feature requests on the forum @ https://forum.itflow.org/t/features. This allows us to gather interest & feedback on the features people feel are most important, whilst keeping GitHub cleaner and more about the code.
|
Going forward, GitHub Issues will be used to track confirmed bugs & planned features via Github Projects. This allows us to keep GitHub clean & tidy, whilst maintaining an active and relaxed community experience on the Forum.
|
||||||
|
|
||||||
New feature requests here will be closed.
|
Please discuss new feature requests on the forum @ https://forum.itflow.org/t/features. When creating discussions, try to imagine how your proposed feature would also benefit other users.
|
||||||
|
|
||||||
Thanks :)
|
All new feature requests raised here will be closed, unless agreed otherwise.
|
||||||
|
|
||||||
|
Thanks,
|
||||||
|
|
||||||
|
The ITFlow team :)
|
||||||
|
|
||||||
|
--
|
||||||
|
|
||||||
|
To privately discuss a security issue, please see https://github.com/itflow-org/itflow/security
|
||||||
|
|||||||
17
.github/ISSUE_TEMPLATE/support.md
vendored
17
.github/ISSUE_TEMPLATE/support.md
vendored
@@ -1,17 +1,24 @@
|
|||||||
---
|
---
|
||||||
name: Support
|
name: Support
|
||||||
about: Please visit the Forum or Discord for support
|
about: Please request support on the Forum @ https://forum.itflow.org/t/support
|
||||||
title: ''
|
title: 'Please visit the Forum for support'
|
||||||
labels: Support
|
labels: Support
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Please visit the Forum or Discord for support
|
We're now using GitHub Issues exclusively for development.
|
||||||
|
-
|
||||||
|
|
||||||
Forum - https://forum.itflow.org/
|
Going forward, GitHub Issues will be used to track confirmed bugs & planned features via Github Projects. This allows us to keep GitHub clean & tidy, whilst maintaining an active and relaxed community experience on the Forum.
|
||||||
|
|
||||||
Discord - https://discord.gg/ZjCcBzTUDr
|
Please use the forum for support queries/issues: https://forum.itflow.org/t/support
|
||||||
|
|
||||||
|
All new support requests raised here will be closed.
|
||||||
|
|
||||||
|
Thanks,
|
||||||
|
|
||||||
|
The ITFlow team :)
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/first-interaction.yml
vendored
4
.github/workflows/first-interaction.yml
vendored
@@ -16,9 +16,9 @@ jobs:
|
|||||||
issue-message: |
|
issue-message: |
|
||||||
Hello & Welcome! :)
|
Hello & Welcome! :)
|
||||||
|
|
||||||
Thanks for taking the time to get in touch. We'll review this issue shortly.
|
Thanks for taking the time to get in touch.
|
||||||
|
|
||||||
Whilst you're waiting, please feel free to check out the [forum](https://forum.itflow.org).
|
We ask that all bugs/feature/support requests are raised via the [forum](https://forum.itflow.org). We'll be in touch shortly to confirm.
|
||||||
pr-message: |
|
pr-message: |
|
||||||
Hello & Welcome! :)
|
Hello & Welcome! :)
|
||||||
|
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -33,6 +33,8 @@
|
|||||||
<a href="https://github.com/itflow-org/itflow/issues">Report Bug</a>
|
<a href="https://github.com/itflow-org/itflow/issues">Report Bug</a>
|
||||||
·
|
·
|
||||||
<a href="https://forum.itflow.org/t/features">Request Feature</a>
|
<a href="https://forum.itflow.org/t/features">Request Feature</a>
|
||||||
|
·
|
||||||
|
<a href="https://github.com/itflow-org/itflow/security/policy">Security</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -83,20 +85,28 @@
|
|||||||
* FullCalendar.io
|
* FullCalendar.io
|
||||||
|
|
||||||
<!-- GETTING STARTED -->
|
<!-- GETTING STARTED -->
|
||||||
## Getting Started / Installation
|
## Getting Started
|
||||||
|
|
||||||
ITFlow is self-hosted. There is a full installation guide in the [docs](https://docs.itflow.org/installation), but the main steps are:
|
ITFlow is self-hosted. There is a full installation guide in the [docs](https://docs.itflow.org/installation).
|
||||||
|
|
||||||
1. Install a LAMP stack (Linux, Apache, MariaDB, PHP)
|
|
||||||
```sh
|
<!-- EASY INSTALL -->
|
||||||
sudo apt install git apache2 php libapache2-mod-php php-intl php-imap php-mailparse php-mysqli php-curl mariadb-server
|
### Installation via Script (Recommended Method)
|
||||||
```
|
|
||||||
2. Clone the repo
|
**Requirements**
|
||||||
```sh
|
- Clean Install of Debian 12 or Ubuntu 22.04
|
||||||
git clone https://github.com/itflow-org/itflow.git /var/www/html
|
- A public IP Address
|
||||||
```
|
- Ports 80 (HTTP) and 443 (HTTPS) TCP accessible from the outside in
|
||||||
3. Create a MariaDB Database
|
- A Fully Qualified Domain Name pointing to the public IP Address – example itflow.example.com, NOT itflow.xyz.example.com
|
||||||
4. Point your browser to your HTTPS web server to begin setup
|
|
||||||
|
**Process**
|
||||||
|
- Login as root
|
||||||
|
- Download & run install script
|
||||||
|
```
|
||||||
|
wget -O - https://github.com/itflow-org/itflow-install-script/raw/main/itflow_install.sh | bash
|
||||||
|
```
|
||||||
|
- Follow Instructions & navigate to setup URL shown
|
||||||
|
- Leave us feedback in the [forum](https://forum.itflow.org/d/11-road-map)
|
||||||
|
|
||||||
<!-- FEATURES -->
|
<!-- FEATURES -->
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|||||||
15
SECURITY.md
15
SECURITY.md
@@ -1,5 +1,9 @@
|
|||||||
# Security Policy
|
# Security Policy
|
||||||
|
|
||||||
|
## **Please do NOT report security concerns/vulnerabilities publicly (Github issues/forum)**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## In Beta
|
## In Beta
|
||||||
|
|
||||||
ITFlow is currently in beta and is a work in progress.
|
ITFlow is currently in beta and is a work in progress.
|
||||||
@@ -13,11 +17,12 @@ We attempt to follow security best practices where possible, including [automate
|
|||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
| Beta | :white_check_mark: |
|
| Beta | :white_check_mark: |
|
||||||
|
| 1.0 | Yet to be released |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability via GitHub Security Advisories
|
||||||
|
|
||||||
**<ins>Please do not report security vulnerabilities through public GitHub issues.</ins>**
|
|
||||||
|
|
||||||
If you have discovered a security issue, please [report it](https://github.com/itflow-org/itflow/security/advisories/new) to us in as much detail as possible, so we can fix it. You should expect to receive an initial acknowledgement within 72 hours.
|
|
||||||
|
|
||||||
**Security contact: [GitHub Security Advisories](https://github.com/itflow-org/itflow/security/advisories/new)**
|
**Security contact: [GitHub Security Advisories](https://github.com/itflow-org/itflow/security/advisories/new)**
|
||||||
|
|
||||||
|
If you have discovered a security issue, please **[report it](https://github.com/itflow-org/itflow/security/advisories/new)** to us in as much detail as possible, so we can fix it.
|
||||||
|
|
||||||
|
You should expect to receive an initial acknowledgement within 72 hours. If you don't receive any feedback, we may have missed the initial email from GitHub (we're human!). Please raise a private forum discussion with johnny and wrongecho quoting ONLY the assigned GHSA ref.
|
||||||
|
|||||||
@@ -45,17 +45,17 @@ if ($session_user_role == 3) {
|
|||||||
$session_user_config_force_mfa = intval($row['user_config_force_mfa']);
|
$session_user_config_force_mfa = intval($row['user_config_force_mfa']);
|
||||||
$user_config_records_per_page = intval($row['user_config_records_per_page']);
|
$user_config_records_per_page = intval($row['user_config_records_per_page']);
|
||||||
|
|
||||||
$sql = mysqli_query($mysqli, "SELECT * FROM companies WHERE company_id = 1");
|
$sql = mysqli_query($mysqli, "SELECT * FROM companies, settings WHERE settings.company_id = companies.company_id AND companies.company_id = 1");
|
||||||
$row = mysqli_fetch_array($sql);
|
$row = mysqli_fetch_array($sql);
|
||||||
|
|
||||||
$session_company_name = $row['company_name'];
|
$session_company_name = $row['company_name'];
|
||||||
$session_company_country = $row['company_country'];
|
$session_company_country = $row['company_country'];
|
||||||
$session_company_locale = $row['company_locale'];
|
$session_company_locale = $row['company_locale'];
|
||||||
$session_company_currency = $row['company_currency'];
|
$session_company_currency = $row['company_currency'];
|
||||||
$session_company_timezone = $row['company_timezone'];
|
$session_timezone = $row['settings_timezone'];
|
||||||
|
|
||||||
// Set Timezone to the companies timezone
|
// Set Timezone to the companies timezone
|
||||||
date_default_timezone_set('$session_company_timezone');
|
date_default_timezone_set('$session_timezone');
|
||||||
|
|
||||||
//Set Currency Format
|
//Set Currency Format
|
||||||
$currency_format = numfmt_create($session_company_locale, NumberFormatter::CURRENCY);
|
$currency_format = numfmt_create($session_company_locale, NumberFormatter::CURRENCY);
|
||||||
|
|||||||
@@ -96,10 +96,10 @@ if (isset($_GET['contact_id'])) {
|
|||||||
<div><i class="fa fa-fw fa-envelope text-secondary mr-3"></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><i class="fa fa-fw fa-envelope text-secondary mr-3"></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>
|
||||||
<?php }
|
<?php }
|
||||||
if (!empty($contact_phone)) { ?>
|
if (!empty($contact_phone)) { ?>
|
||||||
<div class="mb-2"><i class="fa fa-fw fa-phone text-secondary mr-3"></i><?php echo "$contact_phone $contact_extension"; ?></div>
|
<div class="mb-2"><i class="fa fa-fw fa-phone text-secondary mr-3"></i><a href="tel:<?php echo "$contact_phone"?>"><?php echo "$contact_phone $contact_extension"; ?></a></div>
|
||||||
<?php }
|
<?php }
|
||||||
if (!empty($contact_mobile)) { ?>
|
if (!empty($contact_mobile)) { ?>
|
||||||
<div class="mb-2"><i class="fa fa-fw fa-mobile-alt text-secondary mr-3"></i><?php echo $contact_mobile; ?></div>
|
<div class="mb-2"><i class="fa fa-fw fa-mobile-alt text-secondary mr-3"></i><a href="tel:<?php echo $contact_mobile; ?>"><?php echo $contact_mobile; ?></a></div>
|
||||||
<?php }
|
<?php }
|
||||||
if (!empty($contact_pin)) { ?>
|
if (!empty($contact_pin)) { ?>
|
||||||
<div class="mb-2"><i class="fa fa-fw fa-key text-secondary mr-3"></i><?php echo $contact_pin; ?></div>
|
<div class="mb-2"><i class="fa fa-fw fa-key text-secondary mr-3"></i><?php echo $contact_pin; ?></div>
|
||||||
@@ -549,36 +549,36 @@ if (isset($_GET['contact_id'])) {
|
|||||||
|
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function updateContactNotes(contact_id) {
|
function updateContactNotes(contact_id) {
|
||||||
var notes = document.getElementById("contactNotes").value;
|
var notes = document.getElementById("contactNotes").value;
|
||||||
|
|
||||||
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
|
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
|
||||||
jQuery.post(
|
jQuery.post(
|
||||||
"ajax.php",
|
"ajax.php",
|
||||||
{
|
{
|
||||||
contact_set_notes: 'TRUE',
|
contact_set_notes: 'TRUE',
|
||||||
contact_id: contact_id,
|
contact_id: contact_id,
|
||||||
notes: notes
|
notes: notes
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- JavaScript to Show/Hide Password Form Group -->
|
<!-- JavaScript to Show/Hide Password Form Group -->
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('.authMethod').on('change', function() {
|
$('.authMethod').on('change', function() {
|
||||||
var $form = $(this).closest('.authForm');
|
var $form = $(this).closest('.authForm');
|
||||||
if ($(this).val() === 'local') {
|
if ($(this).val() === 'local') {
|
||||||
$form.find('.passwordGroup').show();
|
$form.find('.passwordGroup').show();
|
||||||
} else {
|
} else {
|
||||||
$form.find('.passwordGroup').hide();
|
$form.find('.passwordGroup').hide();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
$('.authMethod').trigger('change');
|
||||||
});
|
});
|
||||||
$('.authMethod').trigger('change');
|
</script>
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
require_once("footer.php");
|
require_once("footer.php");
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<input type="hidden" name="contact_important" value="0">
|
<input type="hidden" name="contact_important" value="0">
|
||||||
<input type="hidden" name="contact_billing" value="0">
|
<input type="hidden" name="contact_billing" value="0">
|
||||||
<input type="hidden" name="contact_technical" value="0">
|
<input type="hidden" name="contact_technical" value="0">
|
||||||
|
<input type="hidden" name="send_email" value="0">
|
||||||
<!-- End prevent undefined errors -->
|
<!-- End prevent undefined errors -->
|
||||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||||
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
|
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
|
||||||
@@ -198,7 +199,7 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
|
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<input type="password" class="form-control" data-toggle="password" name="contact_password" placeholder="Leave blank for no change" autocomplete="new-password">
|
<input type="password" class="form-control" data-toggle="password" name="contact_password" placeholder="Leave blank for no change" autocomplete="new-password" minlength="8">
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
|
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
|
||||||
</div>
|
</div>
|
||||||
@@ -207,7 +208,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input type="checkbox" class="form-check-input" name="send_email" value=""/>
|
<input type="checkbox" class="form-check-input" name="send_email" value="1"/>
|
||||||
<label class="form-check-label">Send user e-mail with login details?</label>
|
<label class="form-check-label">Send user e-mail with login details?</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -252,4 +253,4 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -111,14 +111,14 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||||||
if (empty($contact_phone)) {
|
if (empty($contact_phone)) {
|
||||||
$contact_phone_display = "";
|
$contact_phone_display = "";
|
||||||
} else {
|
} else {
|
||||||
$contact_phone_display = "<div><i class='fas fa-fw fa-phone mr-2'></i>$contact_phone$contact_extension_display</div>";
|
$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 = formatPhoneNumber($row['contact_mobile']);
|
||||||
if (empty($contact_mobile)) {
|
if (empty($contact_mobile)) {
|
||||||
$contact_mobile_display = "";
|
$contact_mobile_display = "";
|
||||||
} else {
|
} else {
|
||||||
$contact_mobile_display = "<div class='mt-2'><i class='fas fa-fw fa-mobile-alt mr-2'></i>$contact_mobile</div>";
|
$contact_mobile_display = "<div class='mt-2'><i class='fas fa-fw fa-mobile-alt mr-2'></i><a href='tel:$contact_mobile'>$contact_mobile</a></div>";
|
||||||
}
|
}
|
||||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||||
if (empty($contact_email)) {
|
if (empty($contact_email)) {
|
||||||
@@ -210,7 +210,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||||||
</a>
|
</a>
|
||||||
<?php if ($session_user_role == 3 && $contact_primary == 0) { ?>
|
<?php if ($session_user_role == 3 && $contact_primary == 0) { ?>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a class="dropdown-item text-danger" href="post.php?anonymize_contact=<?php echo $contact_id; ?>">
|
<a class="dropdown-item text-danger confirm-link" href="post.php?anonymize_contact=<?php echo $contact_id; ?>">
|
||||||
<i class="fas fa-fw fa-user-secret mr-2"></i>Anonymize & Archive
|
<i class="fas fa-fw fa-user-secret mr-2"></i>Anonymize & Archive
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||||||
$domain_webhost = intval($row['domain_webhost']);
|
$domain_webhost = intval($row['domain_webhost']);
|
||||||
$domain_expire = nullable_htmlentities($row['domain_expire']);
|
$domain_expire = nullable_htmlentities($row['domain_expire']);
|
||||||
$domain_registrar_name = nullable_htmlentities($row['vendor_name']);
|
$domain_registrar_name = nullable_htmlentities($row['vendor_name']);
|
||||||
|
$domain_created_at = nullable_htmlentities($row['domain_created_at']);
|
||||||
if (empty($domain_registrar_name)) {
|
if (empty($domain_registrar_name)) {
|
||||||
$domain_registrar_name = "-";
|
$domain_registrar_name = "-";
|
||||||
}
|
}
|
||||||
@@ -82,7 +83,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||||||
if ($row) {
|
if ($row) {
|
||||||
$domain_webhost_name = nullable_htmlentities($row['vendor_name']);
|
$domain_webhost_name = nullable_htmlentities($row['vendor_name']);
|
||||||
}
|
}
|
||||||
$domain_created_at = nullable_htmlentities($row['domain_created_at']);
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -94,9 +94,9 @@ function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date
|
|||||||
|
|
||||||
// Prep ticket details
|
// Prep ticket details
|
||||||
$message = nl2br($message);
|
$message = nl2br($message);
|
||||||
$message = mysqli_real_escape_string($mysqli, "<i>Email from: $contact_email at $date:-</i> <br><br>$message");
|
$message_escaped = mysqli_real_escape_string($mysqli, "<i>Email from: $contact_email at $date:-</i> <br><br>$message");
|
||||||
|
|
||||||
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_subject = '$subject', ticket_details = '$message', ticket_priority = 'Low', ticket_status = 'Pending-Assignment', ticket_created_by = 0, ticket_contact_id = $contact_id, ticket_client_id = $client_id");
|
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_subject = '$subject', ticket_details = '$message_escaped', ticket_priority = 'Low', ticket_status = 'Pending-Assignment', ticket_created_by = 0, ticket_contact_id = $contact_id, ticket_client_id = $client_id");
|
||||||
$id = mysqli_insert_id($mysqli);
|
$id = mysqli_insert_id($mysqli);
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
@@ -141,27 +141,16 @@ function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date
|
|||||||
// E-mail client notification that ticket has been created
|
// E-mail client notification that ticket has been created
|
||||||
if ($config_ticket_client_general_notifications == 1) {
|
if ($config_ticket_client_general_notifications == 1) {
|
||||||
|
|
||||||
$email_subject = "Ticket created - [$config_ticket_prefix$ticket_number] - $subject";
|
// Insert email into queue (first, escape vars)
|
||||||
$email_body = "<i style='color: #808080'>##- Please type your reply above this line -##</i><br><br>Hello, $contact_name<br><br>Thank you for your email. A ticket regarding \"$subject\" has been automatically created for you.<br><br>Ticket: $config_ticket_prefix$ticket_number<br>Subject: $subject<br>Status: Open<br>https://$config_base_url/portal/ticket.php?id=$id<br><br>~<br>$company_name<br>Support Department<br>$config_ticket_from_email<br>$company_phone";
|
$contact_email_escaped = sanitizeInput($contact_email);
|
||||||
|
$contact_name_escaped = sanitizeInput($contact_name);
|
||||||
|
$config_ticket_from_email_escaped = sanitizeInput($config_ticket_from_email);
|
||||||
|
$config_ticket_from_name_escaped = sanitizeInput($config_ticket_from_name);
|
||||||
|
|
||||||
$mail = sendSingleEmail(
|
$subject_escaped = mysqli_escape_string($mysqli, "Ticket created - [$config_ticket_prefix$ticket_number] - $subject");
|
||||||
$config_smtp_host,
|
$body_escaped = mysqli_escape_string($mysqli, "<i style='color: #808080'>##- Please type your reply above this line -##</i><br><br>Hello, $contact_name<br><br>Thank you for your email. A ticket regarding \"$subject\" has been automatically created for you.<br><br>Ticket: $config_ticket_prefix$ticket_number<br>Subject: $subject<br>Status: Open<br>https://$config_base_url/portal/ticket.php?id=$id<br><br>~<br>$company_name<br>Support Department<br>$config_ticket_from_email<br>$company_phone");
|
||||||
$config_smtp_username,
|
|
||||||
$config_smtp_password,
|
|
||||||
$config_smtp_encryption,
|
|
||||||
$config_smtp_port,
|
|
||||||
$config_ticket_from_email,
|
|
||||||
$config_ticket_from_name,
|
|
||||||
$contact_email,
|
|
||||||
$contact_name,
|
|
||||||
$email_subject,
|
|
||||||
$email_body
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($mail !== true) {
|
mysqli_query($mysqli, "INSERT INTO email_queue SET email_recipient = '$contact_email_escaped', email_recipient_name = '$contact_name_escaped', email_from = '$config_ticket_from_email_escaped', email_from_name = '$config_ticket_from_name_escaped', email_subject = '$subject_escaped', email_content = '$body_escaped'");
|
||||||
mysqli_query($mysqli, "INSERT INTO notifications SET notification_type = 'Mail', notification = 'Failed to send email to $contact_email'");
|
|
||||||
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Mail', log_action = 'Error', log_description = 'Failed to send email to $contact_email regarding $subject. $mail'");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,8 +162,10 @@ function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date
|
|||||||
$client_row = mysqli_fetch_array($client_sql);
|
$client_row = mysqli_fetch_array($client_sql);
|
||||||
$client_name = sanitizeInput($client_row['client_name']);
|
$client_name = sanitizeInput($client_row['client_name']);
|
||||||
|
|
||||||
$details = removeEmoji($message);
|
// TODO: Fix Emojis and HTML opening tags sometimes breaking this "forwarding"
|
||||||
$email_subject = "ITFlow - New Ticket - $client_name: $subject";
|
$details = removeEmoji($message_escaped);
|
||||||
|
|
||||||
|
$email_subject = mysqli_escape_string($mysqli, "ITFlow - New Ticket - $client_name: $subject");
|
||||||
$email_body = "Hello, <br><br>This is a notification that a new ticket has been raised in ITFlow. <br>Client: $client_name<br>Priority: Low (email parsed)<br>Link: https://$config_base_url/ticket.php?ticket_id=$id <br><br>--------------------------------<br><br><b>$subject</b><br>$details";
|
$email_body = "Hello, <br><br>This is a notification that a new ticket has been raised in ITFlow. <br>Client: $client_name<br>Priority: Low (email parsed)<br>Link: https://$config_base_url/ticket.php?ticket_id=$id <br><br>--------------------------------<br><br><b>$subject</b><br>$details";
|
||||||
|
|
||||||
mysqli_query($mysqli, "INSERT INTO email_queue SET email_recipient = '$config_ticket_new_ticket_notification_email', email_recipient_name = 'ITFlow Agents', email_from = '$config_ticket_from_email', email_from_name = '$config_ticket_from_name', email_subject = '$email_subject', email_content = '$email_body'");
|
mysqli_query($mysqli, "INSERT INTO email_queue SET email_recipient = '$config_ticket_new_ticket_notification_email', email_recipient_name = 'ITFlow Agents', email_from = '$config_ticket_from_email', email_from_name = '$config_ticket_from_name', email_subject = '$email_subject', email_content = '$email_body'");
|
||||||
@@ -366,9 +357,17 @@ if ($emails) {
|
|||||||
$date = trim(mysqli_real_escape_string($mysqli, nullable_htmlentities(strip_tags($parser->getHeader('date')))));
|
$date = trim(mysqli_real_escape_string($mysqli, nullable_htmlentities(strip_tags($parser->getHeader('date')))));
|
||||||
$attachments = $parser->getAttachments();
|
$attachments = $parser->getAttachments();
|
||||||
|
|
||||||
|
// Get the message content
|
||||||
|
// (first try HTML parsing, but switch to plain text if the email is empty/plain-text only)
|
||||||
|
// $message = $parser->getMessageBody('htmlEmbedded');
|
||||||
|
// if (empty($message)) {
|
||||||
|
// echo "DEBUG: Switching to plain text parsing for this message ($subject)";
|
||||||
|
// $message = $parser->getMessageBody('text');
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: Default to getting HTML and fallback to plaintext, but HTML emails seem to break the forward/agent notifications
|
||||||
|
|
||||||
$message = $parser->getMessageBody('text');
|
$message = $parser->getMessageBody('text');
|
||||||
// If below is enabled and up above is enabled text based emails get cut out
|
|
||||||
//$message = $parser->getMessageBody('htmlEmbedded');
|
|
||||||
|
|
||||||
// Check if we can identify a ticket number (in square brackets)
|
// Check if we can identify a ticket number (in square brackets)
|
||||||
if (preg_match("/\[$config_ticket_prefix\d+\]/", $subject, $ticket_number)) {
|
if (preg_match("/\[$config_ticket_prefix\d+\]/", $subject, $ticket_number)) {
|
||||||
@@ -407,14 +406,14 @@ if ($emails) {
|
|||||||
// Couldn't match this email to an existing ticket or an existing client contact
|
// Couldn't match this email to an existing ticket or an existing client contact
|
||||||
// Checking to see if the sender domain matches a client website
|
// Checking to see if the sender domain matches a client website
|
||||||
|
|
||||||
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM clients WHERE client_website = '$from_domain' LIMIT 1"));
|
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_name = '$from_domain' LIMIT 1"));
|
||||||
|
|
||||||
if ($row && $from_domain == $row['client_website']) {
|
if ($row && $from_domain == $row['domain_name']) {
|
||||||
|
|
||||||
// We found a match - create a contact under this client and raise a ticket for them
|
// We found a match - create a contact under this client and raise a ticket for them
|
||||||
|
|
||||||
// Client details
|
// Client details
|
||||||
$client_id = intval($row['client_id']);
|
$client_id = intval($row['domain_client_id']);
|
||||||
|
|
||||||
// Contact details
|
// Contact details
|
||||||
$password = password_hash(randomString(), PASSWORD_DEFAULT);
|
$password = password_hash(randomString(), PASSWORD_DEFAULT);
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ function sendSingleEmail($config_smtp_host, $config_smtp_username, $config_smtp_
|
|||||||
$smtp_auth = true;
|
$smtp_auth = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try {
|
||||||
// Mail Server Settings
|
// Mail Server Settings
|
||||||
$mail->CharSet = "UTF-8"; // Specify UTF-8 charset to ensure symbols ($/£) load correctly
|
$mail->CharSet = "UTF-8"; // Specify UTF-8 charset to ensure symbols ($/£) load correctly
|
||||||
$mail->SMTPDebug = 0; // No Debugging
|
$mail->SMTPDebug = 0; // No Debugging
|
||||||
@@ -712,13 +712,13 @@ function shortenClient($client) {
|
|||||||
|
|
||||||
// Break into words.
|
// Break into words.
|
||||||
$words = explode(' ', trim($cleaned));
|
$words = explode(' ', trim($cleaned));
|
||||||
|
|
||||||
$shortened = '';
|
$shortened = '';
|
||||||
|
|
||||||
// If there's only one word.
|
// If there's only one word.
|
||||||
if (count($words) == 1) {
|
if (count($words) == 1) {
|
||||||
$word = $words[0];
|
$word = $words[0];
|
||||||
|
|
||||||
if (strlen($word) <= 3) {
|
if (strlen($word) <= 3) {
|
||||||
return strtoupper($word);
|
return strtoupper($word);
|
||||||
}
|
}
|
||||||
@@ -753,22 +753,22 @@ function roundToNearest15($time) {
|
|||||||
|
|
||||||
// Extract hours, minutes, and seconds from the matched time string
|
// Extract hours, minutes, and seconds from the matched time string
|
||||||
list(, $hours, $minutes, $seconds) = $matches;
|
list(, $hours, $minutes, $seconds) = $matches;
|
||||||
|
|
||||||
// Convert everything to seconds for easier calculation
|
// Convert everything to seconds for easier calculation
|
||||||
$totalSeconds = ($hours * 3600) + ($minutes * 60) + $seconds;
|
$totalSeconds = ($hours * 3600) + ($minutes * 60) + $seconds;
|
||||||
|
|
||||||
// Calculate the remainder when divided by 900 seconds (15 minutes)
|
// Calculate the remainder when divided by 900 seconds (15 minutes)
|
||||||
$remainder = $totalSeconds % 900;
|
$remainder = $totalSeconds % 900;
|
||||||
|
|
||||||
if ($remainder > 450) { // If remainder is more than 7.5 minutes (450 seconds), round up
|
if ($remainder > 450) { // If remainder is more than 7.5 minutes (450 seconds), round up
|
||||||
$totalSeconds += (900 - $remainder);
|
$totalSeconds += (900 - $remainder);
|
||||||
} else { // Else round down
|
} else { // Else round down
|
||||||
$totalSeconds -= $remainder;
|
$totalSeconds -= $remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert total seconds to decimal hours
|
// Convert total seconds to decimal hours
|
||||||
$decimalHours = $totalSeconds / 3600;
|
$decimalHours = $totalSeconds / 3600;
|
||||||
|
|
||||||
// Return the decimal hours
|
// Return the decimal hours
|
||||||
return number_format($decimalHours, 2);
|
return number_format($decimalHours, 2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ $session_contact_initials = initials($session_contact_name);
|
|||||||
$session_contact_title = sanitizeInput($contact['contact_title']);
|
$session_contact_title = sanitizeInput($contact['contact_title']);
|
||||||
$session_contact_email = sanitizeInput($contact['contact_email']);
|
$session_contact_email = sanitizeInput($contact['contact_email']);
|
||||||
$session_contact_photo = sanitizeInput($contact['contact_photo']);
|
$session_contact_photo = sanitizeInput($contact['contact_photo']);
|
||||||
|
$session_contact_pin = sanitizeInput($contact['contact_pin']);
|
||||||
$session_contact_primary = intval($contact['contact_primary']);
|
$session_contact_primary = intval($contact['contact_primary']);
|
||||||
|
|
||||||
$session_contact_is_technical_contact = false;
|
$session_contact_is_technical_contact = false;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ require_once('inc_portal.php');
|
|||||||
|
|
||||||
<p>Name: <?php echo $session_contact_name ?></p>
|
<p>Name: <?php echo $session_contact_name ?></p>
|
||||||
<p>Email: <?php echo $session_contact_email ?></p>
|
<p>Email: <?php echo $session_contact_email ?></p>
|
||||||
|
<p>PIN: <?php echo $session_contact_pin ?></p>
|
||||||
<p>Client: <?php echo $session_client_name ?></p>
|
<p>Client: <?php echo $session_client_name ?></p>
|
||||||
<br>
|
<br>
|
||||||
<p>Client Primary Contact: <?php if ($session_contact_primary == 1) {echo "Yes"; } else {echo "No";} ?></p>
|
<p>Client Primary Contact: <?php if ($session_contact_primary == 1) {echo "Yes"; } else {echo "No";} ?></p>
|
||||||
@@ -35,7 +36,7 @@ require_once('inc_portal.php');
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
|
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<input type="password" class="form-control" minlength="6" required data-toggle="password" name="new_password" placeholder="Leave blank for no change" autocomplete="new-password">
|
<input type="password" class="form-control" minlength="8" required data-toggle="password" name="new_password" placeholder="Leave blank for no change" autocomplete="new-password">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" name="edit_profile" class="btn btn-primary text-bold mt-3"><i class="fas fa-check mr-2"></i>Save password</button>
|
<button type="submit" name="edit_profile" class="btn btn-primary text-bold mt-3"><i class="fas fa-check mr-2"></i>Save password</button>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ if (isset($_POST['add_contact'])) {
|
|||||||
// Set a random password
|
// Set a random password
|
||||||
$password_hash = password_hash(randomString(), PASSWORD_DEFAULT);
|
$password_hash = password_hash(randomString(), PASSWORD_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file_exists("uploads/clients/$client_id")) {
|
if (!file_exists("uploads/clients/$client_id")) {
|
||||||
mkdir("uploads/clients/$client_id");
|
mkdir("uploads/clients/$client_id");
|
||||||
}
|
}
|
||||||
@@ -68,6 +68,7 @@ if (isset($_POST['edit_contact'])) {
|
|||||||
require_once('post/contact_model.php');
|
require_once('post/contact_model.php');
|
||||||
|
|
||||||
$contact_id = intval($_POST['contact_id']);
|
$contact_id = intval($_POST['contact_id']);
|
||||||
|
$send_email = intval($_POST['send_email']);
|
||||||
|
|
||||||
// Get Exisiting Contact Photo
|
// Get Exisiting Contact Photo
|
||||||
$sql = mysqli_query($mysqli,"SELECT contact_photo FROM contacts WHERE contact_id = $contact_id");
|
$sql = mysqli_query($mysqli,"SELECT contact_photo FROM contacts WHERE contact_id = $contact_id");
|
||||||
@@ -93,7 +94,7 @@ if (isset($_POST['edit_contact'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send contact a welcome e-mail, if specified
|
// Send contact a welcome e-mail, if specified
|
||||||
if (isset($_POST['send_email']) && !empty($auth_method) && !empty($config_smtp_host)) {
|
if ($send_email && !empty($auth_method) && !empty($config_smtp_host)) {
|
||||||
|
|
||||||
// Un-sanitizied used in body of email
|
// Un-sanitizied used in body of email
|
||||||
$contact_name = $_POST['name'];
|
$contact_name = $_POST['name'];
|
||||||
@@ -102,14 +103,18 @@ if (isset($_POST['edit_contact'])) {
|
|||||||
$config_ticket_from_email_escaped = sanitizeInput($config_ticket_from_email);
|
$config_ticket_from_email_escaped = sanitizeInput($config_ticket_from_email);
|
||||||
$config_ticket_from_name_escaped = sanitizeInput($config_ticket_from_name);
|
$config_ticket_from_name_escaped = sanitizeInput($config_ticket_from_name);
|
||||||
|
|
||||||
|
// Authentication info (azure, reset password, or tech-provided temporary password)
|
||||||
|
|
||||||
if ($auth_method == 'azure') {
|
if ($auth_method == 'azure') {
|
||||||
$password_info = "Login with your Microsoft (Azure AD) account.";
|
$password_info = "Login with your Microsoft (Azure AD) account.";
|
||||||
|
} elseif (empty($_POST['contact_password'])) {
|
||||||
|
$password_info = "Request a password reset at https://$config_base_url/portal/login_reset.php";
|
||||||
} else {
|
} else {
|
||||||
$password_info = $_POST['contact_password'];
|
$password_info = $_POST['contact_password'] . " -- Please change on first login";
|
||||||
}
|
}
|
||||||
|
|
||||||
$subject = sanitizeInput("Your new $session_company_name ITFlow account");
|
$subject = sanitizeInput("Your new $session_company_name support portal account");
|
||||||
$body = mysqli_real_escape_string($mysqli, "Hello, $contact_name<br><br>An ITFlow account has been set up for you. <br><br>Username: $email <br>Password: $password_info<br><br>Login URL: https://$config_base_url/portal/<br><br>~<br>$session_company_name<br>Support Department<br>$config_ticket_from_email");
|
$body = mysqli_real_escape_string($mysqli, "Hello, $contact_name<br><br>$session_company_name has created a support portal account for you. <br><br>Username: $email<br>Password: $password_info<br><br>Login URL: https://$config_base_url/portal/<br><br>~<br>$session_company_name<br>Support Department<br>$config_ticket_from_email");
|
||||||
|
|
||||||
// Queue Mail
|
// Queue Mail
|
||||||
mysqli_query($mysqli, "INSERT INTO email_queue SET email_recipient = '$email', email_recipient_name = '$name', email_from = '$config_ticket_from_email_escaped', email_from_name = '$config_ticket_from_name_escaped', email_subject = '$subject', email_content = '$body'");
|
mysqli_query($mysqli, "INSERT INTO email_queue SET email_recipient = '$email', email_recipient_name = '$name', email_from = '$config_ticket_from_email_escaped', email_from_name = '$config_ticket_from_name_escaped', email_subject = '$subject', email_content = '$body'");
|
||||||
|
|||||||
@@ -280,3 +280,47 @@ if (isset($_POST['export_users_csv'])) {
|
|||||||
exit;
|
exit;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($_POST['ir_reset_user_password'])) {
|
||||||
|
|
||||||
|
// Incident response: allow mass reset of agent passwords
|
||||||
|
|
||||||
|
validateAdminRole();
|
||||||
|
|
||||||
|
validateCSRFToken($_POST['csrf_token']);
|
||||||
|
|
||||||
|
// Confirm logged-in user password, for security
|
||||||
|
$admin_password = $_POST['admin_password'];
|
||||||
|
$sql = mysqli_query($mysqli, "SELECT * FROM users WHERE user_id = $session_user_id");
|
||||||
|
$userRow = mysqli_fetch_array($sql);
|
||||||
|
if (!password_verify($admin_password, $userRow['user_password'])) {
|
||||||
|
$_SESSION['alert_type'] = "error";
|
||||||
|
$_SESSION['alert_message'] = "Incorrect password.";
|
||||||
|
header("Location: " . $_SERVER["HTTP_REFERER"]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get agents/users, other than the current user
|
||||||
|
$sql_users = mysqli_query($mysqli, "SELECT * FROM users WHERE (user_archived_at IS NULL AND user_id != $session_user_id)");
|
||||||
|
|
||||||
|
// Reset passwords
|
||||||
|
while ($row = mysqli_fetch_array($sql_users)) {
|
||||||
|
$user_id = intval($row['user_id']);
|
||||||
|
$user_email = sanitizeInput($row['user_email']);
|
||||||
|
$new_password = randomString();
|
||||||
|
$user_specific_encryption_ciphertext = encryptUserSpecificKey(trim($new_password));
|
||||||
|
|
||||||
|
echo $user_email . " -- " . $new_password; // Show
|
||||||
|
$new_password = password_hash($new_password, PASSWORD_DEFAULT);
|
||||||
|
|
||||||
|
mysqli_query($mysqli, "UPDATE users SET user_password = '$new_password', user_specific_encryption_ciphertext = '$user_specific_encryption_ciphertext' WHERE user_id = $user_id");
|
||||||
|
|
||||||
|
echo "<br><br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logging
|
||||||
|
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'User', log_action = 'Modify', log_description = '$session_name reset ALL user passwords', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_user_id = $session_user_id");
|
||||||
|
|
||||||
|
exit; // Stay on the plain text password page
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ require_once("inc_all_settings.php"); ?>
|
|||||||
<form action="post.php" method="post" autocomplete="off">
|
<form action="post.php" method="post" autocomplete="off">
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Telemery</label>
|
<label>Telemetry</label>
|
||||||
|
<p><i>If you can't measure it, you can't improve it. Please consider turning on telemetry data to provide valuable insights on how you're using ITFlow - so we can improve it for everyone. </i></p>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-broadcast-tower"></i></span>
|
<span class="input-group-text"><i class="fa fa-fw fa-broadcast-tower"></i></span>
|
||||||
@@ -23,12 +24,12 @@ require_once("inc_all_settings.php"); ?>
|
|||||||
<option <?php if ($config_telemetry == "2") { echo "selected"; } ?> value = "2">Detailed</option>
|
<option <?php if ($config_telemetry == "2") { echo "selected"; } ?> value = "2">Detailed</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<small class="form-text"><a href="https://docs.itflow.org/telemetry" target="_blank">Click Here for additional details regarding the information we gather <i class="fas fa-external-link-alt"></i></a></small>
|
<small class="form-text">We respect your privacy. <a href="https://docs.itflow.org/telemetry" target="_blank">Click here <i class="fas fa-external-link-alt"></i></a> for additional details regarding the information we gather. </small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Comments</label>
|
<label>Comments</label>
|
||||||
<textarea class="form-control" rows="4" name="comments" placeholder="Any Comments to send before hitting Send Telemetry Data?"></textarea>
|
<textarea class="form-control" rows="4" name="comments" placeholder="Any one-off comments to send before hitting Send Telemetry Data?"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|||||||
73
ticket.php
73
ticket.php
@@ -326,8 +326,9 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if(!empty($contact_email)){ ?>
|
|
||||||
|
<?php if(!empty($contact_email && $contact_email !== $session_email)){ ?>
|
||||||
|
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="custom-control custom-checkbox">
|
||||||
@@ -483,13 +484,13 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
<!-- Contact card -->
|
<!-- Contact card -->
|
||||||
<div class="card card-body card-outline card-dark mb-3">
|
<div class="card card-body card-outline card-dark mb-3">
|
||||||
<h4 class="text-secondary">Contact</h4>
|
<h4 class="text-secondary">Contact</h4>
|
||||||
|
|
||||||
<?php if (!empty($contact_id)) { ?>
|
<?php if (!empty($contact_id)) { ?>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<i class="fa fa-fw fa-user text-secondary ml-1 mr-2"></i><a href="#" data-toggle="modal" data-target="#editTicketContactModal<?php echo $ticket_id; ?>"><strong><?php echo $contact_name; ?></strong>
|
<i class="fa fa-fw fa-user text-secondary ml-1 mr-2"></i><a href="#" data-toggle="modal" data-target="#editTicketContactModal<?php echo $ticket_id; ?>"><strong><?php echo $contact_name; ?></strong>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
@@ -517,32 +518,31 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
</div>
|
</div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
// Previous tickets
|
||||||
|
$prev_ticket_id = $prev_ticket_subject = $prev_ticket_status = ''; // Default blank
|
||||||
|
|
||||||
$sql_prev_ticket = "SELECT ticket_id, ticket_created_at, ticket_subject, ticket_status, ticket_assigned_to FROM tickets WHERE ticket_contact_id = $contact_id AND ticket_id <> $ticket_id ORDER BY ticket_id DESC LIMIT 1";
|
$sql_prev_ticket = "SELECT ticket_id, ticket_created_at, ticket_subject, ticket_status, ticket_assigned_to FROM tickets WHERE ticket_contact_id = $contact_id AND ticket_id <> $ticket_id ORDER BY ticket_id DESC LIMIT 1";
|
||||||
$row = mysqli_fetch_assoc(mysqli_query($mysqli, $sql_prev_ticket));
|
$prev_ticket_row = mysqli_fetch_assoc(mysqli_query($mysqli, $sql_prev_ticket));
|
||||||
|
|
||||||
$prev_ticket_id = intval($row['ticket_id']);
|
if ($prev_ticket_row) {
|
||||||
$prev_ticket_subject = nullable_htmlentities($row['ticket_subject']);
|
$prev_ticket_id = intval($prev_ticket_row['ticket_id']);
|
||||||
$prev_ticket_status = nullable_htmlentities($row['ticket_status']);
|
$prev_ticket_subject = nullable_htmlentities($prev_ticket_row['ticket_subject']);
|
||||||
?>
|
$prev_ticket_status = nullable_htmlentities($prev_ticket_row['ticket_status']);
|
||||||
|
?>
|
||||||
|
|
||||||
<div>
|
<hr>
|
||||||
<i class="fa fa-fw fa-history text-secondary ml-1 mr-2"></i><b>Previous ticket:</b>
|
<div>
|
||||||
<a href="ticket.php?ticket_id=<?php echo $prev_ticket_id; ?>"><?php echo $prev_ticket_subject; ?></a>
|
<i class="fa fa-fw fa-history text-secondary ml-1 mr-2"></i><b>Previous ticket:</b>
|
||||||
</div>
|
<a href="ticket.php?ticket_id=<?php echo $prev_ticket_id; ?>"><?php echo $prev_ticket_subject; ?></a>
|
||||||
<div class="mt-1">
|
</div>
|
||||||
<?php if ($prev_ticket_status == 'Open') { ?>
|
<div class="mt-1">
|
||||||
<i class="fa fa-fw fa-hourglass-start text-secondary ml-1 mr-2"></i><strong>Status:</strong>
|
|
||||||
<span class="text-danger"><?php echo $prev_ticket_status; ?></span>
|
|
||||||
<?php } else { ?>
|
|
||||||
<i class="fa fa-fw fa-hourglass-start text-secondary ml-1 mr-2"></i><strong>Status:</strong>
|
<i class="fa fa-fw fa-hourglass-start text-secondary ml-1 mr-2"></i><strong>Status:</strong>
|
||||||
<span class="text-success"><?php echo $prev_ticket_status; ?></span>
|
<span class="text-success"><?php echo $prev_ticket_status; ?></span>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php } else { ?>
|
<?php } else { ?>
|
||||||
<div>
|
<div>
|
||||||
<a href="#" data-toggle="modal" data-target="#editTicketContactModal<?php echo $ticket_id; ?>"><i class="fa fa-fw fa-plus mr-2"></i>Add a Contact</a>
|
<a href="#" data-toggle="modal" data-target="#editTicketContactModal<?php echo $ticket_id; ?>"><i class="fa fa-fw fa-plus mr-2"></i>Add a Contact</a>
|
||||||
@@ -565,12 +565,12 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
$sql_ticket_watchers = mysqli_query($mysqli, "SELECT * FROM ticket_watchers WHERE watcher_ticket_id = $ticket_id ORDER BY watcher_email DESC");
|
$sql_ticket_watchers = mysqli_query($mysqli, "SELECT * FROM ticket_watchers WHERE watcher_ticket_id = $ticket_id ORDER BY watcher_email DESC");
|
||||||
while ($ticket_watcher_row = mysqli_fetch_array($sql_ticket_watchers)) {
|
while ($ticket_watcher_row = mysqli_fetch_array($sql_ticket_watchers)) {
|
||||||
$ticket_watcher_email = nullable_htmlentities($ticket_watcher_row['watcher_email']);
|
$ticket_watcher_email = nullable_htmlentities($ticket_watcher_row['watcher_email']);
|
||||||
?>
|
?>
|
||||||
<div class='mt-1'>
|
<div class='mt-1'>
|
||||||
<i class="fa fa-fw fa-eye text-secondary ml-1 mr-2"></i><?php echo $ticket_watcher_email; ?>
|
<i class="fa fa-fw fa-eye text-secondary ml-1 mr-2"></i><?php echo $ticket_watcher_email; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- End Ticket watchers card -->
|
<!-- End Ticket watchers card -->
|
||||||
|
|
||||||
@@ -586,14 +586,15 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<i class="fa fa-fw fa-history text-secondary ml-1 mr-2"></i>Updated: <strong><?php echo $ticket_updated_at; ?></strong>
|
<i class="fa fa-fw fa-history text-secondary ml-1 mr-2"></i>Updated: <strong><?php echo $ticket_updated_at; ?></strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
if ($ticket_status == "Closed") {
|
if ($ticket_status == "Closed") {
|
||||||
$sql_closed_by = mysqli_query($mysqli, "SELECT * FROM tickets, users WHERE ticket_closed_by = user_id");
|
$sql_closed_by = mysqli_query($mysqli, "SELECT * FROM tickets, users WHERE ticket_closed_by = user_id");
|
||||||
$row = mysqli_fetch_array($sql_closed_by);
|
$row = mysqli_fetch_array($sql_closed_by);
|
||||||
$ticket_closed_by_display = nullable_htmlentities($row['user_name']);
|
$ticket_closed_by_display = nullable_htmlentities($row['user_name']);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
||||||
<div class="mt-1">
|
<div class="mt-1">
|
||||||
<i class="fa fa-fw fa-user text-secondary ml-1 mr-2"></i>Closed by: <?php echo ucwords($ticket_closed_by_display); ?>
|
<i class="fa fa-fw fa-user text-secondary ml-1 mr-2"></i>Closed by: <?php echo ucwords($ticket_closed_by_display); ?>
|
||||||
</div>
|
</div>
|
||||||
@@ -601,7 +602,7 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
<i class="fa fa-fw fa-comment-dots text-secondary ml-1 mr-2"></i>Feedback: <?php echo $ticket_feedback; ?>
|
<i class="fa fa-fw fa-comment-dots text-secondary ml-1 mr-2"></i>Feedback: <?php echo $ticket_feedback; ?>
|
||||||
</div>
|
</div>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
<?php if (!empty($ticket_total_reply_time)) { ?>
|
<?php if (!empty($ticket_total_reply_time)) { ?>
|
||||||
<div class="mt-1">
|
<div class="mt-1">
|
||||||
<i class="far fa-fw fa-clock text-secondary ml-1 mr-2"></i>Total time worked: <?php echo $ticket_total_reply_time; ?>
|
<i class="far fa-fw fa-clock text-secondary ml-1 mr-2"></i>Total time worked: <?php echo $ticket_total_reply_time; ?>
|
||||||
@@ -613,13 +614,13 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
<!-- Asset card -->
|
<!-- Asset card -->
|
||||||
<div class="card card-body card-outline card-dark mb-3">
|
<div class="card card-body card-outline card-dark mb-3">
|
||||||
<h4 class="text-secondary">Asset</h4>
|
<h4 class="text-secondary">Asset</h4>
|
||||||
|
|
||||||
<?php if ($asset_id == 0) { ?>
|
<?php if ($asset_id == 0) { ?>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<a href="#" data-toggle="modal" data-target="#editTicketAssetModal<?php echo $ticket_id; ?>"><i class="fa fa-fw fa-plus mr-2"></i>Add an Asset</a>
|
<a href="#" data-toggle="modal" data-target="#editTicketAssetModal<?php echo $ticket_id; ?>"><i class="fa fa-fw fa-plus mr-2"></i>Add an Asset</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php } else { ?>
|
<?php } else { ?>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -686,7 +687,7 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
<i class="fas fa-fw fa-ticket-alt"></i>
|
<i class="fas fa-fw fa-ticket-alt"></i>
|
||||||
Ticket: <a href="ticket.php?ticket_id=<?php echo $service_ticket_id; ?>"><?php echo "$service_ticket_prefix$service_ticket_number" ?></a> <?php echo "on $service_ticket_created_at - <b>$service_ticket_subject</b> ($service_ticket_status)"; ?>
|
Ticket: <a href="ticket.php?ticket_id=<?php echo $service_ticket_id; ?>"><?php echo "$service_ticket_prefix$service_ticket_number" ?></a> <?php echo "on $service_ticket_created_at - <b>$service_ticket_subject</b> ($service_ticket_status)"; ?>
|
||||||
</p>
|
</p>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
@@ -699,13 +700,13 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php } // End Ticket asset Count ?>
|
<?php } // End Ticket asset Count ?>
|
||||||
|
|
||||||
<?php } // End if asset_id == 0 else ?>
|
<?php } // End if asset_id == 0 else ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- End Asset card -->
|
<!-- End Asset card -->
|
||||||
|
|
||||||
<!-- Vendor card -->
|
<!-- Vendor card -->
|
||||||
<div class="card card-body card-outline card-dark mb-3">
|
<div class="card card-body card-outline card-dark mb-3">
|
||||||
<h4 class="text-secondary">Vendor</h4>
|
<h4 class="text-secondary">Vendor</h4>
|
||||||
<?php if (empty($vendor_id)) { ?>
|
<?php if (empty($vendor_id)) { ?>
|
||||||
@@ -784,14 +785,14 @@ if (isset($_GET['ticket_id'])) {
|
|||||||
<i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Ticket
|
<i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Ticket
|
||||||
</a>
|
</a>
|
||||||
<?php }
|
<?php }
|
||||||
|
|
||||||
if ($ticket_status !== "Closed") { ?>
|
if ($ticket_status !== "Closed") { ?>
|
||||||
<a href="post.php?close_ticket=<?php echo $ticket_id; ?>" class="btn btn-secondary btn-block confirm-link">
|
<a href="post.php?close_ticket=<?php echo $ticket_id; ?>" class="btn btn-secondary btn-block confirm-link">
|
||||||
<i class="fas fa-fw fa-gavel mr-2"></i>Close Ticket
|
<i class="fas fa-fw fa-gavel mr-2"></i>Close Ticket
|
||||||
</a>
|
</a>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
31
user_all_reset_password_modal.php
Normal file
31
user_all_reset_password_modal.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<div class="modal" id="resetAllUserPassModal" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-4" style="text-align: center;">
|
||||||
|
<i class="far fas fa-10x fa-skull-crossbones text-danger mb-3 mt-3"></i>
|
||||||
|
<h2>Incident Response: Agent Password Reset</h2>
|
||||||
|
<br>
|
||||||
|
<div class="alert alert-danger" role="alert">
|
||||||
|
<b>This is a potentially destructive function.<br>It is intended to be used as part of a potential security incident.</b>
|
||||||
|
</div>
|
||||||
|
<h6 class="mb-4 text-secondary"><b>All ITFlow agent passwords will be reset and shown to you </b><i>(except yours - change yours first!)</i>.<br/><br/>You should communicate temporary passwords to agents out of band (e.g. via a phone call) and require they are changed ASAP.</h6>
|
||||||
|
<form action="post.php" method="POST">
|
||||||
|
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||||
|
<div class="row col-7 offset-4">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<input type="password" class="form-control" placeholder="Enter your account password to continue" name="admin_password" autocomplete="new-password" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<button class="btn btn-danger" type="submit" name="ir_reset_user_password"><i class="fas fa-fw fa-key mr-2"></i>Reset passwords</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn btn-outline-secondary btn-lg px-5 mr-4" data-dismiss="modal">Cancel</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -33,6 +33,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
||||||
<div class="dropdown-menu">
|
<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>-->
|
<!--<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) { ?>
|
||||||
|
<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 } ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -197,4 +201,5 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
|||||||
require_once("user_add_modal.php");
|
require_once("user_add_modal.php");
|
||||||
require_once("user_invite_modal.php");
|
require_once("user_invite_modal.php");
|
||||||
require_once("user_export_modal.php");
|
require_once("user_export_modal.php");
|
||||||
|
require_once("user_all_reset_password_modal.php");
|
||||||
require_once("footer.php");
|
require_once("footer.php");
|
||||||
|
|||||||
Reference in New Issue
Block a user