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.

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

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


class ServiceLinkSerializer(serializers.ModelSerializer):
44 45
    """ Serializer for the ServiceLink objects """

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):
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):
64 65 66
    """ Serializer fot the Adherent objects (who belong to a
    Mailing) """

67 68
    class Meta:
        model = Adherent
69
        fields = ('email',)
70 71


72
class IpTypeField(serializers.RelatedField):
73 74
    """ Serializer for an IpType object field """

75 76 77
    def to_representation(self, value):
        return value.type

78 79 80
    def to_internal_value(self, data):
        pass

81 82

class IpListSerializer(serializers.ModelSerializer):
83 84
    """ Serializer for an Ipv4List obejct using the IpType serialization """

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):
93 94
    """ Serializer for an Ipv6List object """

95 96 97 98 99
    class Meta:
        model = Ipv6List
        fields = ('ipv6', 'slaac_ip')


100
class InterfaceSerializer(serializers.ModelSerializer):
101 102 103
    """ Serializer for an Interface object. Use SerializerMethodField
    to get ForeignKey values """

104
    ipv4 = IpListSerializer(read_only=True)
105
    # TODO : use serializer.RelatedField to avoid duplicate code
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')

114 115 116
    @staticmethod
    def get_dns(obj):
        """ The name of the associated  DNS object """
117 118
        return obj.domain.name

119 120 121
    @staticmethod
    def get_interface_extension(obj):
        """ The name of the associated Interface object """
122 123
        return obj.domain.extension.name

124 125 126
    @staticmethod
    def get_macaddress(obj):
        """ The string representation of the associated MAC address """
127 128 129
        return str(obj.mac_address)


130
class FullInterfaceSerializer(serializers.ModelSerializer):
131 132 133
    """ Serializer for an Interface obejct. Use SerializerMethodField
    to get ForeignKey values """

134 135
    ipv4 = IpListSerializer(read_only=True)
    ipv6 = Ipv6ListSerializer(read_only=True, many=True)
136
    # TODO : use serializer.RelatedField to avoid duplicate code
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')

145 146 147
    @staticmethod
    def get_dns(obj):
        """ The name of the associated DNS object """
148 149
        return obj.domain.name

150 151 152
    @staticmethod
    def get_interface_extension(obj):
        """ The name of the associated Extension object """
153 154
        return obj.domain.extension.name

155 156 157
    @staticmethod
    def get_macaddress(obj):
        """ The string representation of the associated MAC address """
158 159 160 161
        return str(obj.mac_address)


class ExtensionNameField(serializers.RelatedField):
162 163
    """ Serializer for Extension object field """

164 165 166
    def to_representation(self, value):
        return value.name

167 168 169
    def to_internal_value(self, data):
        pass

170 171

class TypeSerializer(serializers.ModelSerializer):
172 173 174
    """ Serializer for an IpType object. Use SerializerMethodField to
    get ForeignKey values """

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',)

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 """
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')

233 234 235
    @staticmethod
    def get_origin_ip(obj):
        """ The IP of the associated origin for the zone """
236 237
        return obj.origin.ipv4

238 239 240
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone """
241 242
        return str(obj.dns_entry)

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}
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')

260 261 262
    @staticmethod
    def get_entry_name(obj):
        """ The name of the DNS MX entry """
263 264
        return str(obj.name)

265 266 267
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone of the MX record """
268 269
        return obj.zone.name

270 271 272
    @staticmethod
    def get_mx_name(obj):
        """ The string representation of the entry to add to the DNS """
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')

286 287 288
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone """
289 290
        return str(obj.zone.name)

291 292 293
    @staticmethod
    def get_txt_name(obj):
        """ The string representation of the entry to add to the DNS """
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'
        )

316 317 318
    @staticmethod
    def get_extension_name(obj):
        """ The name of the associated extension """
319 320
        return str(obj.extension.name)

321 322 323
    @staticmethod
    def get_srv_name(obj):
        """ The string representation of the entry to add to the DNS """
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')

338 339 340
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone """
341 342
        return obj.zone.name

343 344 345
    @staticmethod
    def get_domain_name(obj):
        """ The name of the associated NS target """
346 347
        return str(obj.ns)

348 349 350
    @staticmethod
    def get_text_name(obj):
        """ The string representation of the entry to add to the DNS """
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')

365 366 367
    @staticmethod
    def get_zone_name(obj):
        """ The name of the associated zone """
368 369
        return obj.extension.name

370 371 372
    @staticmethod
    def get_alias_name(obj):
        """ The name of the associated alias """
373 374
        return str(obj.cname)

375 376 377
    @staticmethod
    def get_cname_name(obj):
        """ The name of the associated CNAME target """
378 379 380
        return str(obj.dns_entry)


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')

391 392 393
    @staticmethod
    def get_server_name(obj):
        """ The name of the associated server """
394 395
        return str(obj.server.domain.name)

396 397 398
    @staticmethod
    def get_service_name(obj):
        """ The name of the service name """
399 400
        return str(obj.service)

401 402 403
    @staticmethod
    def get_regen_status(obj):
        """ The string representation of the regen status """
404
        return obj.need_regen()
405 406 407 408 409 410 411


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

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
423
    def get_ipv4():
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()],
431
            }
Maël Kervella's avatar
Maël Kervella committed
432
            for i in Interface.objects.all() if i.ipv4
433 434
        }

435
    @staticmethod
436
    def get_ipv6():
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()],
444
            }
Maël Kervella's avatar
Maël Kervella committed
445
            for i in Interface.objects.all() if i.ipv6
446
        }