diff --git a/src/pretix/api/views/device.py b/src/pretix/api/views/device.py index 7e717c23bc..24c69ae617 100644 --- a/src/pretix/api/views/device.py +++ b/src/pretix/api/views/device.py @@ -93,6 +93,9 @@ class InitializeView(APIView): if device.initialized: raise ValidationError({'token': ['This initialization token has already been used.']}) + if device.revoked: + raise ValidationError({'token': ['This initialization token has been revoked.']}) + device.initialized = now() device.hardware_brand = serializer.validated_data.get('hardware_brand') device.hardware_model = serializer.validated_data.get('hardware_model') diff --git a/src/pretix/control/templates/pretixcontrol/organizers/devices.html b/src/pretix/control/templates/pretixcontrol/organizers/devices.html index 9416836438..0274d2e4c8 100644 --- a/src/pretix/control/templates/pretixcontrol/organizers/devices.html +++ b/src/pretix/control/templates/pretixcontrol/organizers/devices.html @@ -162,16 +162,19 @@ {% trans "Connect" %} - {% elif d.api_token %} + {% endif %} + {% if not d.initialized or d.api_token %} {% trans "Revoke access" %} {% endif %} - - - {% trans "Logs" %} - + {% if d.initialized %} + + + {% trans "Logs" %} + + {% endif %} diff --git a/src/pretix/control/views/organizer.py b/src/pretix/control/views/organizer.py index 239de7ee98..d824a6dab1 100644 --- a/src/pretix/control/views/organizer.py +++ b/src/pretix/control/views/organizer.py @@ -1184,7 +1184,7 @@ class DeviceRevokeView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi def get(self, request, *args, **kwargs): self.object = self.get_object() - if not self.object.api_token: + if self.object.revoked: messages.success(request, _('This device currently does not have access.')) return redirect(reverse('control:organizer.devices', kwargs={ 'organizer': self.request.organizer.slug, diff --git a/src/tests/api/test_deviceauth.py b/src/tests/api/test_deviceauth.py index 4fd9bd9bf1..1e8d7017b4 100644 --- a/src/tests/api/test_deviceauth.py +++ b/src/tests/api/test_deviceauth.py @@ -72,6 +72,21 @@ def test_initialize_used_token(client, device: Device): assert resp.data == {'token': ['This initialization token has already been used.']} +@pytest.mark.django_db +def test_initialize_revoked_token(client, new_device: Device): + new_device.revoked = True + new_device.save() + resp = client.post('/api/v1/device/initialize', { + 'token': new_device.initialization_token, + 'hardware_brand': 'Samsung', + 'hardware_model': 'Galaxy S', + 'software_brand': 'pretixdroid', + 'software_version': '4.0.0' + }) + assert resp.status_code == 400 + assert resp.data == {'token': ['This initialization token has been revoked.']} + + @pytest.mark.django_db def test_initialize_valid_token(client, new_device: Device): resp = client.post('/api/v1/device/initialize', { diff --git a/src/tests/control/test_devices.py b/src/tests/control/test_devices.py index 60e2d836e6..d3a678410e 100644 --- a/src/tests/control/test_devices.py +++ b/src/tests/control/test_devices.py @@ -110,6 +110,17 @@ def test_revoke_device(event, admin_user, admin_team, device, client): assert device.revoked +@pytest.mark.django_db +def test_revoke_device_before_initialization(event, admin_user, admin_team, device, client): + client.login(email='dummy@dummy.dummy', password='dummy') + device.save() + + client.get('/control/organizer/dummy/device/{}/revoke'.format(device.pk)) + client.post('/control/organizer/dummy/device/{}/revoke'.format(device.pk), {}, follow=True) + device.refresh_from_db() + assert device.revoked + + @pytest.mark.django_db def test_bulk_update_device(event, admin_user, admin_team, device, client): client.login(email='dummy@dummy.dummy', password='dummy')