serializers.py 14 KB
Newer Older
Maël Kervella's avatar
Maël Kervella committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
# Copyright © 2018 Mael Kervella
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Maël Kervella's avatar
Maël Kervella committed
21
"""
Maël Kervella's avatar
Maël Kervella committed
22 23
Serializers for the API app
"""
Maël Kervella's avatar
Maël Kervella committed
24 25

from rest_framework import serializers
26
from users.models import Club, Adherent
Maël Kervella's avatar
Maël Kervella committed
27 28
from machines.models import (
    Interface,
Maël Kervella's avatar
Maël Kervella committed
29 30 31 32 33 34 35
    IpType,
    Extension,
    IpList,
    Domain,
    Txt,
    Mx,
    Srv,
Maël Kervella's avatar
Maël Kervella committed
36
    Service_link,
Maël Kervella's avatar
Maël Kervella committed
37 38 39
    Ns,
    OuverturePort,
    Ipv6List
Maël Kervella's avatar
Maël Kervella committed
40
)
Maël Kervella's avatar
Maël Kervella committed
41 42 43


class ServiceLinkSerializer(serializers.ModelSerializer):
Maël Kervella's avatar
Maël Kervella committed
44 45
    """ Serializer for the ServiceLink objects """

Maël Kervella's avatar
Maël Kervella committed
46 47 48 49 50 51 52
    name = serializers.CharField(source='service.service_type')

    class Meta:
        model = Service_link
        fields = ('name',)


53
class MailingSerializer(serializers.ModelSerializer):
Maël Kervella's avatar
Maël Kervella committed
54 55
    """ Serializer to build Mailing objects """

56 57 58 59 60 61 62 63
    name = serializers.CharField(source='pseudo')

    class Meta:
        model = Club
        fields = ('name',)


class MailingMemberSerializer(serializers.ModelSerializer):
Maël Kervella's avatar
Maël Kervella committed
64 65 66
    """ Serializer fot the Adherent objects (who belong to a
    Mailing) """

67 68
    class Meta:
        model = Adherent
Maël Kervella's avatar
Maël Kervella committed
69
        fields = ('email',)
70 71


Maël Kervella's avatar
Maël Kervella committed
72
class IpTypeField(serializers.RelatedField):
Maël Kervella's avatar
Maël Kervella committed
73 74
    """ Serializer for an IpType object field """

Maël Kervella's avatar
Maël Kervella committed
75 76 77
    def to_representation(self, value):
        return value.type

Maël Kervella's avatar
Maël Kervella committed
78 79 80
    def to_internal_value(self, data):
        pass

Maël Kervella's avatar
Maël Kervella committed
81 82

class IpListSerializer(serializers.ModelSerializer):
Maël Kervella's avatar
Maël Kervella committed
83 84
    """ Serializer for an Ipv4List obejct using the IpType serialization """

Maël Kervella's avatar
Maël Kervella committed
85 86 87 88 89 90 91 92
    ip_type = IpTypeField(read_only=True)

    class Meta:
        model = IpList
        fields = ('ipv4', 'ip_type')


class Ipv6ListSerializer(serializers.ModelSerializer):
Maël Kervella's avatar
Maël Kervella committed
93 94
    """ Serializer for an Ipv6List object """

Maël Kervella's avatar
Maël Kervella committed
95 96 97 98 99
    class Meta:
        model = Ipv6List
        fields = ('ipv6', 'slaac_ip')


Maël Kervella's avatar
Maël Kervella committed
100
class InterfaceSerializer(serializers.ModelSerializer):
Maël Kervella's avatar
Maël Kervella committed
101 102 103
    """ Serializer for an Interface object. Use SerializerMethodField
    to get ForeignKey values """

Maël Kervella's avatar
Maël Kervella committed
104
    ipv4 = IpListSerializer(read_only=True)
Maël Kervella's avatar
Maël Kervella committed
105
    # TODO : use serializer.RelatedField to avoid duplicate code
