Refactor and fix datatables code to use cache safely

This commit is contained in:
Timothy Hobbs 2019-10-11 15:50:35 +02:00
parent 92ea5bc984
commit 0691bbabcd
5 changed files with 24 additions and 20 deletions

View File

@ -31,7 +31,7 @@ def query_to_base64(query):
""" """
Converts a query dict object to a base64-encoded bytes object. Converts a query dict object to a base64-encoded bytes object.
""" """
return b64encode(json.dumps(query).encode('UTF-8')) return b64encode(json.dumps(query).encode('UTF-8')).decode("ascii")
def query_from_base64(b64data): def query_from_base64(b64data):

View File

@ -28,6 +28,8 @@ from markdown.extensions import Extension
import uuid import uuid
from helpdesk import settings as helpdesk_settings
from .templated_email import send_templated_mail from .templated_email import send_templated_mail

View File

@ -240,7 +240,7 @@
"processing": true, "processing": true,
"serverSide": true, "serverSide": true,
"ajax": { "ajax": {
"url": "{% url 'helpdesk:datatables_ticket_list' %}", "url": "{% url 'helpdesk:datatables_ticket_list' urlsafe_query %}",
"type": "GET", "type": "GET",
}, },
createdRow: function( row, data, dataIndex ) createdRow: function( row, data, dataIndex )

View File

@ -37,6 +37,8 @@ class DirectTemplateView(TemplateView):
app_name = 'helpdesk' app_name = 'helpdesk'
base64_pattern = r'(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$'
urlpatterns = [ urlpatterns = [
url(r'^dashboard/$', url(r'^dashboard/$',
staff.dashboard, staff.dashboard,
@ -146,7 +148,7 @@ urlpatterns = [
staff.email_ignore_del, staff.email_ignore_del,
name='email_ignore_del'), name='email_ignore_del'),
url(r'^datatables_ticket_list/$', url(r'^datatables_ticket_list/(?P<query>{})$'.format(base64_pattern),
staff.datatables_ticket_list, staff.datatables_ticket_list,
name="datatables_ticket_list"), name="datatables_ticket_list"),
] ]

View File

@ -17,7 +17,7 @@ from django.contrib.contenttypes.models import ContentType
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.core.exceptions import ValidationError, PermissionDenied from django.core.exceptions import ValidationError, PermissionDenied
from django.db.models import Q from django.db.models import Q
from django.http import HttpResponseRedirect, Http404, HttpResponse from django.http import HttpResponseRedirect, Http404, HttpResponse, JsonResponse
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, get_object_or_404
from django.utils.dates import MONTHS_3 from django.utils.dates import MONTHS_3
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -942,7 +942,7 @@ def ticket_list(request):
urlsafe_query = query_to_base64(query_params) urlsafe_query = query_to_base64(query_params)
cache.set('ticket_qs', ticket_qs) cache.set(request.user.email + urlsafe_query, ticket_qs, timeout=60*60)
user_saved_queries = SavedSearch.objects.filter(Q(user=request.user) | Q(shared__exact=True)) user_saved_queries = SavedSearch.objects.filter(Q(user=request.user) | Q(shared__exact=True))
@ -993,7 +993,10 @@ def load_saved_query(request, query_params=None):
try: try:
# we get a string like: b'stuff' # we get a string like: b'stuff'
# so leave of the first two chars (b') and last (') # so leave of the first two chars (b') and last (')
b64query = saved_query.query[2:-1] if saved_query.query.startswith('b\''):
b64query = saved_query.query[2:-1]
else:
b64query = saved_query.query
query_params = query_from_base64(b64query) query_params = query_from_base64(b64query)
except json.JSONDecodeError: except json.JSONDecodeError:
raise QueryLoadError() raise QueryLoadError()
@ -1002,25 +1005,22 @@ def load_saved_query(request, query_params=None):
@helpdesk_staff_member_required @helpdesk_staff_member_required
@api_view(['GET']) @api_view(['GET'])
def datatables_ticket_list(request): def datatables_ticket_list(request, query):
""" """
Datatable on ticket_list.html uses this view from to get objects to display Datatable on ticket_list.html uses this view from to get objects to display
on the table. query_tickets_by_args is at lib.py, DatatablesTicketSerializer is in on the table. query_tickets_by_args is at lib.py, DatatablesTicketSerializer is in
serializers.py. The serializers and this view use django-rest_framework methods serializers.py. The serializers and this view use django-rest_framework methods
""" """
try: objects = cache.get(request.user.email + query)
objects = cache.get('ticket_qs') query_params = query_from_base64(query)
model_object = query_tickets_by_args(objects, '-date_created', **request.query_params) model_object = query_tickets_by_args(objects, '-date_created', **request.query_params)
serializer = DatatablesTicketSerializer(model_object['items'], many=True) serializer = DatatablesTicketSerializer(model_object['items'], many=True)
result = dict() result = dict()
result['data'] = serializer.data result['data'] = serializer.data
result['draw'] = model_object['draw'] result['draw'] = model_object['draw']
result['recordsTotal'] = model_object['total'] result['recordsTotal'] = model_object['total']
result['recordsFiltered'] = model_object['count'] result['recordsFiltered'] = model_object['count']
return (Response(result, status=status.HTTP_200_OK, template_name=None, content_type=None)) return (JsonResponse(result, status=status.HTTP_200_OK))
except TypeError as e:
return (Response(e, status=status.HTTP_404_NOT_FOUND, template_name=None, content_type=None))
@helpdesk_staff_member_required @helpdesk_staff_member_required