From ffc97338c9e8d5c42f2effe7a3623403cae28784 Mon Sep 17 00:00:00 2001 From: Timothy Hobbs Date: Fri, 7 Sep 2018 19:05:16 +0200 Subject: [PATCH] Submit ticket link should work for non-logged in users --- helpdesk/forms.py | 18 ++- .../helpdesk/public_create_ticket.html | 47 ++++++++ helpdesk/urls.py | 12 +- helpdesk/views/permissions.py | 8 ++ helpdesk/views/public.py | 106 ++++++++++-------- helpdesk/views/staff.py | 47 +++----- 6 files changed, 151 insertions(+), 87 deletions(-) create mode 100644 helpdesk/templates/helpdesk/public_create_ticket.html create mode 100644 helpdesk/views/permissions.py diff --git a/helpdesk/forms.py b/helpdesk/forms.py index e9d4ef64..f5d1473c 100644 --- a/helpdesk/forms.py +++ b/helpdesk/forms.py @@ -301,21 +301,27 @@ class TicketForm(AbstractTicketForm): help_text=_('This e-mail address will receive copies of all public ' 'updates to this ticket.'), ) - assigned_to = forms.ChoiceField( - widget=forms.Select(attrs={'class': 'form-control'}), - choices=(), + widget=forms.Select(attrs={'class': 'form-control'}) if not helpdesk_settings.HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO else forms.HiddenInput(), required=False, label=_('Case owner'), help_text=_('If you select an owner other than yourself, they\'ll be ' 'e-mailed details of this ticket immediately.'), + + choices=() ) def __init__(self, *args, **kwargs): """ Add any custom fields that are defined to the form. """ - super(TicketForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) + self.fields['queue'].choices = [('', '--------')] + [(q.id, q.title) for q in Queue.objects.all()] + if helpdesk_settings.HELPDESK_STAFF_ONLY_TICKET_OWNERS: + assignable_users = User.objects.filter(is_active=True, is_staff=True).order_by(User.USERNAME_FIELD) + else: + assignable_users = User.objects.filter(is_active=True).order_by(User.USERNAME_FIELD) + self.fields['assigned_to'].choices = [('', '--------')] + [(u.id, u.get_username()) for u in assignable_users] self._add_form_custom_fields() def save(self, user=None): @@ -375,8 +381,8 @@ class PublicTicketForm(AbstractTicketForm): self.fields['priority'].widget = forms.HiddenInput() if hasattr(settings, 'HELPDESK_PUBLIC_TICKET_DUE_DATE'): self.fields['due_date'].widget = forms.HiddenInput() - - self._add_form_custom_fields(False) + self.fields['queue'].choices = [('', '--------')] + [ + (q.id, q.title) for q in Queue.objects.filter(allow_public_submission=True)] def save(self): """ diff --git a/helpdesk/templates/helpdesk/public_create_ticket.html b/helpdesk/templates/helpdesk/public_create_ticket.html new file mode 100644 index 00000000..139657b6 --- /dev/null +++ b/helpdesk/templates/helpdesk/public_create_ticket.html @@ -0,0 +1,47 @@ +{% extends "helpdesk/public_base.html" %} +{% load i18n bootstrap %} + +{% block helpdesk_body %} + +{% if helpdesk_settings.HELPDESK_SUBMIT_A_TICKET_PUBLIC %} +
+
+ +
+

{% trans "Submit a Ticket" %}

+

{% trans "Please provide as descriptive a title and description as possible." %}

+ +
+
+ {{ form|bootstrap }} + {% comment %} + {% for field in form %} + + {% if field.is_hidden %} + {{ field }} + {% else %} + + +
+ {% if not field.field.required %} {% trans "(Optional)" %}{% endif %} +
{{ field }}
+ {% if field.errors %}
{{ field.errors }}
{% endif %} + {% if field.help_text %}{{ field.help_text }}{% endif %} +
+ + {% endif %} + + {% endfor %} + {% endcomment %} + +
+ +
+
+ +{% csrf_token %}
+
+
+
+{% endif %} +{% endblock %} diff --git a/helpdesk/urls.py b/helpdesk/urls.py index a206ff0d..969d8dd1 100644 --- a/helpdesk/urls.py +++ b/helpdesk/urls.py @@ -12,7 +12,7 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth import views as auth_views from django.views.generic import TemplateView -from helpdesk.decorators import helpdesk_staff_member_required +from helpdesk.decorators import helpdesk_staff_member_required, protect_view from helpdesk import settings as helpdesk_settings from helpdesk.views import feeds, staff, public, kb @@ -46,10 +46,6 @@ urlpatterns = [ staff.mass_update, name='mass_update'), - url(r'^tickets/submit/$', - staff.create_ticket, - name='submit'), - url(r'^tickets/(?P[0-9]+)/$', staff.view_ticket, name='view'), @@ -149,9 +145,13 @@ urlpatterns = [ urlpatterns += [ url(r'^$', - public.homepage, + protect_view(public.Homepage.as_view()), name='home'), + url(r'^tickets/submit/$', + public.create_ticket, + name='submit'), + url(r'^view/$', public.view_ticket, name='public_view'), diff --git a/helpdesk/views/permissions.py b/helpdesk/views/permissions.py new file mode 100644 index 00000000..955e71c9 --- /dev/null +++ b/helpdesk/views/permissions.py @@ -0,0 +1,8 @@ +from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin + +from helpdesk.decorators import is_helpdesk_staff + + +class MustBeStaffMixin(LoginRequiredMixin, UserPassesTestMixin): + def test_func(self): + return is_helpdesk_staff(self.request.user) diff --git a/helpdesk/views/public.py b/helpdesk/views/public.py index 78fb113d..0bcc17a9 100644 --- a/helpdesk/views/public.py +++ b/helpdesk/views/public.py @@ -18,55 +18,58 @@ from django.shortcuts import render from django.utils.http import urlquote from django.utils.translation import ugettext as _ from django.conf import settings +from django.views.generic.edit import FormView from helpdesk import settings as helpdesk_settings from helpdesk.decorators import protect_view, is_helpdesk_staff +import helpdesk.views.staff as staff from helpdesk.forms import PublicTicketForm from helpdesk.lib import text_is_spam from helpdesk.models import Ticket, Queue, UserSettings, KBCategory -@protect_view -def homepage(request): - if not request.user.is_authenticated and helpdesk_settings.HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT: - return HttpResponseRedirect(reverse('login')) - - if is_helpdesk_staff(request.user) or \ - (request.user.is_authenticated and - helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE): - try: - if request.user.usersettings_helpdesk.settings.get('login_view_ticketlist', False): - return HttpResponseRedirect(reverse('helpdesk:list')) - else: - return HttpResponseRedirect(reverse('helpdesk:dashboard')) - except UserSettings.DoesNotExist: - return HttpResponseRedirect(reverse('helpdesk:dashboard')) - - if request.method == 'POST': - form = PublicTicketForm(request.POST, request.FILES) - form.fields['queue'].choices = [('', '--------')] + [ - (q.id, q.title) for q in Queue.objects.filter(allow_public_submission=True)] - if form.is_valid(): - if text_is_spam(form.cleaned_data['body'], request): - # This submission is spam. Let's not save it. - return render(request, template_name='helpdesk/public_spam.html') - else: - ticket = form.save() - try: - return HttpResponseRedirect('%s?ticket=%s&email=%s' % ( - reverse('helpdesk:public_view'), - ticket.ticket_for_url, - urlquote(ticket.submitter_email)) - ) - except ValueError: - # if someone enters a non-int string for the ticket - return HttpResponseRedirect(reverse('helpdesk:home')) +def create_ticket(request, *args, **kwargs): + if is_helpdesk_staff(request.user): + return staff.CreateTicketView.as_view()(request, *args, **kwargs) else: + return CreateTicketView.as_view()(request, *args, **kwargs) + + +class CreateTicketView(FormView): + template_name = 'helpdesk/public_create_ticket.html' + form_class = PublicTicketForm + + def dispatch(self, *args, **kwargs): + request = self.request + if not request.user.is_authenticated and helpdesk_settings.HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT: + return HttpResponseRedirect(reverse('login')) + + if is_helpdesk_staff(request.user) or \ + (request.user.is_authenticated and + helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE): + try: + if request.user.usersettings_helpdesk.settings.get('login_view_ticketlist', False): + return HttpResponseRedirect(reverse('helpdesk:list')) + else: + return HttpResponseRedirect(reverse('helpdesk:dashboard')) + except UserSettings.DoesNotExist: + return HttpResponseRedirect(reverse('helpdesk:dashboard')) + return super().dispatch(*args, **kwargs) + + def get_context(self): + knowledgebase_categories = KBCategory.objects.all() + return { + 'helpdesk_settings': helpdesk_settings, + 'kb_categories': knowledgebase_categories + } + + def get_initial(self): + request = self.request + initial_data = {} try: queue = Queue.objects.get(slug=request.GET.get('queue', None)) except Queue.DoesNotExist: queue = None - initial_data = {} # add pre-defined data for public ticket if hasattr(settings, 'HELPDESK_PUBLIC_TICKET_QUEUE'): @@ -85,18 +88,31 @@ def homepage(request): if request.user.is_authenticated and request.user.email: initial_data['submitter_email'] = request.user.email + return initial_data - form = PublicTicketForm(initial=initial_data) - form.fields['queue'].choices = [('', '--------')] + [ - (q.id, q.title) for q in Queue.objects.filter(allow_public_submission=True)] + def form_valid(self, form): + request = self.request + if text_is_spam(form.cleaned_data['body'], request): + # This submission is spam. Let's not save it. + return render(request, template_name='helpdesk/public_spam.html') + else: + ticket = form.save() + try: + return HttpResponseRedirect('%s?ticket=%s&email=%s' % ( + reverse('helpdesk:public_view'), + ticket.ticket_for_url, + urlquote(ticket.submitter_email)) + ) + except ValueError: + # if someone enters a non-int string for the ticket + return HttpResponseRedirect(reverse('helpdesk:home')) - knowledgebase_categories = KBCategory.objects.all() + def get_success_url(self): + request = self.request - return render(request, 'helpdesk/public_homepage.html', { - 'form': form, - 'helpdesk_settings': helpdesk_settings, - 'kb_categories': knowledgebase_categories - }) + +class Homepage(CreateTicketView): + template_name = 'helpdesk/public_homepage.html' @protect_view diff --git a/helpdesk/views/staff.py b/helpdesk/views/staff.py index e6496694..54961f07 100644 --- a/helpdesk/views/staff.py +++ b/helpdesk/views/staff.py @@ -26,6 +26,7 @@ from django.utils.translation import ugettext as _ from django.utils.html import escape from django import forms from django.utils import timezone +from django.views.generic.edit import FormView from django.utils import six @@ -46,6 +47,7 @@ from helpdesk.models import ( IgnoreEmail, TicketCC, TicketDependency, ) from helpdesk import settings as helpdesk_settings +from helpdesk.views.permissions import MustBeStaffMixin User = get_user_model() @@ -1019,44 +1021,29 @@ def edit_ticket(request, ticket_id): edit_ticket = staff_member_required(edit_ticket) -@helpdesk_staff_member_required -def create_ticket(request): - if helpdesk_settings.HELPDESK_STAFF_ONLY_TICKET_OWNERS: - assignable_users = User.objects.filter(is_active=True, is_staff=True).order_by(User.USERNAME_FIELD) - else: - assignable_users = User.objects.filter(is_active=True).order_by(User.USERNAME_FIELD) +class CreateTicketView(MustBeStaffMixin, FormView): + template_name = 'helpdesk/create_ticket.html' + form_class = TicketForm - if request.method == 'POST': - form = TicketForm(request.POST, request.FILES) - form.fields['queue'].choices = [('', '--------')] + [ - (q.id, q.title) for q in Queue.objects.all()] - form.fields['assigned_to'].choices = [('', '--------')] + [ - (u.id, u.get_username()) for u in assignable_users] - if form.is_valid(): - ticket = form.save(user=request.user) - if _has_access_to_queue(request.user, ticket.queue): - return HttpResponseRedirect(ticket.get_absolute_url()) - else: - return HttpResponseRedirect(reverse('helpdesk:dashboard')) - else: + def get_initial(self): initial_data = {} + request = self.request if request.user.usersettings_helpdesk.settings.get('use_email_as_submitter', False) and request.user.email: initial_data['submitter_email'] = request.user.email if 'queue' in request.GET: initial_data['queue'] = request.GET['queue'] + return initial_data - form = TicketForm(initial=initial_data) - form.fields['queue'].choices = [('', '--------')] + [ - (q.id, q.title) for q in Queue.objects.all()] - form.fields['assigned_to'].choices = [('', '--------')] + [ - (u.id, u.get_username()) for u in assignable_users] - if helpdesk_settings.HELPDESK_CREATE_TICKET_HIDE_ASSIGNED_TO: - form.fields['assigned_to'].widget = forms.HiddenInput() + def form_valid(self, form): + self.ticket = form.save() + return super().form_valid(form) - return render(request, 'helpdesk/create_ticket.html', {'form': form}) - - -create_ticket = staff_member_required(create_ticket) + def get_success_url(self): + request = self.request + if _has_access_to_queue(request.user, self.ticket.queue): + return self.ticket.get_absolute_url() + else: + return reverse('helpdesk:dashboard') @helpdesk_staff_member_required