doorcontrol: Move Door names from HIDEvents into new table

This commit is contained in:
Adam Goldsmith 2023-09-19 01:06:24 -04:00
parent cb8bf3da4f
commit ee001b0256
6 changed files with 101 additions and 10 deletions

View File

@ -1,6 +1,11 @@
from django.contrib import admin from django.contrib import admin
from .models import HIDEvent from .models import Door, HIDEvent
@admin.register(Door)
class DoorAdmin(admin.ModelAdmin):
pass
class IsRedFilter(admin.SimpleListFilter): class IsRedFilter(admin.SimpleListFilter):
@ -23,10 +28,10 @@ class IsRedFilter(admin.SimpleListFilter):
@admin.register(HIDEvent) @admin.register(HIDEvent)
class HIDEventAdmin(admin.ModelAdmin): class HIDEventAdmin(admin.ModelAdmin):
search_fields = ["forename", "surname", "cardholder_id"] search_fields = ["forename", "surname", "cardholder_id"]
list_display = ["door_name", "timestamp", "event_type", "description", "is_red"] list_display = ["timestamp", "door", "event_type", "description", "is_red"]
list_filter = [ list_filter = [
"timestamp", "timestamp",
"door_name", "door",
"event_type", "event_type",
IsRedFilter, IsRedFilter,
] ]

View File

@ -95,4 +95,10 @@ class Migration(migrations.Migration):
"managed": False, "managed": False,
}, },
), ),
migrations.AddConstraint(
model_name="hidevent",
constraint=models.UniqueConstraint(
fields=("door_name", "timestamp", "event_type"), name="unique_hidevent"
),
),
] ]

View File

@ -0,0 +1,74 @@
# Generated by Django 4.2.5 on 2023-09-19 04:20
from django.db import migrations, models
import django.db.models.deletion
def link_events_to_doors(apps, schema_editor):
HIDEvent = apps.get_model("doorcontrol", "HIDEvent")
Door = apps.get_model("doorcontrol", "Door")
for event in HIDEvent.objects.all():
door, created = Door.objects.get_or_create(name=event.door_name)
event.door = door
event.save()
class Migration(migrations.Migration):
dependencies = [
("doorcontrol", "0001_initial"),
]
operations = [
migrations.AlterModelOptions(
name="hidevent",
options={"ordering": ("-timestamp",)},
),
migrations.CreateModel(
name="Door",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=64, unique=True)),
],
),
# create nullable foreign key to door
migrations.AddField(
model_name="hidevent",
name="door",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="doorcontrol.door",
null=True,
),
),
# create new Doors and link them to HID Events
migrations.RunPython(link_events_to_doors, atomic=True),
# make door foreign key not nullable
migrations.AlterField(
model_name="hidevent",
name="door",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="doorcontrol.door"
),
),
# remove old constaint
migrations.RemoveConstraint(model_name="hidevent", name="unique_hidevent"),
# remove old name field
migrations.RemoveField(
model_name="hidevent",
name="door_name",
),
migrations.AddConstraint(
model_name="hidevent",
constraint=models.UniqueConstraint(
fields=("door", "timestamp", "event_type"), name="unique_hidevent"
),
),
]

View File

@ -3,6 +3,13 @@ from django.db.models import ExpressionWrapper, F, Func, Q
from django.db.models.functions import Mod from django.db.models.functions import Mod
class Door(models.Model):
name = models.CharField(max_length=64, unique=True)
def __str__(self):
return self.name
class HIDEventQuerySet(models.QuerySet): class HIDEventQuerySet(models.QuerySet):
def with_is_red(self): def with_is_red(self):
"""Based on `function isRedEvent` from /html/hid-global.js on a HID EDGE EVO Solo""" """Based on `function isRedEvent` from /html/hid-global.js on a HID EDGE EVO Solo"""
@ -98,7 +105,7 @@ class HIDEvent(models.Model):
DOOR_UNLOCKED = 12032, "Door Unlocked" DOOR_UNLOCKED = 12032, "Door Unlocked"
DOOR_LOCKED = 12033, "Door Locked" DOOR_LOCKED = 12033, "Door Locked"
door_name = models.CharField(max_length=64, db_column="doorName") door = models.ForeignKey(Door, on_delete=models.CASCADE)
timestamp = models.DateTimeField() timestamp = models.DateTimeField()
event_type = models.IntegerField(db_column="eventType", choices=EventType.choices) event_type = models.IntegerField(db_column="eventType", choices=EventType.choices)
reader_address = models.IntegerField(db_column="readerAddress") reader_address = models.IntegerField(db_column="readerAddress")
@ -156,7 +163,7 @@ class HIDEvent(models.Model):
return event_types.get(self.event_type, f"Unknown Event Type {self.event_type}") return event_types.get(self.event_type, f"Unknown Event Type {self.event_type}")
def __str__(self): def __str__(self):
return f"{self.door_name} {self.timestamp} - {self.description}" return f"{self.door.name} {self.timestamp} - {self.description}"
def decoded_card_number(self) -> str: def decoded_card_number(self) -> str:
"""Requires annotations from `with_decoded_card_number`""" """Requires annotations from `with_decoded_card_number`"""
@ -173,9 +180,8 @@ class HIDEvent(models.Model):
class Meta: class Meta:
constraints = [ constraints = [
models.UniqueConstraint( models.UniqueConstraint(
fields=["door_name", "timestamp", "event_type"], name="unique_hidevent" fields=["door", "timestamp", "event_type"], name="unique_hidevent"
) )
] ]
managed = False
db_table = "hidevent" db_table = "hidevent"
ordering = ("-timestamp",) ordering = ("-timestamp",)

View File

@ -13,8 +13,8 @@ class DoorControlRouter:
return None return None
def allow_migrate(self, db, app_label, model_name=None, **hints): def allow_migrate(self, db, app_label, model_name=None, **hints):
if db == self.db: if app_label == self.app_label:
return False return db == self.db
return None return None
def allow_relation(self, obj1, obj2, **hints): def allow_relation(self, obj1, obj2, **hints):

View File

@ -163,7 +163,7 @@ class DeniedAccess(BaseAccessReport):
return [ return [
{ {
"timestamp": event.timestamp, "timestamp": event.timestamp,
"door name": event.door_name, "door name": event.door.name,
"event type": HIDEvent.EventType(event.event_type).label, "event type": HIDEvent.EventType(event.event_type).label,
"name": " ".join( "name": " ".join(
(n for n in [event.forename, event.surname] if n is not None) (n for n in [event.forename, event.surname] if n is not None)