Merge custom staff filter, PR #239

This commit is contained in:
Garret Wassermann 2017-10-30 03:17:40 -04:00
commit 3a1bd76e75
10 changed files with 333 additions and 29 deletions

View File

@ -108,8 +108,12 @@ These options only change display of items on public-facing pages, not staff pag
Options that change ticket updates
----------------------------------
- **HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE** Allow non-staff users to interact with tickets? This will also change how 'staff_member_required'
in staff.py will be defined.
- **HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE** Allow non-staff users to interact with tickets?
Set to True to allow any authenticated user to manage tickets.
You can also apply a custom authorisation logic for identifying helpdesk staff members, by setting this to a callable.
In that case, the value should be a function accepting the active user as a parameter and returning True if the user is considered helpdesk staff, e.g.
lambda u: u.is_authenticated() and u.is_active and u.groups.filter(name='helpdesk_staff').exists()))
**Default:** ``HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = False``

View File

@ -3,9 +3,21 @@ from functools import wraps
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, Http404
from django.utils.decorators import available_attrs
from django.contrib.auth.decorators import user_passes_test
from helpdesk import settings as helpdesk_settings
if callable(helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE):
# apply a custom user validation condition
is_helpdesk_staff = helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE
elif helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE:
# treat 'normal' users like 'staff'
is_helpdesk_staff = lambda u: u.is_authenticated() and u.is_active
else:
is_helpdesk_staff = lambda u: u.is_authenticated() and u.is_active and u.is_staff
helpdesk_staff_member_required = user_passes_test(is_helpdesk_staff)
helpdesk_superuser_required = user_passes_test(lambda u: u.is_authenticated() and u.is_active and u.is_superuser)
def protect_view(view_func):
"""
@ -21,3 +33,4 @@ def protect_view(view_func):
return view_func(request, *args, **kwargs)
return _wrapped_view

View File

@ -312,6 +312,7 @@ def process_attachments(followup, attached_files):
attachments = []
for attached in attached_files:
if attached.size:
filename = smart_text(attached.name)
att = Attachment(

View File

@ -2,8 +2,9 @@
Default settings for django-helpdesk.
"""
import warnings
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
try:
@ -85,12 +86,12 @@ HELPDESK_SUBMIT_A_TICKET_PUBLIC = getattr(settings, 'HELPDESK_SUBMIT_A_TICKET_PU
# options for update_ticket views #
###################################
''' options for update_ticket views '''
# allow non-staff users to interact with tickets?
# this will also change how 'staff_member_required'
# in staff.py will be defined.
HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = getattr(settings,
'HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE',
False)
# can be True/False or a callable accepting the active user and returning True if they must be considered helpdesk staff
HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = getattr(settings, 'HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE', False)
if not (HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE in (True, False) or callable(HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE)):
warnings.warn("HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE should be set to either True/False or a callable.", RuntimeWarning)
# show edit buttons in ticket follow ups.
HELPDESK_SHOW_EDIT_BUTTON_FOLLOW_UP = getattr(settings,

View File

@ -1,4 +1,4 @@
{% load i18n %}
{% load i18n helpdesk_staff %}
<!-- Navigation -->
<nav class="navbar navbar-default navbar-fixed-top" role="navigation" style="margin-bottom: 0">
@ -14,7 +14,7 @@
<!-- /.navbar-header -->
<div class="collapse navbar-collapse" id="helpdesk-nav-collapse">
{% if helpdesk_settings.HELPDESK_NAVIGATION_ENABLED and user.is_authenticated or user.is_staff %}
{% if helpdesk_settings.HELPDESK_NAVIGATION_ENABLED and user.is_authenticated or user|is_helpdesk_staff %}
<ul class="nav navbar-top-links navbar-right">
<li>
<a href='{% url 'helpdesk:dashboard' %}'><i class="fa fa-dashboard fa-fw"></i> <span class="nav-text">{% trans "Dashboard" %}</span></a>
@ -28,6 +28,7 @@
<li>
<a href='{% url 'helpdesk:report_index' %}'><i class="fa fa-bar-chart-o fa-fw"></i> <span class="nav-text"> {% trans "Stats" %}</span></a>
</li>
{% if helpdesk_settings.HELPDESK_KB_ENABLED %}
<li>
<a href='{% url 'helpdesk:kb_index' %}'><i class="fa fa-database fa-fw"></i> <span class="nav-text">{% trans "Knowledgebase" %}</span></a>

View File

@ -0,0 +1,22 @@
"""
django-helpdesk - A Django powered ticket tracker for small enterprise.
templatetags/helpdesk_staff.py - The is_helpdesk_staff template filter returns True if the user qualifies as Helpdesk staff.
"""
import logging
from django.template import Library
from django.db.models import Q
from helpdesk.decorators import is_helpdesk_staff
logger = logging.getLogger(__name__)
register = Library()
@register.filter(name='is_helpdesk_staff')
def helpdesk_staff(user):
try:
return is_helpdesk_staff(user)
except Exception, e:
logger.exception("'helpdesk_staff' template tag (django-helpdesk) crashed")

View File

@ -4,6 +4,8 @@ from django.contrib.auth import get_user_model
User = get_user_model()
from helpdesk.models import Ticket, Queue
def get_staff_user(username='helpdesk.staff', password='password'):
try:
@ -37,4 +39,37 @@ def reload_urlconf(urlconf=None):
clear_url_caches()
def update_user_settings(user, **kwargs):
usersettings = user.usersettings
settings = usersettings.settings
settings.update(kwargs)
usersettings.settings = settings
usersettings.save()
def delete_user_settings(user, *args):
usersettings = user.usersettings
settings = usersettings.settings
for setting in args:
if setting in settings:
del settings[setting]
usersettings.settings = settings
usersettings.save()
def create_ticket(**kwargs):
q = kwargs.get('queue', None)
if q is None:
try:
q = Queue.objects.all()[0]
except IndexError:
q = Queue.objects.create(title='Test Q', slug='test', )
data = {
'title': "I wish to register a complaint",
'queue': q,
}
data.update(kwargs)
return Ticket.objects.create(**data)
HELPDESK_URLCONF = 'helpdesk.urls'

View File

@ -1,22 +1,21 @@
# -*- coding: utf-8 -*-
import sys
from django.core.urlresolvers import reverse
from django.test import TestCase
from helpdesk.tests.helpers import get_staff_user, reload_urlconf
from helpdesk import settings
from helpdesk.tests.helpers import (get_staff_user, reload_urlconf, User, update_user_settings, delete_user_settings,
create_ticket)
class TestKBDisabled(TestCase):
class KBDisabledTestCase(TestCase):
def setUp(self):
from helpdesk import settings
self.HELPDESK_KB_ENABLED = settings.HELPDESK_KB_ENABLED
if self.HELPDESK_KB_ENABLED:
settings.HELPDESK_KB_ENABLED = False
reload_urlconf()
def tearDown(self):
from helpdesk import settings
if self.HELPDESK_KB_ENABLED:
settings.HELPDESK_KB_ENABLED = True
reload_urlconf()
@ -36,3 +35,193 @@ class TestKBDisabled(TestCase):
raise
else:
self.assertEqual(response.status_code, 200)
class StaffUserTestCaseMixin(object):
HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = False
def setUp(self):
self.original_setting = settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE
settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = self.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE
self.reload_views()
def tearDown(self):
settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = self.original_setting
self.reload_views()
def reload_views(self):
try:
reload(sys.modules['helpdesk.decorators'])
reload(sys.modules['helpdesk.views.staff'])
reload_urlconf()
except KeyError:
pass
def test_anonymous_user(self):
"""Access to the dashboard always requires a login"""
response = self.client.get(reverse('helpdesk_dashboard'), follow=True)
self.assertTemplateUsed(response, 'helpdesk/registration/login.html')
class NonStaffUsersAllowedTestCase(StaffUserTestCaseMixin, TestCase):
HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = True
def test_non_staff_allowed(self):
"""If HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE is True,
authenticated, non-staff users should be able to access
the dashboard.
"""
from helpdesk.decorators import is_helpdesk_staff
user = User.objects.create_user(username='henry.wensleydale', password='gouda', email='wensleydale@example.com')
self.assertTrue(is_helpdesk_staff(user))
self.client.login(username=user.username, password='gouda')
response = self.client.get(reverse('helpdesk_dashboard'), follow=True)
self.assertTemplateUsed(response, 'helpdesk/dashboard.html')
class StaffUsersOnlyTestCase(StaffUserTestCaseMixin, TestCase):
# Use default values
HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = False
def test_non_staff(self):
"""Non-staff users are correctly identified"""
from helpdesk.decorators import is_helpdesk_staff
user = User.objects.create_user(username='henry.wensleydale', password='gouda', email='wensleydale@example.com')
self.assertFalse(is_helpdesk_staff(user))
def test_staff_only(self):
"""If HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE is False,
only staff users should be able to access the dashboard.
"""
from helpdesk.decorators import is_helpdesk_staff
user = get_staff_user()
self.assertTrue(is_helpdesk_staff(user))
self.client.login(username=user.username, password='password')
response = self.client.get(reverse('helpdesk_dashboard'), follow=True)
self.assertTemplateUsed(response, 'helpdesk/dashboard.html')
class CustomStaffUserTestCase(StaffUserTestCaseMixin, TestCase):
@staticmethod
def custom_staff_filter(user):
"""Arbitrary user validation function"""
return user.is_authenticated() and user.is_active and user.username.lower().endswith('wensleydale')
HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = custom_staff_filter
def test_custom_staff_pass(self):
"""If HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE is callable,
a custom access rule is applied.
"""
from helpdesk.decorators import is_helpdesk_staff
user = User.objects.create_user(username='henry.wensleydale', password='gouda', email='wensleydale@example.com')
self.assertTrue(is_helpdesk_staff(user))
self.client.login(username=user.username, password='gouda')
response = self.client.get(reverse('helpdesk_dashboard'), follow=True)
self.assertTemplateUsed(response, 'helpdesk/dashboard.html')
def test_custom_staff_fail(self):
from helpdesk.decorators import is_helpdesk_staff
user = User.objects.create_user(username='terry.milton', password='frog', email='milton@example.com')
self.assertFalse(is_helpdesk_staff(user))
self.client.login(username=user.username, password='frog')
response = self.client.get(reverse('helpdesk_dashboard'), follow=True)
self.assertTemplateUsed(response, 'helpdesk/registration/login.html')
class HomePageAnonymousUserTestCase(TestCase):
def setUp(self):
self.redirect_to_login = settings.HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT
def tearDown(self):
settings.HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = self.redirect_to_login
def test_homepage(self):
settings.HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = True
response = self.client.get(reverse('helpdesk_home'))
self.assertTemplateUsed('helpdesk/public_homepage.html')
def test_redirect_to_login(self):
"""Unauthenticated users are redirected to the login page if HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT is True"""
settings.HELPDESK_REDIRECT_TO_LOGIN_BY_DEFAULT = True
response = self.client.get(reverse('helpdesk_home'))
self.assertRedirects(response, reverse('login'))
class HomePageTestCase(TestCase):
def setUp(self):
self.original_setting = settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE
settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = False
try:
reload(sys.modules['helpdesk.views.public'])
except KeyError:
pass
def tearDown(self):
settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE = self.original_setting
reload(sys.modules['helpdesk.views.public'])
def assertUserRedirectedToView(self, user, view_name):
self.client.login(username=user.username, password='password')
response = self.client.get(reverse('helpdesk_home'))
self.assertRedirects(response, reverse(view_name))
self.client.logout()
def test_redirect_to_dashboard(self):
"""Authenticated users are redirected to the dashboard"""
user = get_staff_user()
# login_view_ticketlist is False...
update_user_settings(user, login_view_ticketlist=False)
self.assertUserRedirectedToView(user, 'helpdesk_dashboard')
# ... or missing
delete_user_settings(user, 'login_view_ticketlist')
self.assertUserRedirectedToView(user, 'helpdesk_dashboard')
def test_no_user_settings_redirect_to_dashboard(self):
"""Authenticated users are redirected to the dashboard if user settings are missing"""
from helpdesk.models import UserSettings
user = get_staff_user()
UserSettings.objects.filter(user=user).delete()
self.assertUserRedirectedToView(user, 'helpdesk_dashboard')
def test_redirect_to_ticket_list(self):
"""Authenticated users are redirected to the ticket list based on their user settings"""
user = get_staff_user()
update_user_settings(user, login_view_ticketlist=True)
self.assertUserRedirectedToView(user, 'helpdesk_list')
class ReturnToTicketTestCase(TestCase):
def test_staff_user(self):
from helpdesk.views.staff import return_to_ticket
user = get_staff_user()
ticket = create_ticket()
response = return_to_ticket(user, settings, ticket)
self.assertEqual(response['location'], ticket.get_absolute_url())
def test_non_staff_user(self):
from helpdesk.views.staff import return_to_ticket
user = User.objects.create_user(username='henry.wensleydale', password='gouda', email='wensleydale@example.com')
ticket = create_ticket()
response = return_to_ticket(user, settings, ticket)
self.assertEqual(response['location'], ticket.ticket_url)

View File

@ -14,7 +14,7 @@ from django.utils.http import urlquote
from django.utils.translation import ugettext as _
from helpdesk import settings as helpdesk_settings
from helpdesk.decorators import protect_view
from helpdesk.decorators import protect_view, is_helpdesk_staff
from helpdesk.forms import PublicTicketForm
from helpdesk.lib import text_is_spam
from helpdesk.models import Ticket, Queue, UserSettings, KBCategory
@ -22,7 +22,10 @@ from helpdesk.models import Ticket, Queue, UserSettings, KBCategory
@protect_view
def homepage(request):
if request.user.is_staff or \
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:
@ -85,7 +88,7 @@ def view_ticket(request):
except ObjectDoesNotExist:
error_message = _('Invalid ticket ID or e-mail address. Please try again.')
else:
if request.user.is_staff:
if is_helpdesk_staff(request.user):
redirect_url = reverse('helpdesk:view', args=[ticket_id])
if 'close' in request.GET:
redirect_url += '?close'

View File

@ -42,7 +42,6 @@ from helpdesk import settings as helpdesk_settings
User = get_user_model()
if helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE:
# treat 'normal' users like 'staff'
staff_member_required = user_passes_test(
@ -86,6 +85,7 @@ def _has_access_to_queue(user, queue):
return user.has_perm(queue.permission_name)
@helpdesk_staff_member_required
def dashboard(request):
"""
A quick summary overview for users: A list of their own tickets, a table
@ -166,7 +166,7 @@ def dashboard(request):
})
dashboard = staff_member_required(dashboard)
@helpdesk_staff_member_required
def delete_ticket(request, ticket_id):
ticket = get_object_or_404(Ticket, id=ticket_id)
if not _has_access_to_queue(request.user, ticket.queue):
@ -178,10 +178,17 @@ def delete_ticket(request, ticket_id):
})
else:
ticket.delete()
<<<<<<< HEAD
return HttpResponseRedirect(reverse('helpdesk:home'))
delete_ticket = staff_member_required(delete_ticket)
=======
return HttpResponseRedirect(reverse('helpdesk_home'))
@helpdesk_staff_member_required
>>>>>>> brente/custom-staff-filter
def followup_edit(request, ticket_id, followup_id):
"""Edit followup options with an ability to change the ticket."""
followup = get_object_or_404(FollowUp, id=followup_id)
@ -232,6 +239,7 @@ def followup_edit(request, ticket_id, followup_id):
followup_edit = staff_member_required(followup_edit)
@helpdesk_staff_member_required
def followup_delete(request, ticket_id, followup_id):
"""followup delete for superuser"""
@ -245,6 +253,7 @@ def followup_delete(request, ticket_id, followup_id):
followup_delete = staff_member_required(followup_delete)
@helpdesk_staff_member_required
def view_ticket(request, ticket_id):
ticket = get_object_or_404(Ticket, id=ticket_id)
if not _has_access_to_queue(request.user, ticket.queue):
@ -363,7 +372,7 @@ def update_ticket(request, ticket_id, public=False):
if not (public or (
request.user.is_authenticated() and
request.user.is_active and (
request.user.is_staff or
is_helpdesk_staff(request.user) or
helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE))):
return HttpResponseRedirect('%s?next=%s' %
(reverse('helpdesk:login'), request.path))
@ -421,7 +430,7 @@ def update_ticket(request, ticket_id, public=False):
f = FollowUp(ticket=ticket, date=timezone.now(), comment=comment)
if request.user.is_staff or helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE:
if is_helpdesk_staff(request.user):
f.user = request.user
f.public = public
@ -462,7 +471,9 @@ def update_ticket(request, ticket_id, public=False):
f.save()
files = process_attachments(f, request.FILES.getlist('attachment'))
files = []
if request.FILES:
files = process_attachments(f, request.FILES.getlist('attachment'))
if title and title != ticket.title:
c = TicketChange(
@ -586,6 +597,7 @@ def update_ticket(request, ticket_id, public=False):
(not reassigned and
ticket.assigned_to.usersettings_helpdesk.settings.get(
'email_on_ticket_change', False)):
send_templated_mail(
template_staff,
context,
@ -627,14 +639,19 @@ def update_ticket(request, ticket_id, public=False):
def return_to_ticket(user, helpdesk_settings, ticket):
<<<<<<< HEAD
"""Helper function for update_ticket"""
=======
""" Helper function for update_ticket """
>>>>>>> brente/custom-staff-filter
if user.is_staff or helpdesk_settings.HELPDESK_ALLOW_NON_STAFF_TICKET_UPDATE:
if is_helpdesk_staff(user):
return HttpResponseRedirect(ticket.get_absolute_url())
else:
return HttpResponseRedirect(ticket.ticket_url)
@helpdesk_staff_member_required
def mass_update(request):
tickets = request.POST.getlist('ticket_id')
action = request.POST.get('action', None)
@ -751,6 +768,7 @@ def mass_update(request):
mass_update = staff_member_required(mass_update)
@helpdesk_staff_member_required
def ticket_list(request):
context = {}
@ -934,6 +952,7 @@ def ticket_list(request):
ticket_list = staff_member_required(ticket_list)
@helpdesk_staff_member_required
def edit_ticket(request, ticket_id):
ticket = get_object_or_404(Ticket, id=ticket_id)
if not _has_access_to_queue(request.user, ticket.queue):
@ -951,6 +970,7 @@ 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)
@ -988,6 +1008,7 @@ def create_ticket(request):
create_ticket = staff_member_required(create_ticket)
@helpdesk_staff_member_required
def raw_details(request, type):
# TODO: This currently only supports spewing out 'PreSetReply' objects,
# in the future it needs to be expanded to include other items. All it
@ -1004,9 +1025,9 @@ def raw_details(request, type):
raise Http404
raise Http404
raw_details = staff_member_required(raw_details)
@helpdesk_staff_member_required
def hold_ticket(request, ticket_id, unhold=False):
ticket = get_object_or_404(Ticket, id=ticket_id)
if not _has_access_to_queue(request.user, ticket.queue):
@ -1031,19 +1052,20 @@ def hold_ticket(request, ticket_id, unhold=False):
ticket.save()
return HttpResponseRedirect(ticket.get_absolute_url())
hold_ticket = staff_member_required(hold_ticket)
@helpdesk_staff_member_required
def unhold_ticket(request, ticket_id):
return hold_ticket(request, ticket_id, unhold=True)
unhold_ticket = staff_member_required(unhold_ticket)
@helpdesk_staff_member_required
def rss_list(request):
return render(request, 'helpdesk/rss_list.html', {'queues': Queue.objects.all()})
rss_list = staff_member_required(rss_list)
@helpdesk_staff_member_required
def report_index(request):
number_tickets = Ticket.objects.all().count()
saved_query = request.GET.get('saved_query', None)
@ -1092,6 +1114,7 @@ def report_index(request):
report_index = staff_member_required(report_index)
@helpdesk_staff_member_required
def run_report(request, report):
if Ticket.objects.all().count() == 0 or report not in (
'queuemonth', 'usermonth', 'queuestatus', 'queuepriority', 'userstatus',
@ -1292,6 +1315,7 @@ def run_report(request, report):
run_report = staff_member_required(run_report)
@helpdesk_staff_member_required
def save_query(request):
title = request.POST.get('title', None)
shared = request.POST.get('shared', False)
@ -1309,6 +1333,7 @@ def save_query(request):
save_query = staff_member_required(save_query)
@helpdesk_staff_member_required
def delete_saved_query(request, id):
query = get_object_or_404(SavedSearch, id=id, user=request.user)
@ -1320,6 +1345,7 @@ def delete_saved_query(request, id):
delete_saved_query = staff_member_required(delete_saved_query)
@helpdesk_staff_member_required
def user_settings(request):
s = request.user.usersettings_helpdesk
if request.POST:
@ -1334,6 +1360,7 @@ def user_settings(request):
user_settings = staff_member_required(user_settings)
@helpdesk_superuser_required
def email_ignore(request):
return render(request, 'helpdesk/email_ignore_list.html', {
'ignore_list': IgnoreEmail.objects.all(),
@ -1341,6 +1368,7 @@ def email_ignore(request):
email_ignore = superuser_required(email_ignore)
@helpdesk_superuser_required
def email_ignore_add(request):
if request.method == 'POST':
form = EmailIgnoreForm(request.POST)
@ -1354,6 +1382,7 @@ def email_ignore_add(request):
email_ignore_add = superuser_required(email_ignore_add)
@helpdesk_superuser_required
def email_ignore_del(request, id):
ignore = get_object_or_404(IgnoreEmail, id=id)
if request.method == 'POST':
@ -1364,6 +1393,7 @@ def email_ignore_del(request, id):
email_ignore_del = superuser_required(email_ignore_del)
@helpdesk_staff_member_required
def ticket_cc(request, ticket_id):
ticket = get_object_or_404(Ticket, id=ticket_id)
if not _has_access_to_queue(request.user, ticket.queue):
@ -1377,6 +1407,7 @@ def ticket_cc(request, ticket_id):
ticket_cc = staff_member_required(ticket_cc)
@helpdesk_staff_member_required
def ticket_cc_add(request, ticket_id):
ticket = get_object_or_404(Ticket, id=ticket_id)
if not _has_access_to_queue(request.user, ticket.queue):
@ -1401,6 +1432,7 @@ def ticket_cc_add(request, ticket_id):
ticket_cc_add = staff_member_required(ticket_cc_add)
@helpdesk_staff_member_required
def ticket_cc_del(request, ticket_id, cc_id):
cc = get_object_or_404(TicketCC, ticket__id=ticket_id, id=cc_id)
@ -1412,6 +1444,7 @@ def ticket_cc_del(request, ticket_id, cc_id):
ticket_cc_del = staff_member_required(ticket_cc_del)
@helpdesk_staff_member_required
def ticket_dependency_add(request, ticket_id):
ticket = get_object_or_404(Ticket, id=ticket_id)
if not _has_access_to_queue(request.user, ticket.queue):
@ -1433,6 +1466,7 @@ def ticket_dependency_add(request, ticket_id):
ticket_dependency_add = staff_member_required(ticket_dependency_add)
@helpdesk_staff_member_required
def ticket_dependency_del(request, ticket_id, dependency_id):
dependency = get_object_or_404(TicketDependency, ticket__id=ticket_id, id=dependency_id)
if request.method == 'POST':
@ -1442,6 +1476,7 @@ def ticket_dependency_del(request, ticket_id, dependency_id):
ticket_dependency_del = staff_member_required(ticket_dependency_del)
@helpdesk_staff_member_required
def attachment_del(request, ticket_id, attachment_id):
ticket = get_object_or_404(Ticket, id=ticket_id)
if not _has_access_to_queue(request.user, ticket.queue):