Maël Kervella's avatar
Maël Kervella committed
106 107 108 109 110 111 112 113
    mac_address = serializers.SerializerMethodField('get_macaddress')
    domain = serializers.SerializerMethodField('get_dns')
    extension = serializers.SerializerMethodField('get_interface_extension')

    class Meta:
        model = Interface
        fields = ('ipv4', 'mac_address', 'domain', 'extension')

Maël Kervella's avatar
Maël Kervella committed
114 115 116
    @staticmethod
    def get_dns(obj):
        """ The name of the associated  DNS object """
Maël Kervella's avatar
Maël Kervella committed
117 118
        return obj.domain.name

Maël Kervella's avatar
Maël Kervella committed
119 120 121
    @staticmethod
    def get_interface_extension(obj):
        """ The name of the associated Interface object """
Maël Kervella's avatar
Maël Kervella committed
122 123
        return obj.domain.extension.name

Maël Kervella's avatar
Maël Kervella committed
124 125 126
    @staticmethod
    def get_macaddress(obj):
        """ The string representation of the associated MAC address """
Maël Kervella's avatar
Maël Kervella committed
127 128 129
        return str(obj.mac_address)


Maël Kervella's avatar
Maël Kervella committed
130
class FullInterfaceSerializer(serializers.ModelSerializer):
Maël Kervella's avatar
Maël Kervella committed
131 132 133
    """ Serializer for an Interface obejct. Use SerializerMethodField
    to get ForeignKey values """

Maël Kervella's avatar
Maël Kervella committed
134 135
    ipv4 = IpListSerializer(read_only=True)
    ipv6 = Ipv6ListSerializer(read_only=True, many=True)
Maël Kervella's avatar
Maël Kervella committed
136
    # TODO : use serializer.RelatedField to avoid duplicate code
Maël Kervella's avatar
Maël Kervella committed
137 138 139 140 141 142 143 144
    mac_address = serializers.SerializerMethodField('get_macaddress')
    domain = serializers.SerializerMethodField('get_dns')
    extension = serializers.SerializerMethodField('get_interface_extension')

    class Meta:
        model = Interface
        fields = ('ipv4', 'ipv6', 'mac_address', 'domain', 'extension')

Maël Kervella's avatar
Maël Kervella committed
145 146 147
    @staticmethod
    def get_dns(obj):
        """ The name of the associated DNS object """
Maël Kervella's avatar
Maël Kervella committed
148 149
        return obj.domain.name

Maël Kervella's avatar
Maël Kervella committed
150 151 152
    @staticmethod
    def get_interface_extension(obj):
        """ The name of the associated Extension object """
Maël Kervella's avatar
Maël Kervella committed
153 154
        return obj.domain.extension.name

Maël Kervella's avatar
Maël Kervella committed
155 156 157
    @staticmethod
    def get_macaddress(obj):
        """ The string representation of the associated MAC address """
Maël Kervella's avatar
Maël Kervella committed
158 159 160 161
        return str(obj.mac_address)


class ExtensionNameField(serializers.RelatedField):
Maël Kervella's avatar
Maël Kervella committed
162 163
    """ Serializer for Extension object field """

Maël Kervella's avatar
Maël Kervella committed
164 165 166
    def to_representation(self, value):
        return value.name

Maël Kervella's avatar
Maël Kervella committed
167 168 169
    def to_internal_value(self, data):
        pass

Maël Kervella's avatar
Maël Kervella committed
170 171

class TypeSerializer(serializers.ModelSerializer):
Maël Kervella's avatar
Maël Kervella committed
172 173 174
    """ Serializer for an IpType object. Use SerializerMethodField to
    get ForeignKey values """

Maël Kervella's avatar
Maël Kervella committed
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    extension = ExtensionNameField(read_only=True)
    ouverture_ports_tcp_in = serializers\
        .SerializerMethodField('get_port_policy_input_tcp')
    ouverture_ports_tcp_out = serializers\
        .SerializerMethodField('get_port_policy_output_tcp')
    ouverture_ports_udp_in = serializers\
        .SerializerMethodField('get_port_policy_input_udp')
    ouverture_ports_udp_out = serializers\
        .SerializerMethodField('get_port_policy_output_udp')

    class Meta:
        model = IpType
        fields = ('type', 'extension', 'domaine_ip_start', 'domaine_ip_stop',
                  'prefix_v6',
                  'ouverture_ports_tcp_in', 'ouverture_ports_tcp_out',
                  'ouverture_ports_udp_in', 'ouverture_ports_udp_out',)

