From dd4c04945ab02dff7fce637dc17f2896b388e987 Mon Sep 17 00:00:00 2001
From: Georg Lehner
Date: Thu, 6 Jun 2024 15:47:50 +0200
Subject: [PATCH 01/10] Add HELPDESK_ENABLE_ATTACHMENTS setting and make it
show/hide attachment related UI
Default setting is false. This is not backward compatible.
The rationale is: attachments contain most likely sensitive information.
By default they are served without access control. Currently there is
no simple feature to configure access control. To avoid unintentional
disclosure attachments should be an opt in: you have been warned.
---
helpdesk/forms.py | 23 +++++++++---------
helpdesk/settings.py | 5 ++++
.../helpdesk/public_view_ticket.html | 5 ++--
helpdesk/templates/helpdesk/ticket.html | 24 +++++++++++--------
.../templates/helpdesk/ticket_desc_table.html | 4 +++-
5 files changed, 37 insertions(+), 24 deletions(-)
diff --git a/helpdesk/forms.py b/helpdesk/forms.py
index eb77c2e6..3124f281 100644
--- a/helpdesk/forms.py
+++ b/helpdesk/forms.py
@@ -239,17 +239,18 @@ class AbstractTicketForm(CustomFieldMixin, forms.Form):
label=_('Due on'),
)
- attachment = forms.FileField(
- widget=forms.FileInput(attrs={'class': 'form-control-file'}),
- required=False,
- label=_('Attach File'),
- help_text=_('You can attach a file to this ticket. '
- 'Only file types such as plain text (.txt), '
- 'a document (.pdf, .docx, or .odt), '
- 'or screenshot (.png or .jpg) may be uploaded.'),
- validators=[validate_file_extension]
- )
-
+ if helpdesk_settings.HELPDESK_ENABLE_ATTACHMENTS:
+ attachment = forms.FileField(
+ widget=forms.FileInput(attrs={'class': 'form-control-file'}),
+ required=False,
+ label=_('Attach File'),
+ help_text=_('You can attach a file to this ticket. '
+ 'Only file types such as plain text (.txt), '
+ 'a document (.pdf, .docx, or .odt), '
+ 'or screenshot (.png or .jpg) may be uploaded.'),
+ validators=[validate_file_extension]
+ )
+
class Media:
js = ('helpdesk/js/init_due_date.js',
'helpdesk/js/init_datetime_classes.js')
diff --git a/helpdesk/settings.py b/helpdesk/settings.py
index 2235e7d5..6d83ed63 100644
--- a/helpdesk/settings.py
+++ b/helpdesk/settings.py
@@ -56,6 +56,11 @@ HELPDESK_STAFF_VIEW_PROTECTOR = getattr(settings,
'HELPDESK_STAFF_VIEW_PROTECTOR',
lambda _: None)
+# Enable ticket and Email attachments
+HELPDESK_ENABLE_ATTACHMENTS = getattr(settings,
+ 'HELPDESK_ENABLE_ATTACHMENTS',
+ False)
+
# Enable the Dependencies field on ticket view
HELPDESK_ENABLE_DEPENDENCIES_ON_TICKET = getattr(settings,
'HELPDESK_ENABLE_DEPENDENCIES_ON_TICKET',
diff --git a/helpdesk/templates/helpdesk/public_view_ticket.html b/helpdesk/templates/helpdesk/public_view_ticket.html
index 77de5af1..ee36e304 100644
--- a/helpdesk/templates/helpdesk/public_view_ticket.html
+++ b/helpdesk/templates/helpdesk/public_view_ticket.html
@@ -122,7 +122,8 @@
-
+
+{% if helpdesk_settings.HELPDESK_ENABLE_ATTACHMENTS %}
@@ -140,7 +141,7 @@
-
+{% endif %}
diff --git a/helpdesk/templates/helpdesk/ticket.html b/helpdesk/templates/helpdesk/ticket.html
index b61743f7..652988e0 100644
--- a/helpdesk/templates/helpdesk/ticket.html
+++ b/helpdesk/templates/helpdesk/ticket.html
@@ -54,14 +54,16 @@
{% blocktrans with change.field as field and change.old_value as old_value and change.new_value as new_value %}Changed {{ field }} from {{ old_value }} to {{ new_value }}.{% endblocktrans %}
{% if forloop.last %}{% endif %}
{% endfor %}
- {% for attachment in followup.followupattachment_set.all %}{% if forloop.first %}{% trans "Attachments" %}:
{% endif %}
+ {% if helpdesk_settings.HELPDESK_ENABLE_ATTACHMENTS %}
+ {% for attachment in followup.followupattachment_set.all %}{% if forloop.first %}{% trans "Attachments" %}:
{% endif %}
{{ attachment.filename }} ({{ attachment.mime_type }}, {{ attachment.size|filesizeformat }})
- {% if followup.user and request.user == followup.user %}
+ {% if followup.user and request.user == followup.user %}
- {% endif %}
+ {% endif %}
From cc1b125d53ac9653f25c072eb77ab21349e1cc3c Mon Sep 17 00:00:00 2001
From: Georg Lehner
Date: Thu, 6 Jun 2024 15:58:27 +0200
Subject: [PATCH 02/10] Disable email attachment processing and email saving if
attachments are not enabled.
Caution: untested
---
helpdesk/email.py | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/helpdesk/email.py b/helpdesk/email.py
index f0d3a70f..de9aebdc 100644
--- a/helpdesk/email.py
+++ b/helpdesk/email.py
@@ -595,16 +595,17 @@ def create_object_from_email_message(message, ticket_id, payload, files, logger)
logger.info("[%s-%s] %s" % (ticket.queue.slug, ticket.id, ticket.title,))
- try:
- attached = process_attachments(f, files)
- except ValidationError as e:
- logger.error(str(e))
- else:
- for att_file in attached:
- logger.info(
- "Attachment '%s' (with size %s) successfully added to ticket from email.",
- att_file[0], att_file[1].size
- )
+ if helpdesk.settings.HELPDESK_ENABLE_ATTACHMENTS:
+ try:
+ attached = process_attachments(f, files)
+ except ValidationError as e:
+ logger.error(str(e))
+ else:
+ for att_file in attached:
+ logger.info(
+ "Attachment '%s' (with size %s) successfully added to ticket from email.",
+ att_file[0], att_file[1].size
+ )
context = safe_template_context(ticket)
@@ -984,7 +985,7 @@ def extract_email_metadata(message: str,
filtered_body, full_body = extract_email_message_content(message_obj, files, include_chained_msgs)
# If the base part is not a multipart then it will have already been processed as the vbody content so
# no need to process attachments
- if "multipart" == message_obj.get_content_maintype():
+ if "multipart" == message_obj.get_content_maintype() and helpdesk.settings.HELPDESK_ENABLE_ATTACHMENTS:
# Find and attach all other parts or part contents as attachments
counter, content_parts_excluded = extract_attachments(message_obj, files, logger)
if not content_parts_excluded:
@@ -994,7 +995,8 @@ def extract_email_metadata(message: str,
Verify that there were no text/* parts containing message content.")
if logger.isEnabledFor(logging.DEBUG):
logger.debug("Email parsed and %s attachments were found and attached.", counter)
- add_file_if_always_save_incoming_email_message(files, message)
+ if helpdesk.settings.HELPDESK_ENABLE_ATTACHMENTS:
+ add_file_if_always_save_incoming_email_message(files, message)
smtp_priority = message_obj.get('priority', '')
smtp_importance = message_obj.get('importance', '')
From 2d5c350f00bcf54684c2fdc5da9215f074d5cea4 Mon Sep 17 00:00:00 2001
From: Georg Lehner
Date: Thu, 6 Jun 2024 16:42:13 +0200
Subject: [PATCH 03/10] Add documentation for the HELPDESK_ENABLE_ATTACHMENTS
setting
---
docs/settings.rst | 31 ++++++++++++++++++++++---------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/docs/settings.rst b/docs/settings.rst
index 6299a9b7..ea1529b7 100644
--- a/docs/settings.rst
+++ b/docs/settings.rst
@@ -39,8 +39,8 @@ If you want to override the default settings for your users, create ``HELPDESK_D
}
-Access controll & Security
----------------
+Access control & Security
+-------------------------
These settings can be used to change who can access the helpdesk.
- **HELPDESK_PUBLIC_VIEW_PROTECTOR** This is a function that takes a request and can either return `None` granting access to to a public view or a redirect denying access.
@@ -51,16 +51,24 @@ These settings can be used to change who can access the helpdesk.
**Default:** ``HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = False``
-- **HELPDESK_VALID_EXTENSIONS** Valid extensions for file types that can be attached to tickets. Note: This used to be calle **VALID_EXTENSIONS** which is now deprecated.
-
- **Default:** ``HELPDESK_VALID_EXTENSIONS = ['.txt', '.asc', '.htm', '.html', '.pdf', '.doc', '.docx', '.odt', '.jpg', '.png', '.eml']
-
-- **HELPDESK_VALIDATE_ATTACHMENT_TYPES** If you'd like to turn of filtering of helpdesk extension types you can set this to False.
-
- **HELPDESK_ANON_ACCESS_RAISES_404** If True, redirects user to a 404 page when attempting to reach ticket pages while not logged in, rather than redirecting to a login screen.
**Default:** ``HELPDESK_ANON_ACCESS_RAISES_404 = False``
+Settings related to attachments:
+
+- **HELPDESK_ENABLE_ATTACHMENTS** If set to ``True``, files can be
+ attached to tickets and followups, and emails are searched for
+ attachments which are then attached to the ticket. Also enables the
+ ``HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE`` setting.
+
+- **HELPDESK_VALID_EXTENSIONS** Valid extensions for file types that can be attached to tickets. Note: This used to be called **VALID_EXTENSIONS** which is now deprecated.
+
+ **Default:** ``HELPDESK_VALID_EXTENSIONS = ['.txt', '.asc', '.htm', '.html', '.pdf', '.doc', '.docx', '.odt', '.jpg', '.png', '.eml']``
+
+- **HELPDESK_VALIDATE_ATTACHMENT_TYPES** If you'd like to turn of filtering of helpdesk extension types you can set this to False.
+
+
Generic Options
---------------
These changes are visible throughout django-helpdesk
@@ -422,4 +430,9 @@ The following settings were defined in previous versions and are no longer suppo
- **HELPDESK_FULL_FIRST_MESSAGE_FROM_EMAIL** Do not ignore fowarded and replied text from the email messages which create a new ticket; useful for cases when customer forwards some email (error from service or something) and wants support to see that
-- **HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE** Any incoming .eml message is saved and available, helps when customer spent some time doing fancy markup which has been corrupted during the email-to-ticket-comment translate process
+- **HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE** Any incoming .eml
+ message is saved and available, helps when customer spent some time
+ doing fancy markup which has been corrupted during the
+ email-to-ticket-comment translate process.
+
+ Requires ``HELPDESK_ENABLE_ATTACHMENTS`` to be set to `True`
From d3553d9335c6b50a1120ba3760b6965d1d9693d7 Mon Sep 17 00:00:00 2001
From: Georg Lehner
Date: Thu, 6 Jun 2024 16:55:53 +0200
Subject: [PATCH 04/10] Add warning about new default to
HELPDESK_ENABLE_ATTACHEMENTS
---
docs/settings.rst | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/docs/settings.rst b/docs/settings.rst
index ea1529b7..004a06bf 100644
--- a/docs/settings.rst
+++ b/docs/settings.rst
@@ -61,6 +61,12 @@ Settings related to attachments:
attached to tickets and followups, and emails are searched for
attachments which are then attached to the ticket. Also enables the
``HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE`` setting.
+
+ **Caution**: Until version 1.2.0 attachments were enabled by
+ default. Since uploaded files by default are published without access
+ control this can lead to unintended exposure of sensitive
+ data. The default is now to disable attachments by default. Only
+ enable attachments if you have secured access to them.
- **HELPDESK_VALID_EXTENSIONS** Valid extensions for file types that can be attached to tickets. Note: This used to be called **VALID_EXTENSIONS** which is now deprecated.
From a2f944b475e983400da4b81096df1e30e74b6f18 Mon Sep 17 00:00:00 2001
From: Georg Lehner
Date: Fri, 7 Jun 2024 17:58:41 +0200
Subject: [PATCH 05/10] Enable attachments by default
In order to not break existing django-helpdesk installations
upon upgrade.
---
docs/settings.rst | 10 +++++-----
helpdesk/settings.py | 6 +++++-
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/docs/settings.rst b/docs/settings.rst
index 004a06bf..3d0131b3 100644
--- a/docs/settings.rst
+++ b/docs/settings.rst
@@ -62,11 +62,11 @@ Settings related to attachments:
attachments which are then attached to the ticket. Also enables the
``HELPDESK_ALWAYS_SAVE_INCOMING_EMAIL_MESSAGE`` setting.
- **Caution**: Until version 1.2.0 attachments were enabled by
- default. Since uploaded files by default are published without access
- control this can lead to unintended exposure of sensitive
- data. The default is now to disable attachments by default. Only
- enable attachments if you have secured access to them.
+ **Caution**: Set this to False, unless you have secured access to
+ the uploaded files. Otherwise anyone on the Internet will be able
+ to download your ticket attachments.
+
+ Attachments are enabled by default for backwards compatibility.
- **HELPDESK_VALID_EXTENSIONS** Valid extensions for file types that can be attached to tickets. Note: This used to be called **VALID_EXTENSIONS** which is now deprecated.
diff --git a/helpdesk/settings.py b/helpdesk/settings.py
index 6d83ed63..d6d1acbb 100644
--- a/helpdesk/settings.py
+++ b/helpdesk/settings.py
@@ -57,9 +57,13 @@ HELPDESK_STAFF_VIEW_PROTECTOR = getattr(settings,
lambda _: None)
# Enable ticket and Email attachments
+#
+# Caution! Set this to False, unless you have secured access to
+# the uploaded files. Otherwise anyone on the Internet will be
+# able to download your ticket attachments.
HELPDESK_ENABLE_ATTACHMENTS = getattr(settings,
'HELPDESK_ENABLE_ATTACHMENTS',
- False)
+ True)
# Enable the Dependencies field on ticket view
HELPDESK_ENABLE_DEPENDENCIES_ON_TICKET = getattr(settings,
From 3dcbdad638be1066cff269bb0f2fb83dbee439ca Mon Sep 17 00:00:00 2001
From: Georg Lehner
Date: Fri, 7 Jun 2024 18:04:05 +0200
Subject: [PATCH 06/10] Fix: helpdesk settings are imported as settings
---
helpdesk/email.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/helpdesk/email.py b/helpdesk/email.py
index de9aebdc..3bb9463c 100644
--- a/helpdesk/email.py
+++ b/helpdesk/email.py
@@ -595,7 +595,7 @@ def create_object_from_email_message(message, ticket_id, payload, files, logger)
logger.info("[%s-%s] %s" % (ticket.queue.slug, ticket.id, ticket.title,))
- if helpdesk.settings.HELPDESK_ENABLE_ATTACHMENTS:
+ if settings.HELPDESK_ENABLE_ATTACHMENTS:
try:
attached = process_attachments(f, files)
except ValidationError as e:
@@ -985,7 +985,7 @@ def extract_email_metadata(message: str,
filtered_body, full_body = extract_email_message_content(message_obj, files, include_chained_msgs)
# If the base part is not a multipart then it will have already been processed as the vbody content so
# no need to process attachments
- if "multipart" == message_obj.get_content_maintype() and helpdesk.settings.HELPDESK_ENABLE_ATTACHMENTS:
+ if "multipart" == message_obj.get_content_maintype() and settings.HELPDESK_ENABLE_ATTACHMENTS:
# Find and attach all other parts or part contents as attachments
counter, content_parts_excluded = extract_attachments(message_obj, files, logger)
if not content_parts_excluded:
@@ -995,7 +995,7 @@ def extract_email_metadata(message: str,
Verify that there were no text/* parts containing message content.")
if logger.isEnabledFor(logging.DEBUG):
logger.debug("Email parsed and %s attachments were found and attached.", counter)
- if helpdesk.settings.HELPDESK_ENABLE_ATTACHMENTS:
+ if settings.HELPDESK_ENABLE_ATTACHMENTS:
add_file_if_always_save_incoming_email_message(files, message)
smtp_priority = message_obj.get('priority', '')
From 78cf89ca9b707dbf9826b3bbd3a2ca1aa624f07d Mon Sep 17 00:00:00 2001
From: Georg Lehner
Date: Mon, 10 Jun 2024 11:24:00 +0200
Subject: [PATCH 07/10] Exclude related JavaScript function from staff Ticket
view when attachments are not enabled
---
helpdesk/templates/helpdesk/ticket.html | 117 ++++++++++++------------
1 file changed, 60 insertions(+), 57 deletions(-)
diff --git a/helpdesk/templates/helpdesk/ticket.html b/helpdesk/templates/helpdesk/ticket.html
index 652988e0..ce7d61e4 100644
--- a/helpdesk/templates/helpdesk/ticket.html
+++ b/helpdesk/templates/helpdesk/ticket.html
@@ -266,71 +266,74 @@ $( function() {
+ {% if helpdesk_settings.HELPDESK_ENABLE_ATTACHMENTS %}
+ // this function listens for changes on any file input, and
+ // emits the appropriate event to update the input's text.
+ // Needed to have properly styled file input buttons! (this really shouldn't be this hard...)
+ $(document).on('change', ':file', function() {
+ var input = $(this),
+ inputWidgetNum = $(this).attr('id').split("file")[1],
+ numFiles = input.get(0).files ? input.get(0).files.length : 1,
+ label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
+ input.trigger('fileselect', [numFiles, label, inputWidgetNum]);
+ });
+ {% endif %}
+
{% endblock %}
From 20cd08fe28afa47967a75da0ecf51246e1e177e5 Mon Sep 17 00:00:00 2001
From: Georg Lehner
Date: Mon, 10 Jun 2024 12:47:13 +0200
Subject: [PATCH 08/10] Do not show attachments in public tickets if not
enabled, fix attachment upload if enabled
Attachments in followups were still shown (if they existed) even if
HELPDESK_ENABLE_ATTACHMENT was set to False.
If attachments were enabled it was not possible to upload them because
the JavaScript code for uploading attachments to public was not loaded
in the template.
---
helpdesk/templates/helpdesk/public_base.html | 1 +
.../helpdesk/public_view_ticket.html | 66 +++++++++++++++----
2 files changed, 56 insertions(+), 11 deletions(-)
diff --git a/helpdesk/templates/helpdesk/public_base.html b/helpdesk/templates/helpdesk/public_base.html
index ca0b74e1..22f256dc 100644
--- a/helpdesk/templates/helpdesk/public_base.html
+++ b/helpdesk/templates/helpdesk/public_base.html
@@ -9,6 +9,7 @@
{% include 'helpdesk/base-head.html' %}
{% block helpdesk_head %}{% endblock %}
+ {% include 'helpdesk/base_js.html' %}
diff --git a/helpdesk/templates/helpdesk/public_view_ticket.html b/helpdesk/templates/helpdesk/public_view_ticket.html
index ee36e304..4c5a736e 100644
--- a/helpdesk/templates/helpdesk/public_view_ticket.html
+++ b/helpdesk/templates/helpdesk/public_view_ticket.html
@@ -75,16 +75,19 @@
{% for followup in ticket.followup_set.public_followups %}
-{{ followup.comment|force_escape|urlizetrunc:50|num_to_link|linebreaksbr }}
-{% if followup.ticketchange_set.all %}
-{% for change in followup.ticketchange_set.all %}
-
{% blocktrans with change.field as field and change.old_value as old_value and change.new_value as new_value %}Changed {{ field }} from {{ old_value }} to {{ new_value }}.{% endblocktrans %}
-{% endfor %}
-
{% endif %}
-{% for attachment in followup.followupattachment_set.all %}{% if forloop.first %}
+ {% for change in followup.ticketchange_set.all %}
+
{% blocktrans with change.field as field and change.old_value as old_value and change.new_value as new_value %}Changed {{ field }} from {{ old_value }} to {{ new_value }}.{% endblocktrans %}
+ {% endfor %}
+
{% endif %}
+
+ {% if helpdesk_settings.HELPDESK_ENABLE_ATTACHMENTS %}
+ {% for attachment in followup.followupattachment_set.all %}{% if forloop.first %}