import traceback from django.utils.timezone import now from django.http import JsonResponse from rest_framework import status from apps.pos_device.models import Sessions, DeviceVersion from apps.authentication.models import Organization class POSDeviceException(Exception): """Custom Exception for POS Validation""" def __init__(self, message, code=400): self.message = message self.code = code super().__init__(message) def get_client_ip(request): forwarded = request.META.get('HTTP_X_FORWARDED_FOR') return forwarded.split(',')[0] if forwarded else request.META.get('REMOTE_ADDR') class PosDeviceValidationMiddleware: REQUIRED_HEADERS = [ 'device-mac', 'device-serial', 'device-name', 'device-sdk', 'device-provider', 'device-version', 'device-vname', 'device-lng', 'device-lot' # noqa ] def __init__(self, get_response): self.get_response = get_response def __call__(self, request): try: if request.path.startswith("/pos_device/pos/"): self.validate_request(request) return self.get_response(request) except POSDeviceException as e: return JsonResponse({'message': e.message}, status=e.code) # for response 500 errors in json format except Exception as e: if request.path.startswith('/pos_device/pos/'): return JsonResponse( {"message": str(e), "traceback": traceback.format_exc()}, status=500 ) raise def validate_request(self, request): headers = request.headers data = {key: headers.get(key) for key in self.REQUIRED_HEADERS} missing = [key for key, value in data.items() if not value] if missing: raise POSDeviceException(f'پارامترهای ارسالی ناقص هستند: {", ".join(missing)}') # noqa provider_name = data['device-provider'] organization = Organization.objects.filter(en_name=provider_name).first() # noqa if not organization: raise POSDeviceException('شرکت پرداخت الکترونیک پشتیبانی نمی‌شود!', code=402) # noqa if not organization.active: raise POSDeviceException('شرکت پرداخت الکترونیک مسدود شده است!', code=402) # noqa versions = DeviceVersion.objects.filter(organization=organization) if not versions.exists(): raise POSDeviceException('هیچ نسخه‌ای برای این شرکت ثبت نشده است!', code=402) # noqa current_version = versions.filter(code=data['device-version']).first() if not current_version or current_version.remove: raise POSDeviceException( f'نسخه {data["device-vname"]} منقضی شده است. لطفا بروزرسانی کنید.', code=402 # noqa ) session = Sessions.objects.filter( device__serial=data['device-serial'], sdk=data['device-sdk'] ).first() if session: session.session_last_seen_date = now() session.lng = data['device-lng'] session.lot = data['device-lot'] session.version = data['device-version'] session.ip = get_client_ip(request) session.save()