Maël Kervella's avatar
Maël Kervella committed
192 193 194 195
    @staticmethod
    def get_port_policy(obj, protocole, io):
        """ Generic utility function to get the policy for a given
        port, protocole and IN or OUT """
Maël Kervella's avatar
Maël Kervella committed
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
        if obj.ouverture_ports is None:
            return []
        return map(
            str,
            obj.ouverture_ports.ouvertureport_set.filter(
                protocole=protocole
            ).filter(io=io)
        )

    def get_port_policy_input_tcp(self, obj):
        """Renvoie la liste des ports ouverts en entrée tcp"""
        return self.get_port_policy(obj, OuverturePort.TCP, OuverturePort.IN)

    def get_port_policy_output_tcp(self, obj):
        """Renvoie la liste des ports ouverts en sortie tcp"""
        return self.get_port_policy(obj, OuverturePort.TCP, OuverturePort.OUT)

    def get_port_policy_input_udp(self, obj):
        """Renvoie la liste des ports ouverts en entrée udp"""
        return self.get_port_policy(obj, OuverturePort.UDP, OuverturePort.IN)

    def get_port_policy_output_udp(self, obj):
        """Renvoie la liste des ports ouverts en sortie udp"""
        return self.get_port_policy(obj, OuverturePort.UDP, OuverturePort.OUT)


class ExtensionSerializer(serializers.ModelSerializer):
    """Serialisation d'une extension : origin_ip et la zone sont
    des foreign_key donc evalués en get_..."""
    origin = serializers.SerializerMethodField('get_origin_ip')
    zone_entry = serializers.SerializerMethodField('get_zone_name')
    soa = serializers.SerializerMethodField('get_soa_data')

    class Meta:
        model = Extension
        fields = ('name', 'origin', 'origin_v6', 'zone_entry', 'soa')

Maël Kervella's avatar
Maël Kervella committed
233 234 235
    @staticmethod
    def get_origin_ip(obj):
        """ The IP of the associated origin for the zone """
Maël Kervella's avatar
Maël Kervella committed
236 237
        return obj.origin.ipv4

Maël Kervella's avatar
Maël Kervella committed
238 239 240
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone """
Maël Kervella's avatar
Maël Kervella committed
241 242
        return str(obj.dns_entry)

Maël Kervella's avatar
Maël Kervella committed
243 244 245
    @staticmethod
    def get_soa_data(obj):
        """ The representation of the associated SOA """
Maël Kervella's avatar
Maël Kervella committed
246
        return {'mail': obj.soa.dns_soa_mail, 'param': obj.soa.dns_soa_param}
Maël Kervella's avatar
Maël Kervella committed
247 248 249 250 251 252 253 254 255 256 257 258 259


class MxSerializer(serializers.ModelSerializer):
    """Serialisation d'un MX, evaluation du nom, de la zone
    et du serveur cible, etant des foreign_key"""
    name = serializers.SerializerMethodField('get_entry_name')
    zone = serializers.SerializerMethodField('get_zone_name')
    mx_entry = serializers.SerializerMethodField('get_mx_name')

    class Meta:
        model = Mx
        fields = ('zone', 'priority', 'name', 'mx_entry')

Maël Kervella's avatar
Maël Kervella committed
260 261 262
    @staticmethod
    def get_entry_name(obj):
        """ The name of the DNS MX entry """
Maël Kervella's avatar
Maël Kervella committed
263 264
        return str(obj.name)

Maël Kervella's avatar
Maël Kervella committed
265 266 267
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone of the MX record """
Maël Kervella's avatar
Maël Kervella committed
268 269
        return obj.zone.name

Maël Kervella's avatar
Maël Kervella committed
270 271 272
    @staticmethod
    def get_mx_name(obj):
        """ The string representation of the entry to add to the DNS """
