Merge branch 'master' into ticket-update-type-email-match

This commit is contained in:
Johnny 2023-10-08 19:54:14 -04:00 committed by GitHub
commit edf6e18dc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 127 additions and 110 deletions

View File

@ -1,35 +1,22 @@
---
name: Bug report
about: Something not working quite right? Create a report to help us improve!
title: ''
labels: ''
about: Please report bugs on the Forum @ https://forum.itflow.org/t/bug
title: 'Please report bugs on the Forum'
labels: Support
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
We're now using GitHub Issues exclusively for development.
-
**Can you reproduce this on the demo at demo.itflow.org**
Yes/No/NA
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.
**Are you on the latest available version of ITFlow, with an up-to-date database structure?**
Yes/No
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.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
4. See error
Thanks,
**Expected behavior**
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.
The ITFlow team :)
--

View File

@ -1,16 +1,25 @@
---
name: Feature request
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
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

View File

@ -1,17 +1,24 @@
---
name: Support
about: Please visit the Forum or Discord for support
title: ''
about: Please request support on the Forum @ https://forum.itflow.org/t/support
title: 'Please visit the Forum for support'
labels: Support
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 :)
--

View File

@ -16,9 +16,9 @@ jobs:
issue-message: |
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: |
Hello & Welcome! :)

View File

