diff --git a/memberportal/access/models.py b/memberportal/access/models.py index be4ad2af..57d3e8e4 100644 --- a/memberportal/access/models.py +++ b/memberportal/access/models.py @@ -90,6 +90,59 @@ def __str__(self): def log_access(self, member_id, success=True): pass + def log_event(self, description=None, event_type=None, data=None): + if self.type == "door": + log_event( + description=description, event_type=event_type, data=data, door=self + ) + return True + elif self.type == "interlock": + log_event( + description=description, + event_type=event_type, + data=data, + interlock=self, + ) + return True + elif self.type == "memberbucks": + log_event( + description=description, + event_type=event_type, + data=data, + memberbucks_device=self, + ) + return True + + def log_connected(self): + self.log_event( + description=f"Device connected.", + ) + + def log_disconnected(self): + self.log_event( + description=f"Device disconnected.", + ) + + def log_authenticated(self): + self.log_event( + description=f"Device authenticated.", + ) + + def log_force_rebooted(self): + self.log_event( + description=f"Device manually rebooted.", + ) + + def log_force_sync(self): + self.log_event( + description=f"Device manually synced.", + ) + + def log_force_bump(self): + self.log_event( + description=f"Device manually bumped.", + ) + def sync(self, request=None): if self.type != "door": logger.debug( diff --git a/memberportal/api_access/consumers.py b/memberportal/api_access/consumers.py index ebaf7ac2..9d2e9e12 100644 --- a/memberportal/api_access/consumers.py +++ b/memberportal/api_access/consumers.py @@ -10,7 +10,7 @@ MemberbucksDevice, AccessControlledDeviceAPIKey, ) -from profile.models import Profile +from profile.models import Profile, log_event from constance import config logger = logging.getLogger("app") @@ -47,6 +47,7 @@ def connect(self): ) self.device = device_object self.device.checkin() + self.device.log_connected() # Set the channels group name and add the device to the group self.device_group_name = self.device.serial_number @@ -75,6 +76,7 @@ def connect(self): def disconnect(self, close_code): logger.info("Device disconnected!") logger.info("Device was connected for %s", self.last_seen - self.connected_at) + self.device.log_disconnected() async_to_sync(self.channel_layer.group_discard)( self.device_group_name, self.channel_name ) @@ -106,6 +108,7 @@ def receive_json(self, content=None, **kwargs): ) self.authorised = True self.send_json({"authorised": True}) + self.device.log_authenticated() self.sync_users({}) # sync the cards down self.update_device_locked_out() diff --git a/memberportal/api_access/views.py b/memberportal/api_access/views.py index 48a5c47e..7df945ec 100644 --- a/memberportal/api_access/views.py +++ b/memberportal/api_access/views.py @@ -153,6 +153,7 @@ class SyncInterlock(APIView): def post(self, request, interlock_id): interlock = Interlock.objects.get(pk=interlock_id) + interlock.log_force_sync() return Response({"success": interlock.sync()}) @@ -166,6 +167,7 @@ class RebootInterlock(APIView): def post(self, request, interlock_id): interlock = Interlock.objects.get(pk=interlock_id) + interlock.log_force_rebooted() return Response({"success": interlock.reboot()}) @@ -179,6 +181,7 @@ class SyncDoor(APIView): def post(self, request, door_id): door = Doors.objects.get(pk=door_id) + door.log_force_sync() return Response({"success": door.sync(request=request)}) @@ -192,6 +195,7 @@ class RebootDoor(APIView): def post(self, request, door_id): door = Doors.objects.get(pk=door_id) + door.log_force_rebooted() return Response({"success": door.reboot(request=request)}) @@ -208,7 +212,9 @@ def post(self, request, door_id): # BUT we still need to check if the API is enabled or it's a user making the request if config.ENABLE_DOOR_BUMP_API or request.user.is_authenticated: door = Doors.objects.get(pk=door_id) - return Response({"success": door.bump()}) + bumped = door.bump() + door.log_force_bump() + return Response({"success": bumped}) else: return Response( {"success": False, "error": "This API is disabled in the config."}, diff --git a/memberportal/profile/models.py b/memberportal/profile/models.py index 5921e7ea..04e169a0 100644 --- a/memberportal/profile/models.py +++ b/memberportal/profile/models.py @@ -15,6 +15,7 @@ from constance import config from api_general.models import SiteSession from api_admin_tools.models import MemberTier, PaymentPlan +from access.models import Doors, Interlock, MemberbucksDevice import json import uuid import logging @@ -32,8 +33,9 @@ ("memberbucks", "Memberbucks related event"), ("spacebucks", "Spacebucks related event"), ("profile", "Member profile was edited or updated"), - ("interlock", "Interlock related event"), - ("door", "Door related event"), + ("interlock", "Interlock device related event"), + ("door", "Door device related event"), + ("memberbucksdevice", "Memberbucks device related event"), ("email", "An email was sent or attempted to be sent"), ("admin", "An admin performed an action"), ("error", "An event or action caused an error"), @@ -47,6 +49,27 @@ class Log(models.Model): description = models.CharField("Description of action/event", max_length=500) data = models.TextField("Extra data for debugging action/event") date = models.DateTimeField(auto_now_add=True) + door = models.ForeignKey( + Doors, + on_delete=models.CASCADE, + null=True, + default=None, + blank=True, + ) + interlock = models.ForeignKey( + Interlock, + on_delete=models.CASCADE, + null=True, + default=None, + blank=True, + ) + memberbucks_device = models.ForeignKey( + MemberbucksDevice, + on_delete=models.CASCADE, + null=True, + default=None, + blank=True, + ) class UserEventLog(Log): @@ -57,8 +80,17 @@ class EventLog(Log): pass -def log_event(description, event_type, data=""): - EventLog(description=description, logtype=event_type, data=data).save() +def log_event( + description, event_type, data="", door=None, interlock=None, memberbucks_device=None +): + EventLog( + description=description, + logtype=event_type, + data=data, + door=door, + interlock=interlock, + memberbucks_device=memberbucks_device, + ).save() class UserManager(BaseUserManager):