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
10 changed files with 127 additions and 110 deletions

View File

@@ -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.
-- --

View File

@@ -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

View File

@@ -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 :)
-- --

View File

@@ -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! :)

View File

@@ -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

View File

@@ -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.

View File

@@ -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>

View File

@@ -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);

View File

@@ -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

View File

@@ -326,6 +326,7 @@ if (isset($_GET['ticket_id'])) {
</div> </div>
</div> </div>
<?php if(!empty($contact_email && $contact_email !== $session_email)){ ?> <?php if(!empty($contact_email && $contact_email !== $session_email)){ ?>
<div class="col-md-2"> <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> <label class="custom-control-label" for="ticket_reply_type_checkbox">Email contact<br><small class="text-secondary">(Public Update)</small></label>
</div> </div>
</div> </div>
</div>
<?php } ?> <?php } ?>
@@ -487,9 +487,9 @@ if (isset($_GET['ticket_id'])) {
<?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,27 +517,26 @@ 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 } ?>
@@ -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"); $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>
@@ -594,6 +593,7 @@ if (isset($_GET['ticket_id'])) {
$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>
@@ -686,7 +686,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>