import logging from django.utils.timezone import now from rest_framework import serializers from rest_framework.exceptions import ValidationError from rest_framework.response import Response from rest_framework.views import APIView from pretix.api.auth.device import DeviceTokenAuthentication from pretix.base.models import Device from pretix.base.models.devices import generate_api_token logger = logging.getLogger(__name__) class InitializationRequestSerializer(serializers.Serializer): token = serializers.CharField(max_length=190) hardware_brand = serializers.CharField(max_length=190) hardware_model = serializers.CharField(max_length=190) software_brand = serializers.CharField(max_length=190) software_version = serializers.CharField(max_length=190) class UpdateRequestSerializer(serializers.Serializer): hardware_brand = serializers.CharField(max_length=190) hardware_model = serializers.CharField(max_length=190) software_brand = serializers.CharField(max_length=190) software_version = serializers.CharField(max_length=190) class DeviceSerializer(serializers.ModelSerializer): organizer = serializers.SlugRelatedField(slug_field='slug', read_only=True) class Meta: model = Device fields = [ 'organizer', 'device_id', 'unique_serial', 'api_token', 'name' ] class InitializeView(APIView): authentication_classes = tuple() permission_classes = tuple() def post(self, request, format=None): serializer = InitializationRequestSerializer(data=request.data) serializer.is_valid(raise_exception=True) try: device = Device.objects.get(initialization_token=serializer.validated_data.get('token')) except Device.DoesNotExist: raise ValidationError({'token': ['Unknown initialization token.']}) if device.initialized: raise ValidationError({'token': ['This initialization token has already been used.']}) device.initialized = now() device.hardware_brand = serializer.validated_data.get('hardware_brand') device.hardware_model = serializer.validated_data.get('hardware_model') device.software_brand = serializer.validated_data.get('software_brand') device.software_version = serializer.validated_data.get('software_version') device.api_token = generate_api_token() device.save() device.log_action('pretix.device.initialized', data=serializer.validated_data, auth=device) serializer = DeviceSerializer(device) return Response(serializer.data) class UpdateView(APIView): authentication_classes = (DeviceTokenAuthentication,) def post(self, request, format=None): serializer = UpdateRequestSerializer(data=request.data) serializer.is_valid(raise_exception=True) device = request.auth device.hardware_brand = serializer.validated_data.get('hardware_brand') device.hardware_model = serializer.validated_data.get('hardware_model') device.software_brand = serializer.validated_data.get('software_brand') device.software_version = serializer.validated_data.get('software_version') device.save() device.log_action('pretix.device.updated', data=serializer.validated_data, auth=device) serializer = DeviceSerializer(device) return Response(serializer.data) class RollKeyView(APIView): authentication_classes = (DeviceTokenAuthentication,) def post(self, request, format=None): device = request.auth device.api_token = generate_api_token() device.save() device.log_action('pretix.device.keyroll', auth=device) serializer = DeviceSerializer(device) return Response(serializer.data) class RevokeKeyView(APIView): authentication_classes = (DeviceTokenAuthentication,) def post(self, request, format=None): device = request.auth device.revoked = True device.save() device.log_action('pretix.device.revoked', auth=device) serializer = DeviceSerializer(device) return Response(serializer.data)