@ -33,6 +33,8 @@
<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://github.com/itflow-org/itflow/security/policy">Security</a>
</p>
</div>
@ -83,20 +85,28 @@
* FullCalendar.io
<!-- 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
sudo apt install git apache2 php libapache2-mod-php php-intl php-imap php-mailparse php-mysqli php-curl mariadb-server
```
2. Clone the repo
```sh
git clone https://github.com/itflow-org/itflow.git /var/www/html
```
3. Create a MariaDB Database
4. Point your browser to your HTTPS web server to begin setup
<!-- EASY INSTALL -->
### Installation via Script (Recommended Method)
**Requirements**
- Clean Install of Debian 12 or Ubuntu 22.04
- A public IP Address
- Ports 80 (HTTP) and 443 (HTTPS) TCP accessible from the outside in
- A Fully Qualified Domain Name pointing to the public IP Address example itflow.example.com, NOT itflow.xyz.example.com
**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 -->
## Key Features

View File

@ -1,5 +1,9 @@
# Security Policy
## **Please do NOT report security concerns/vulnerabilities publicly (Github issues/forum)**
---
## In Beta
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 |
| ------- | ------------------ |
| Beta | :white_check_mark: |
| 1.0 | Yet to be released |
## Reporting a Vulnerability
**<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.
## Reporting a Vulnerability via GitHub Security Advisories
**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.

View File

@ -72,6 +72,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$domain_webhost = intval($row['domain_webhost']);
$domain_expire = nullable_htmlentities($row['domain_expire']);
$domain_registrar_name = nullable_htmlentities($row['vendor_name']);
$domain_created_at = nullable_htmlentities($row['domain_created_at']);
if (empty($domain_registrar_name)) {
$domain_registrar_name = "-";
}
@ -82,7 +83,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if ($row) {
$domain_webhost_name = nullable_htmlentities($row['vendor_name']);
}
$domain_created_at = nullable_htmlentities($row['domain_created_at']);
?>
<tr>

View File

@ -94,9 +94,9 @@ function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date
// Prep ticket details
$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);
// 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
if ($config_ticket_client_general_notifications == 1) {
$email_subject = "Ticket created - [$config_ticket_prefix$ticket_number] - $subject";
$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";
// Insert email into queue (first, escape vars)
$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(
$config_smtp_host,
$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
);
$subject_escaped = mysqli_escape_string($mysqli, "Ticket created - [$config_ticket_prefix$ticket_number] - $subject");
$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");
if ($mail !== true) {
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'");
}
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'");
}
@ -173,8 +162,10 @@ function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date
$client_row = mysqli_fetch_array($client_sql);
$client_name = sanitizeInput($client_row['client_name']);
$details = removeEmoji($message);
$email_subject = "ITFlow - New Ticket - $client_name: $subject";
// TODO: Fix Emojis and HTML opening tags sometimes breaking this "forwarding"
$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";
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')))));
$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');
// 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)
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
// 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
// Client details
$client_id = intval($row['client_id']);
$client_id = intval($row['domain_client_id']);
// Contact details
$password = password_hash(randomString(), PASSWORD_DEFAULT);

View File

@ -516,7 +516,7 @@ function sendSingleEmail($config_smtp_host, $config_smtp_username, $config_smtp_
$smtp_auth = true;
}
try{
try {
// Mail Server Settings
$mail->CharSet = "UTF-8"; // Specify UTF-8 charset to ensure symbols ($/£) load correctly
$mail->SMTPDebug = 0; // No Debugging
@ -712,13 +712,13 @@ function shortenClient($client) {
// Break into words.
$words = explode(' ', trim($cleaned));
$shortened = '';
// If there's only one word.
if (count($words) == 1) {
$word = $words[0];
if (strlen($word) <= 3) {
return strtoupper($word);
}
@ -753,22 +753,22 @@ function roundToNearest15($time) {
// Extract hours, minutes, and seconds from the matched time string
list(, $hours, $minutes, $seconds) = $matches;
// Convert everything to seconds for easier calculation
$totalSeconds = ($hours * 3600) + ($minutes * 60) + $seconds;
// Calculate the remainder when divided by 900 seconds (15 minutes)
$remainder = $totalSeconds % 900;
if ($remainder > 450) { // If remainder is more than 7.5 minutes (450 seconds), round up
$totalSeconds += (900 - $remainder);
} else { // Else round down
$totalSeconds -= $remainder;
}
// Convert total seconds to decimal hours
$decimalHours = $totalSeconds / 3600;
// Return the decimal hours
return number_format($decimalHours, 2);
}
}

View File

@ -326,6 +326,7 @@ if (isset($_GET['ticket_id'])) {
</div>
</div>
<?php if(!empty($contact_email && $contact_email !== $session_email)){ ?>
<div class="col-md-2">
@ -335,7 +336,6 @@ if (isset($_GET['ticket_id'])) {
<label class="custom-control-label" for="ticket_reply_type_checkbox">Email contact<br><small class="text-secondary">(Public Update)</small></label>
</div>
</div>
</div>
<?php } ?>
@ -487,9 +487,9 @@ if (isset($_GET['ticket_id'])) {
<?php if (!empty($contact_id)) { ?>
<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>
</div>
</div>
<?php
@ -517,27 +517,26 @@ if (isset($_GET['ticket_id'])) {
</div>
<?php } ?>
<hr>
<?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";
$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']);
$prev_ticket_subject = nullable_htmlentities($row['ticket_subject']);
$prev_ticket_status = nullable_htmlentities($row['ticket_status']);
?>
if ($prev_ticket_row) {
$prev_ticket_id = intval($prev_ticket_row['ticket_id']);
$prev_ticket_subject = nullable_htmlentities($prev_ticket_row['ticket_subject']);
$prev_ticket_status = nullable_htmlentities($prev_ticket_row['ticket_status']);
?>
<div>
<i class="fa fa-fw fa-history text-secondary ml-1 mr-2"></i><b>Previous ticket:</b>
<a href="ticket.php?ticket_id=<?php echo $prev_ticket_id; ?>"><?php echo $prev_ticket_subject; ?></a>
</div>
<div class="mt-1">
<?php if ($prev_ticket_status == 'Open') { ?>
<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 { ?>
<hr>
<div>
<i class="fa fa-fw fa-history text-secondary ml-1 mr-2"></i><b>Previous ticket:</b>
<a href="ticket.php?ticket_id=<?php echo $prev_ticket_id; ?>"><?php echo $prev_ticket_subject; ?></a>
</div>
<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-success"><?php echo $prev_ticket_status; ?></span>
<?php } ?>
@ -565,7 +564,7 @@ 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");
while ($ticket_watcher_row = mysqli_fetch_array($sql_ticket_watchers)) {
$ticket_watcher_email = nullable_htmlentities($ticket_watcher_row['watcher_email']);
?>
?>
<div class='mt-1'>
<i class="fa fa-fw fa-eye text-secondary ml-1 mr-2"></i><?php echo $ticket_watcher_email; ?>
</div>
@ -594,6 +593,7 @@ if (isset($_GET['ticket_id'])) {
$ticket_closed_by_display = nullable_htmlentities($row['user_name']);
?>
<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); ?>
</div>
@ -686,7 +686,7 @@ if (isset($_GET['ticket_id'])) {
<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)"; ?>
</p>
<?php
<?php
}
?>
</div>