Maël Kervella's avatar
Maël Kervella committed
273 274 275 276 277 278 279 280 281 282 283 284 285
        return str(obj.dns_entry)


class TxtSerializer(serializers.ModelSerializer):
    """Serialisation d'un txt : zone cible et l'entrée txt
    sont evaluées à part"""
    zone = serializers.SerializerMethodField('get_zone_name')
    txt_entry = serializers.SerializerMethodField('get_txt_name')

    class Meta:
        model = Txt
        fields = ('zone', 'txt_entry', 'field1', 'field2')

Maël Kervella's avatar
Maël Kervella committed
286 287 288
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone """
Maël Kervella's avatar
Maël Kervella committed
289 290
        return str(obj.zone.name)

Maël Kervella's avatar
Maël Kervella committed
291 292 293
    @staticmethod
    def get_txt_name(obj):
        """ The string representation of the entry to add to the DNS """
Maël Kervella's avatar
Maël Kervella committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
        return str(obj.dns_entry)


class SrvSerializer(serializers.ModelSerializer):
    """Serialisation d'un srv : zone cible et l'entrée txt"""
    extension = serializers.SerializerMethodField('get_extension_name')
    srv_entry = serializers.SerializerMethodField('get_srv_name')

    class Meta:
        model = Srv
        fields = (
            'service',
            'protocole',
            'extension',
            'ttl',
            'priority',
            'weight',
            'port',
            'target',
            'srv_entry'
        )

Maël Kervella's avatar
Maël Kervella committed
316 317 318
    @staticmethod
    def get_extension_name(obj):
        """ The name of the associated extension """
Maël Kervella's avatar
Maël Kervella committed
319 320
        return str(obj.extension.name)

Maël Kervella's avatar
Maël Kervella committed
321 322 323
    @staticmethod
    def get_srv_name(obj):
        """ The string representation of the entry to add to the DNS """
Maël Kervella's avatar
Maël Kervella committed
324 325 326 327 328 329 330 331 332 333 334 335 336 337
        return str(obj.dns_entry)


class NsSerializer(serializers.ModelSerializer):
    """Serialisation d'un NS : la zone, l'entrée ns complète et le serveur
    ns sont évalués à part"""
    zone = serializers.SerializerMethodField('get_zone_name')
    ns = serializers.SerializerMethodField('get_domain_name')
    ns_entry = serializers.SerializerMethodField('get_text_name')

    class Meta:
        model = Ns
        fields = ('zone', 'ns', 'ns_entry')

Maël Kervella's avatar
Maël Kervella committed
338 339 340
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone """
Maël Kervella's avatar
Maël Kervella committed
341 342
        return obj.zone.name

Maël Kervella's avatar
Maël Kervella committed
343 344 345
    @staticmethod
    def get_domain_name(obj):
        """ The name of the associated NS target """
Maël Kervella's avatar
Maël Kervella committed
346 347
        return str(obj.ns)

Maël Kervella's avatar
Maël Kervella committed
348 349 350
    @staticmethod
    def get_text_name(obj):
        """ The string representation of the entry to add to the DNS """
Maël Kervella's avatar
Maël Kervella committed
351 352 353 354 355 356 357 358 359 360 361 362 363 364
        return str(obj.dns_entry)


class DomainSerializer(serializers.ModelSerializer):
    """Serialisation d'un domain, extension, cname sont des foreign_key,
    et l'entrée complète, sont évalués à part"""
    extension = serializers.SerializerMethodField('get_zone_name')
    cname = serializers.SerializerMethodField('get_alias_name')
    cname_entry = serializers.SerializerMethodField('get_cname_name')

    class Meta:
        model = Domain
        fields = ('name', 'extension', 'cname', 'cname_entry')

