diff --git a/push_notifications/admin.py b/push_notifications/admin.py index 7c6d1767..477156b0 100644 --- a/push_notifications/admin.py +++ b/push_notifications/admin.py @@ -128,9 +128,10 @@ def disable(self, request, queryset): class GCMDeviceAdmin(DeviceAdmin): list_display = ( - "__str__", "device_id", "user", "active", "date_created", "cloud_message_type" + "__str__", "user", "active", "date_created", "cloud_message_type" ) list_filter = ("active", "cloud_message_type") + search_fields = ("registration_id", "user__username", "user__email") class WebPushDeviceAdmin(DeviceAdmin): diff --git a/push_notifications/api/rest_framework.py b/push_notifications/api/rest_framework.py index 6efff4ae..9f4b5231 100644 --- a/push_notifications/api/rest_framework.py +++ b/push_notifications/api/rest_framework.py @@ -1,3 +1,9 @@ +import logging + +from django.db import IntegrityError +logger = logging.getLogger(__name__) +logger.setLevel(logging.INFO) + from rest_framework import permissions, status from rest_framework.fields import IntegerField from rest_framework.response import Response @@ -153,7 +159,16 @@ def create(self, request, *args, **kwargs): self.perform_update(serializer) return Response(serializer.data) else: - self.perform_create(serializer) + try: + self.perform_create(serializer) + except IntegrityError: + instance = self.queryset.model.objects.filter( + registration_id=request.data[self.lookup_field] + ).first() + if instance: + logger.error(f"registration_id already exist {instance.registration_id} user: {instance.user} created time for that {instance.date_created}", exc_info=True) + else: + logger.error(f"registration_id that already exist {instance}", exc_info=True) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) @@ -168,6 +183,61 @@ def perform_update(self, serializer): return super(DeviceViewSetMixin, self).perform_update(serializer) +class CustomDeviceViewSetMixin: + lookup_field = "registration_id" + + def create(self, request, *args, **kwargs): + serializer = None + is_update = False + log_error = False + + if SETTINGS.get("UPDATE_ON_DUPLICATE_REG_ID") and self.lookup_field in request.data: + old_registration_id = request.data.get("old_registration_id", None) + new_registration_id = request.data.get("registration_id", None) + if new_registration_id and not old_registration_id: + instance = self.queryset.model.objects.filter( + registration_id=new_registration_id + ).first() + if instance: + serializer = self.get_serializer(instance, data=request.data) + is_update = True + if not serializer: + serializer = self.get_serializer(data=request.data) + elif new_registration_id and old_registration_id: + instance = self.queryset.model.objects.filter( + registration_id=old_registration_id + ).first() + if instance: + serializer = self.get_serializer(instance, data=request.data) + is_update = True + if not serializer: + serializer = self.get_serializer(data=request.data) + log_error = True + + serializer.is_valid(raise_exception=True) + if is_update: + self.perform_update(serializer) + return Response(serializer.data) + else: + self.perform_create(serializer, log_error=log_error) + headers = self.get_success_headers(serializer.data) + return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + + def perform_create(self, serializer, log_error=False): + if self.request.user.is_authenticated: + serializer.save(user=self.request.user) + if log_error: + logger.error( + f"No device found against old_registration_id created with new registration_id. User:{self.request.user.id}", + exc_info=True) + return super(CustomDeviceViewSetMixin, self).perform_create(serializer) + + def perform_update(self, serializer): + if self.request.user.is_authenticated: + serializer.save(user=self.request.user) + return super(CustomDeviceViewSetMixin, self).perform_update(serializer) + + class AuthorizedMixin: permission_classes = (permissions.IsAuthenticated, IsOwner) @@ -191,10 +261,19 @@ class GCMDeviceViewSet(DeviceViewSetMixin, ModelViewSet): serializer_class = GCMDeviceSerializer +class CustomGCMDeviceViewSet(CustomDeviceViewSetMixin, ModelViewSet): + queryset = GCMDevice.objects.all() + serializer_class = GCMDeviceSerializer + + class GCMDeviceAuthorizedViewSet(AuthorizedMixin, GCMDeviceViewSet): pass +class CustomGCMDeviceAuthorizedViewSet(AuthorizedMixin, CustomGCMDeviceViewSet): + pass + + class WNSDeviceViewSet(DeviceViewSetMixin, ModelViewSet): queryset = WNSDevice.objects.all() serializer_class = WNSDeviceSerializer