mirror of
https://github.com/pretix/pretix.git
synced 2026-05-06 15:24:02 +00:00
* Add data shredders for PII * First working shredder * Add more shredders * Add new shredders and download confirmation * tmp * PayPal, Stripe, banktransfer * Add icon to logs * Untested payment log shredders * Add waiting list shredder * First tests * Add tests for shredders * Improve templats, link to shredder * Test payment info shredders * More tests * Documentation * Fix enabled flag in payment provider overview * Fix minor issues
This commit is contained in:
@@ -369,8 +369,9 @@ class PaymentSettings(EventSettingsViewMixin, EventSettingsFormView):
|
||||
key=lambda s: s.verbose_name
|
||||
)
|
||||
for p in context['providers']:
|
||||
if not p.is_enabled and p.is_meta and p.settings._enabled:
|
||||
p.is_enabled = True
|
||||
p.show_enabled = p.is_enabled
|
||||
if p.is_meta:
|
||||
p.show_enabled = p.settings._enabled in (True, 'True')
|
||||
return context
|
||||
|
||||
|
||||
|
||||
@@ -347,6 +347,8 @@ class OrderInvoiceRegenerate(OrderView):
|
||||
else:
|
||||
if inv.canceled:
|
||||
messages.error(self.request, _('The invoice has already been canceled.'))
|
||||
elif inv.shredded:
|
||||
messages.error(self.request, _('The invoice has been cleaned of personal data.'))
|
||||
else:
|
||||
inv = regenerate_invoice(inv)
|
||||
self.order.log_action('pretix.event.order.invoice.regenerated', user=self.request.user, data={
|
||||
@@ -370,6 +372,8 @@ class OrderInvoiceReissue(OrderView):
|
||||
else:
|
||||
if inv.canceled:
|
||||
messages.error(self.request, _('The invoice has already been canceled.'))
|
||||
elif inv.shredded:
|
||||
messages.error(self.request, _('The invoice has been cleaned of personal data.'))
|
||||
else:
|
||||
c = generate_cancellation(inv)
|
||||
if self.order.status not in (Order.STATUS_CANCELED, Order.STATUS_REFUNDED):
|
||||
@@ -447,6 +451,10 @@ class InvoiceDownload(EventPermissionRequiredMixin, View):
|
||||
invoice_pdf(self.invoice.pk)
|
||||
self.invoice = Invoice.objects.get(pk=self.invoice.pk)
|
||||
|
||||
if self.invoice.shredded:
|
||||
messages.error(request, _('The invoice file is no longer stored on the server.'))
|
||||
return redirect(self.get_order_url())
|
||||
|
||||
if not self.invoice.file:
|
||||
# This happens if we have celery installed and the file will be generated in the background
|
||||
messages.warning(request, _('The invoice file has not yet been generated, we will generate it for you '
|
||||
@@ -648,7 +656,10 @@ class OrderModifyInformation(OrderQuestionsViewMixin, OrderView):
|
||||
_("We had difficulties processing your input. Please review the errors below."))
|
||||
return self.get(request, *args, **kwargs)
|
||||
self.invoice_form.save()
|
||||
self.order.log_action('pretix.event.order.modified', user=request.user)
|
||||
self.order.log_action('pretix.event.order.modified', {
|
||||
'invoice_data': self.invoice_form.cleaned_data,
|
||||
'data': [f.cleaned_data for f in self.forms]
|
||||
}, user=request.user)
|
||||
if self.invoice_form.has_changed():
|
||||
success_message = ('The invoice address has been updated. If you want to generate a new invoice, '
|
||||
'you need to do this manually.')
|
||||
|
||||
109
src/pretix/control/views/shredder.py
Normal file
109
src/pretix/control/views/shredder.py
Normal file
@@ -0,0 +1,109 @@
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views import View
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from pretix.base.models import CachedFile
|
||||
from pretix.base.services.shredder import export, shred
|
||||
from pretix.base.shredder import ShredError, shred_constraints
|
||||
from pretix.base.views.async import AsyncAction
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ShredderMixin:
|
||||
|
||||
@cached_property
|
||||
def shredders(self):
|
||||
return OrderedDict(
|
||||
sorted(self.request.event.get_data_shredders().items(), key=lambda s: s[1].verbose_name)
|
||||
)
|
||||
|
||||
|
||||
class StartShredView(EventPermissionRequiredMixin, ShredderMixin, TemplateView):
|
||||
permission = 'can_change_orders'
|
||||
template_name = 'pretixcontrol/shredder/index.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['shredders'] = self.shredders
|
||||
ctx['constraints'] = shred_constraints(self.request.event)
|
||||
return ctx
|
||||
|
||||
|
||||
class ShredDownloadView(EventPermissionRequiredMixin, ShredderMixin, TemplateView):
|
||||
permission = 'can_change_orders'
|
||||
template_name = 'pretixcontrol/shredder/download.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['shredders'] = self.shredders
|
||||
ctx['file'] = get_object_or_404(CachedFile, pk=kwargs.get("file"))
|
||||
return ctx
|
||||
|
||||
|
||||
class ShredExportView(EventPermissionRequiredMixin, ShredderMixin, AsyncAction, View):
|
||||
permission = 'can_change_orders'
|
||||
task = export
|
||||
known_errortypes = ['ShredError']
|
||||
|
||||
def get_success_message(self, value):
|
||||
return None
|
||||
|
||||
def get_success_url(self, value):
|
||||
return reverse('control:event.shredder.download', kwargs={
|
||||
'event': self.request.event.slug,
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'file': str(value)
|
||||
})
|
||||
|
||||
def get_error_url(self):
|
||||
return reverse('control:event.shredder.start', kwargs={
|
||||
'event': self.request.event.slug,
|
||||
'organizer': self.request.event.organizer.slug
|
||||
})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
constr = shred_constraints(self.request.event)
|
||||
if constr:
|
||||
return self.error(ShredError(self.get_error_url()))
|
||||
|
||||
return self.do(self.request.event.id, request.POST.getlist("shredder"))
|
||||
|
||||
|
||||
class ShredDoView(EventPermissionRequiredMixin, ShredderMixin, AsyncAction, View):
|
||||
permission = 'can_change_orders'
|
||||
task = shred
|
||||
known_errortypes = ['ShredError']
|
||||
|
||||
def get_success_url(self, value):
|
||||
return reverse('control:event.shredder.start', kwargs={
|
||||
'event': self.request.event.slug,
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
})
|
||||
|
||||
def get_success_message(self, value):
|
||||
return _('The selected data was deleted successfully.')
|
||||
|
||||
def get_error_url(self):
|
||||
return reverse('control:event.shredder.download', kwargs={
|
||||
'event': self.request.event.slug,
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'file': self.request.POST.get("file")
|
||||
})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
constr = shred_constraints(self.request.event)
|
||||
if constr:
|
||||
return self.error(ShredError(self.get_error_url()))
|
||||
|
||||
if not self.request.user.check_password(request.POST.get("password")):
|
||||
return self.error(ShredError(_("The current password you entered was not correct.")))
|
||||
|
||||
return self.do(self.request.event.id, request.POST.get("file"), request.POST.get("confirm_code"))
|
||||
Reference in New Issue
Block a user