Maël Kervella's avatar
Maël Kervella committed
365 366 367
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone """
Maël Kervella's avatar
Maël Kervella committed
368 369
        return obj.extension.name

Maël Kervella's avatar
Maël Kervella committed
370 371 372
    @staticmethod
    def get_alias_name(obj):
        """ The name of the associated alias """
Maël Kervella's avatar
Maël Kervella committed
373 374
        return str(obj.cname)

Maël Kervella's avatar
Maël Kervella committed
375 376 377
    @staticmethod
    def get_cname_name(obj):
        """ The name of the associated CNAME target """
Maël Kervella's avatar
Maël Kervella committed
378 379 380
        return str(obj.dns_entry)


Maël Kervella's avatar
Maël Kervella committed
381 382 383 384 385 386 387 388 389 390
class ServicesSerializer(serializers.ModelSerializer):
    """Evaluation d'un Service, et serialisation"""
    server = serializers.SerializerMethodField('get_server_name')
    service = serializers.SerializerMethodField('get_service_name')
    need_regen = serializers.SerializerMethodField('get_regen_status')

    class Meta:
        model = Service_link
        fields = ('server', 'service', 'need_regen')

Maël Kervella's avatar
Maël Kervella committed
391 392 393
    @staticmethod
    def get_server_name(obj):
        """ The name of the associated server """
Maël Kervella's avatar
Maël Kervella committed
394 395
        return str(obj.server.domain.name)

Maël Kervella's avatar
Maël Kervella committed
396 397 398
    @staticmethod
    def get_service_name(obj):
        """ The name of the service name """
Maël Kervella's avatar
Maël Kervella committed
399 400
        return str(obj.service)

Maël Kervella's avatar
Maël Kervella committed
401 402 403
    @staticmethod
    def get_regen_status(obj):
        """ The string representation of the regen status """
Maël Kervella's avatar
Maël Kervella committed
404
        return obj.need_regen()
Maël Kervella's avatar
Maël Kervella committed
405 406 407 408 409 410 411


class OuverturePortsSerializer(serializers.Serializer):
    """Serialisation de l'ouverture des ports"""
    ipv4 = serializers.SerializerMethodField()
    ipv6 = serializers.SerializerMethodField()

Maël Kervella's avatar
Maël Kervella committed
412 413 414 415 416 417 418 419 420 421 422
    def create(self, validated_data):
        """ Creates a new object based on the un-serialized data.
        Used to implement an abstract inherited method """
        pass

    def update(self, instance, validated_data):
        """ Updates an object based on the un-serialized data.
        Used to implement an abstract inherited method """
        pass

    @staticmethod
Maël Kervella's avatar
Maël Kervella committed
423
    def get_ipv4():
Maël Kervella's avatar
Maël Kervella committed
424
        """ The representation of the policy for the IPv4 addresses """
Maël Kervella's avatar
Maël Kervella committed
425 426 427 428 429 430
        return {
            i.ipv4.ipv4: {
                "tcp_in": [j.tcp_ports_in() for j in i.port_lists.all()],
                "tcp_out": [j.tcp_ports_out()for j in i.port_lists.all()],
                "udp_in": [j.udp_ports_in() for j in i.port_lists.all()],
                "udp_out": [j.udp_ports_out() for j in i.port_lists.all()],
Maël Kervella's avatar
Maël Kervella committed
431
            }
Maël Kervella's avatar
Maël Kervella committed
432
            for i in Interface.objects.all() if i.ipv4
Maël Kervella's avatar
Maël Kervella committed
433 434
        }

Maël Kervella's avatar
Maël Kervella committed
435
    @staticmethod
Maël Kervella's avatar
Maël Kervella committed
436
    def get_ipv6():
Maël Kervella's avatar
Maël Kervella committed
437
        """ The representation of the policy for the IPv6 addresses """
Maël Kervella's avatar
Maël Kervella committed
438 439 440 441 442 443
        return {
            i.ipv6: {
                "tcp_in": [j.tcp_ports_in() for j in i.port_lists.all()],
                "tcp_out": [j.tcp_ports_out()for j in i.port_lists.all()],
                "udp_in": [j.udp_ports_in() for j in i.port_lists.all()],
                "udp_out": [j.udp_ports_out() for j in i.port_lists.all()],
Maël Kervella's avatar
Maël Kervella committed
444
            }
Maël Kervella's avatar
Maël Kervella committed
445
            for i in Interface.objects.all() if i.ipv6
Maël Kervella's avatar
Maël Kervella committed
446
        }