LogEntry: Add a direct relationship to organizer (#3732)

* LogEntry: Add a direct relationship to organizer

* Update src/pretix/base/models/log.py

Co-authored-by: Richard Schreiber <schreiber@rami.io>

* Fix condition

* Fix query count

* REbase migration

* Fix tests

---------

Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
Raphael Michel
2023-11-22 16:22:33 +01:00
committed by GitHub
parent 2ef015015a
commit b639ac850f
4 changed files with 73 additions and 5 deletions

View File

@@ -384,7 +384,7 @@ def register_default_webhook_events(sender, **kwargs):
def notify_webhooks(logentry_ids: list): def notify_webhooks(logentry_ids: list):
if not isinstance(logentry_ids, list): if not isinstance(logentry_ids, list):
logentry_ids = [logentry_ids] logentry_ids = [logentry_ids]
qs = LogEntry.all.select_related('event', 'event__organizer').filter(id__in=logentry_ids) qs = LogEntry.all.select_related('event', 'event__organizer', 'organizer_link').filter(id__in=logentry_ids)
_org, _at, webhooks = None, None, None _org, _at, webhooks = None, None, None
for logentry in qs: for logentry in qs:
if not logentry.organizer: if not logentry.organizer:

View File

@@ -0,0 +1,56 @@
# Generated by Django 4.2.4 on 2023-11-20 12:38
import django.db.models.deletion
from django.db import migrations, models
from django.db.models import F, OuterRef, Subquery
def backfill_organizer(apps, schema_editor):
LogEntry = apps.get_model("pretixbase", "LogEntry")
Event = apps.get_model("pretixbase", "Event")
ContentType = apps.get_model("contenttypes", "ContentType")
LogEntry.objects.filter(
organizer_link__isnull=True, event__isnull=False
).update(organizer_link_id=Subquery(
Event.objects.filter(pk=OuterRef('event_id')).values('organizer_id'),
)
)
for ct in ContentType.objects.all():
try:
model = apps.get_model(ct.app_label, ct.model)
except LookupError:
continue
if "organizer" in model._meta.fields:
LogEntry.objects.filter(
organizer_link__isnull=True, event__isnull=True, content_type=ct,
).update(
organizer_link_id=Subquery(model.objects.filter(pk=OuterRef('object_id')).values('organizer_id'))
)
elif "event" in model._meta.fields:
LogEntry.objects.filter(
organizer_link__isnull=True, event__isnull=True, content_type=ct,
).update(
organizer_link_id=Subquery(model.objects.filter(pk=OuterRef('object_id')).values('event__organizer_id'))
)
class Migration(migrations.Migration):
dependencies = [
("pretixbase", "0251_order_invoice_dirty"),
]
operations = [
migrations.AddField(
model_name="logentry",
name="organizer_link",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="pretixbase.organizer",
),
),
migrations.RunPython(
backfill_organizer,
)
]

View File

@@ -84,13 +84,21 @@ class LoggingMixin:
from .devices import Device from .devices import Device
from .event import Event from .event import Event
from .log import LogEntry from .log import LogEntry
from .organizer import TeamAPIToken from .organizer import Organizer, TeamAPIToken
event = None event = None
if isinstance(self, Event): organizer_id = None
if isinstance(self, Organizer):
organizer_id = self.pk
elif isinstance(self, Event):
event = self event = self
organizer_id = self.organizer_id
elif hasattr(self, 'event'): elif hasattr(self, 'event'):
event = self.event event = self.event
organizer_id = self.event.organizer_id
elif hasattr(self, 'organizer_id'):
organizer_id = self.organizer_id
if user and not user.is_authenticated: if user and not user.is_authenticated:
user = None user = None
@@ -106,7 +114,8 @@ class LoggingMixin:
elif isinstance(api_token, TeamAPIToken): elif isinstance(api_token, TeamAPIToken):
kwargs['api_token'] = api_token kwargs['api_token'] = api_token
logentry = LogEntry(content_object=self, user=user, action_type=action, event=event, **kwargs) logentry = LogEntry(content_object=self, user=user, action_type=action, event=event,
organizer_link_id=organizer_id, **kwargs)
if isinstance(data, dict): if isinstance(data, dict):
sensitivekeys = ['password', 'secret', 'api_key'] sensitivekeys = ['password', 'secret', 'api_key']

View File

@@ -78,6 +78,7 @@ class LogEntry(models.Model):
device = models.ForeignKey('Device', null=True, blank=True, on_delete=models.PROTECT) device = models.ForeignKey('Device', null=True, blank=True, on_delete=models.PROTECT)
oauth_application = models.ForeignKey('pretixapi.OAuthApplication', null=True, blank=True, on_delete=models.PROTECT) oauth_application = models.ForeignKey('pretixapi.OAuthApplication', null=True, blank=True, on_delete=models.PROTECT)
event = models.ForeignKey('Event', null=True, blank=True, on_delete=models.SET_NULL) event = models.ForeignKey('Event', null=True, blank=True, on_delete=models.SET_NULL)
organizer_link = models.ForeignKey('Organizer', null=True, blank=True, on_delete=models.PROTECT)
action_type = models.CharField(max_length=255) action_type = models.CharField(max_length=255)
data = models.TextField(default='{}') data = models.TextField(default='{}')
visible = models.BooleanField(default=True) visible = models.BooleanField(default=True)
@@ -126,7 +127,9 @@ class LogEntry(models.Model):
def organizer(self): def organizer(self):
from .organizer import Organizer from .organizer import Organizer
if self.event: if self.organizer_link:
return self.organizer_link
elif self.event:
return self.event.organizer return self.event.organizer
elif hasattr(self.content_object, 'event'): elif hasattr(self.content_object, 'event'):
return self.content_object.event.organizer return self.content_object.event.organizer