blob: 1dd52ea938971620a4b52d16d412af7aac3799af [file] [log] [blame]
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +02001"""Serializers for Crashreport-related models."""
Borjan Tchakaloff340b6f32018-03-01 15:23:43 +04002from django.utils import timezone
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +02003from django.core.exceptions import ObjectDoesNotExist
Mitja Nikolausfd452f82018-11-07 11:53:59 +01004from django.utils.dateparse import parse_datetime
Dirk Vogtd1345212016-09-14 14:31:45 +02005from rest_framework import serializers
Dirk Vogtf2a33422016-10-11 17:17:26 +02006from rest_framework.exceptions import NotFound
Dirk Vogtd1345212016-09-14 14:31:45 +02007from rest_framework import permissions
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +02008
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +02009from crashreports.models import Crashreport, Device, HeartBeat, LogFile
Dirk Vogt67eb1482016-10-13 12:42:56 +020010from crashreports.permissions import user_is_hiccup_staff
11
12
13class PrivateField(serializers.ReadOnlyField):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020014 """Class for making a field private.
15
16 The private attribute can then only be read by Hiccup staff members
17 """
Dirk Vogt67eb1482016-10-13 12:42:56 +020018
19 def get_attribute(self, instance):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020020 """Get the private attribute.
21
Dirk Vogt67eb1482016-10-13 12:42:56 +020022 Given the *outgoing* object instance, return the primitive value
23 that should be used for this field.
24 """
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020025 if user_is_hiccup_staff(self.context["request"].user):
Dirk Vogt67eb1482016-10-13 12:42:56 +020026 return super(PrivateField, self).get_attribute(instance)
27 return -1
Dirk Vogtd1345212016-09-14 14:31:45 +020028
Mitja Nikolaus2189b5e2018-08-31 10:50:55 +020029 def to_internal_value(self, data):
30 """Transform the *incoming* primitive data into a native value.
31
32 Since PrivateField is read only, there will never be any incoming data,
33 thus we raise NotImplementedError.
34 """
35 raise NotImplementedError()
36
Dirk Vogtf2a33422016-10-11 17:17:26 +020037
Dirk Vogtd1345212016-09-14 14:31:45 +020038class CrashReportSerializer(serializers.ModelSerializer):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020039 """Serializer for CrashReport instances."""
40
Dirk Vogtf2a33422016-10-11 17:17:26 +020041 permission_classes = (permissions.AllowAny,)
Dirk Vogt83107df2017-05-02 12:04:19 +020042 logfiles = serializers.HyperlinkedRelatedField(
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020043 read_only=True, many=True, view_name="api_v1_logfiles_by_id"
44 )
Dirk Vogtf2a33422016-10-11 17:17:26 +020045 uuid = serializers.CharField(max_length=64)
Dirk Vogt67eb1482016-10-13 12:42:56 +020046 id = PrivateField()
47 device_local_id = serializers.IntegerField(required=False)
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020048 date = serializers.DateTimeField(default_timezone=timezone.utc)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020049
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020050 class Meta: # noqa: D106
Dirk Vogtd1345212016-09-14 14:31:45 +020051 model = Crashreport
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020052 exclude = ("device",)
Dirk Vogtf2a33422016-10-11 17:17:26 +020053
54 def create(self, validated_data):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020055 """Create a crashreport.
56
57 Args:
58 validated_data: Data of the crashreport, excluding the device
59
60 Returns: The created report
61
62 """
Dirk Vogtf2a33422016-10-11 17:17:26 +020063 try:
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020064 device = Device.objects.get(uuid=validated_data["uuid"])
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020065 except ObjectDoesNotExist:
Dirk Vogtf2a33422016-10-11 17:17:26 +020066 raise NotFound(detail="uuid does not exist")
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020067 validated_data.pop("uuid", None)
Dirk Vogtf2a33422016-10-11 17:17:26 +020068 report = Crashreport(**validated_data)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020069 report.device = device
Dirk Vogtf2a33422016-10-11 17:17:26 +020070 report.save()
71 return report
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020072
73
74class HeartBeatSerializer(serializers.ModelSerializer):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020075 """Serializer for HeartBeat instances."""
76
Dirk Vogt36635692016-10-17 12:19:10 +020077 permission_classes = (permissions.IsAuthenticated,)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020078 uuid = serializers.CharField(max_length=64)
Dirk Vogt67eb1482016-10-13 12:42:56 +020079 id = PrivateField()
80 device_local_id = serializers.IntegerField(required=False)
Mitja Nikolausfd452f82018-11-07 11:53:59 +010081 date = serializers.DateField()
Dirk Vogte1784882016-10-13 16:09:38 +020082
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020083 class Meta: # noqa: D106
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020084 model = HeartBeat
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020085 exclude = ("device",)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020086
87 def create(self, validated_data):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020088 """Create a heartbeat report.
89
90 Args:
91 validated_data: Data of the heartbeat, excluding the device
92
93 Returns: The created heartbeat
94
95 """
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020096 try:
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020097 device = Device.objects.get(uuid=validated_data["uuid"])
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +020098 except ObjectDoesNotExist:
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020099 raise NotFound(detail="uuid does not exist")
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200100 validated_data.pop("uuid", None)
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200101 heartbeat = HeartBeat(**validated_data)
102 heartbeat.device = device
103 heartbeat.save()
104 return heartbeat
105
Mitja Nikolausfd452f82018-11-07 11:53:59 +0100106 def to_internal_value(self, data):
107 """Parse serialized heartbeat representations.
108
109 Incoming 'date' values that are datetime values (including time) are
110 changed so that only the date part of the value is deserialized.
111 Initially, the date was a datetime field and Hiccup clients can still
112 send datetime values.
113 """
114 datetime = parse_datetime(data["date"])
115 if datetime:
116 updated_data = data.copy()
117 updated_data["date"] = datetime.date().isoformat()
118 data = updated_data
119
120 return super(HeartBeatSerializer, self).to_internal_value(data)
121
Dirk Vogtf2a33422016-10-11 17:17:26 +0200122
Dirk Vogt83107df2017-05-02 12:04:19 +0200123class LogFileSerializer(serializers.ModelSerializer):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +0200124 """Serializer for LogFile instances."""
125
Dirk Vogt83107df2017-05-02 12:04:19 +0200126 permission_classes = (permissions.IsAdminUser,)
127
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +0200128 class Meta: # noqa: D106
Dirk Vogt83107df2017-05-02 12:04:19 +0200129 model = LogFile
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200130 fields = "__all__"
Dirk Vogt83107df2017-05-02 12:04:19 +0200131
132
Dirk Vogtf2a33422016-10-11 17:17:26 +0200133class DeviceSerializer(serializers.ModelSerializer):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +0200134 """Serializer for Device instances."""
Dirk Vogtc9e10ab2016-10-12 13:58:15 +0200135
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +0200136 permission_classes = (permissions.IsAdminUser,)
137 board_date = serializers.DateTimeField(default_timezone=timezone.utc)
138 last_heartbeat = serializers.DateTimeField(default_timezone=timezone.utc)
139
140 class Meta: # noqa: D106
Dirk Vogtf2a33422016-10-11 17:17:26 +0200141 model = Device
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200142 fields = "__all__"
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100143
144
145class DeviceCreateSerializer(DeviceSerializer):
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +0200146 """Serializer for creating Device instances."""
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100147
Mitja Nikolaus5c3e0572018-07-30 13:36:14 +0200148 class Meta: # noqa: D106
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100149 model = Device
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200150 fields = ("board_date", "chipset")
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100151 extra_kwargs = {
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200152 "board_date": {"required": True},
153 "chipset": {"required": True},
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100154 }