Ce serveur Gitlab sera éteint le 30 juin 2020, pensez à migrer vos projets vers les serveurs gitlab-research.centralesupelec.fr et gitlab-student.centralesupelec.fr !

views.py 21.1 KB
Newer Older
1
# -*- mode: python; coding: utf-8 -*-
Maël Kervella's avatar
Maël Kervella committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
# 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 Maël 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.

22
"""Defines the views of the API
Maël Kervella's avatar
Maël Kervella committed
23

24 25 26
All views inherits the `rest_framework.views.APIview` to respect the
REST API requirements such as dealing with HTTP status code, format of
the response (JSON or other), the CSRF exempting, ...
Maël Kervella's avatar
Maël Kervella committed
27
"""
28

29
import datetime
30

31
from django.conf import settings
32
from django.db.models import Q
33 34
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
Maël Kervella's avatar
Maël Kervella committed
35
from rest_framework.response import Response
36
from rest_framework import viewsets, generics, views
Maël Kervella's avatar
Maël Kervella committed
37

Maël Kervella's avatar
Maël Kervella committed
38 39 40 41 42
import cotisations.models as cotisations
import machines.models as machines
import preferences.models as preferences
import topologie.models as topologie
import users.models as users
43
from re2o.utils import all_active_interfaces, all_has_access
44

Maël Kervella's avatar
Maël Kervella committed
45
from . import serializers
46
from .pagination import PageSizedPagination
47
from .permissions import ACLPermission
48

Maël Kervella's avatar
Maël Kervella committed
49

50
# COTISATIONS
51 52 53


class FactureViewSet(viewsets.ReadOnlyModelViewSet):
54 55
    """Exposes list and details of `cotisations.models.Facture` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
56 57
    queryset = cotisations.Facture.objects.all()
    serializer_class = serializers.FactureSerializer
58 59 60


class VenteViewSet(viewsets.ReadOnlyModelViewSet):
61 62
    """Exposes list and details of `cotisations.models.Vente` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
63 64
    queryset = cotisations.Vente.objects.all()
    serializer_class = serializers.VenteSerializer
65 66 67


class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
68 69
    """Exposes list and details of `cotisations.models.Article` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
70 71
    queryset = cotisations.Article.objects.all()
    serializer_class = serializers.ArticleSerializer
72 73 74


class BanqueViewSet(viewsets.ReadOnlyModelViewSet):
75 76
    """Exposes list and details of `cotisations.models.Banque` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
77 78
    queryset = cotisations.Banque.objects.all()
    serializer_class = serializers.BanqueSerializer
79 80 81


class PaiementViewSet(viewsets.ReadOnlyModelViewSet):
82 83
    """Exposes list and details of `cotisations.models.Paiement` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
84 85
    queryset = cotisations.Paiement.objects.all()
    serializer_class = serializers.PaiementSerializer
86 87 88


class CotisationViewSet(viewsets.ReadOnlyModelViewSet):
89 90
    """Exposes list and details of `cotisations.models.Cotisation` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
91 92
    queryset = cotisations.Cotisation.objects.all()
    serializer_class = serializers.CotisationSerializer
93 94


95
# MACHINES
96 97 98


class MachineViewSet(viewsets.ReadOnlyModelViewSet):
99 100
    """Exposes list and details of `machines.models.Machine` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
101 102
    queryset = machines.Machine.objects.all()
    serializer_class = serializers.MachineSerializer
103 104 105


class MachineTypeViewSet(viewsets.ReadOnlyModelViewSet):
106 107
    """Exposes list and details of `machines.models.MachineType` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
108 109
    queryset = machines.MachineType.objects.all()
    serializer_class = serializers.MachineTypeSerializer
110 111 112


class IpTypeViewSet(viewsets.ReadOnlyModelViewSet):
113 114
    """Exposes list and details of `machines.models.IpType` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
115 116
    queryset = machines.IpType.objects.all()
    serializer_class = serializers.IpTypeSerializer
117 118 119


class VlanViewSet(viewsets.ReadOnlyModelViewSet):
120 121
    """Exposes list and details of `machines.models.Vlan` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
122 123
    queryset = machines.Vlan.objects.all()
    serializer_class = serializers.VlanSerializer
124 125 126


class NasViewSet(viewsets.ReadOnlyModelViewSet):
127 128
    """Exposes list and details of `machines.models.Nas` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
129 130
    queryset = machines.Nas.objects.all()
    serializer_class = serializers.NasSerializer
131 132 133


class SOAViewSet(viewsets.ReadOnlyModelViewSet):
134 135
    """Exposes list and details of `machines.models.SOA` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
136 137
    queryset = machines.SOA.objects.all()
    serializer_class = serializers.SOASerializer
138 139 140


class ExtensionViewSet(viewsets.ReadOnlyModelViewSet):
141 142
    """Exposes list and details of `machines.models.Extension` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
143 144
    queryset = machines.Extension.objects.all()
    serializer_class = serializers.ExtensionSerializer
145 146 147


class MxViewSet(viewsets.ReadOnlyModelViewSet):
148 149
    """Exposes list and details of `machines.models.Mx` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
150 151
    queryset = machines.Mx.objects.all()
    serializer_class = serializers.MxSerializer
152 153 154


class NsViewSet(viewsets.ReadOnlyModelViewSet):
155 156
    """Exposes list and details of `machines.models.Ns` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
157 158
    queryset = machines.Ns.objects.all()
    serializer_class = serializers.NsSerializer
159 160 161


class TxtViewSet(viewsets.ReadOnlyModelViewSet):
162 163
    """Exposes list and details of `machines.models.Txt` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
164 165
    queryset = machines.Txt.objects.all()
    serializer_class = serializers.TxtSerializer
166 167 168 169 170 171

class DNameViewSet(viewsets.ReadOnlyModelViewSet):
    """Exposes list and details of `machines.models.DName` objects.
    """
    queryset = machines.DName.objects.all()
    serializer_class = serializers.DNameSerializer
172 173 174


class SrvViewSet(viewsets.ReadOnlyModelViewSet):
175 176
    """Exposes list and details of `machines.models.Srv` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
177 178
    queryset = machines.Srv.objects.all()
    serializer_class = serializers.SrvSerializer
179 180


181 182 183 184 185 186 187
class SshFpViewSet(viewsets.ReadOnlyModelViewSet):
    """Exposes list and details of `machines.models.SshFp` objects.
    """
    queryset = machines.SshFp.objects.all()
    serializer_class = serializers.SshFpSerializer


188
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
189 190
    """Exposes list and details of `machines.models.Interface` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
191 192
    queryset = machines.Interface.objects.all()
    serializer_class = serializers.InterfaceSerializer
193 194 195


class Ipv6ListViewSet(viewsets.ReadOnlyModelViewSet):
196 197
    """Exposes list and details of `machines.models.Ipv6List` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
198 199
    queryset = machines.Ipv6List.objects.all()
    serializer_class = serializers.Ipv6ListSerializer
200 201 202


class DomainViewSet(viewsets.ReadOnlyModelViewSet):
203 204
    """Exposes list and details of `machines.models.Domain` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
205 206
    queryset = machines.Domain.objects.all()
    serializer_class = serializers.DomainSerializer
207 208 209


class IpListViewSet(viewsets.ReadOnlyModelViewSet):
210 211
    """Exposes list and details of `machines.models.IpList` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
212 213
    queryset = machines.IpList.objects.all()
    serializer_class = serializers.IpListSerializer
214 215 216


class ServiceViewSet(viewsets.ReadOnlyModelViewSet):
217 218
    """Exposes list and details of `machines.models.Service` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
219 220
    queryset = machines.Service.objects.all()
    serializer_class = serializers.ServiceSerializer
221 222


223
class ServiceLinkViewSet(viewsets.ReadOnlyModelViewSet):
224 225
    """Exposes list and details of `machines.models.Service_link` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
226 227
    queryset = machines.Service_link.objects.all()
    serializer_class = serializers.ServiceLinkSerializer
228 229 230


class OuverturePortListViewSet(viewsets.ReadOnlyModelViewSet):
231 232 233
    """Exposes list and details of `machines.models.OuverturePortList`
    objects.
    """
Maël Kervella's avatar
Maël Kervella committed
234 235
    queryset = machines.OuverturePortList.objects.all()
    serializer_class = serializers.OuverturePortListSerializer
236 237 238


class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
239 240
    """Exposes list and details of `machines.models.OuverturePort` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
241 242
    queryset = machines.OuverturePort.objects.all()
    serializer_class = serializers.OuverturePortSerializer
243 244


245
# PREFERENCES
246 247
# Those views differ a bit because there is only one object
# to display, so we don't bother with the listing part
248

249
class OptionalUserView(generics.RetrieveAPIView):
250 251
    """Exposes details of `preferences.models.` settings.
    """
252 253 254 255 256 257 258 259 260
    permission_classes = (ACLPermission, )
    perms_map = {'GET' : [preferences.OptionalUser.can_view_all]}
    serializer_class = serializers.OptionalUserSerializer

    def get_object(self):
        return preferences.OptionalUser.objects.first()


class OptionalMachineView(generics.RetrieveAPIView):
261 262
    """Exposes details of `preferences.models.OptionalMachine` settings.
    """
263 264 265 266 267 268 269 270 271
    permission_classes = (ACLPermission, )
    perms_map = {'GET' : [preferences.OptionalMachine.can_view_all]}
    serializer_class = serializers.OptionalMachineSerializer

    def get_object(self):
        return preferences.OptionalMachine.objects.first()


class OptionalTopologieView(generics.RetrieveAPIView):
272 273
    """Exposes details of `preferences.models.OptionalTopologie` settings.
    """
274 275 276 277 278 279 280 281 282
    permission_classes = (ACLPermission, )
    perms_map = {'GET' : [preferences.OptionalTopologie.can_view_all]}
    serializer_class = serializers.OptionalTopologieSerializer

    def get_object(self):
        return preferences.OptionalTopologie.objects.first()


class GeneralOptionView(generics.RetrieveAPIView):
283 284
    """Exposes details of `preferences.models.GeneralOption` settings.
    """
285 286 287 288 289 290 291 292
    permission_classes = (ACLPermission, )
    perms_map = {'GET' : [preferences.GeneralOption.can_view_all]}
    serializer_class = serializers.GeneralOptionSerializer

    def get_object(self):
        return preferences.GeneralOption.objects.first()


293
class HomeServiceViewSet(viewsets.ReadOnlyModelViewSet):
294 295
    """Exposes list and details of `preferences.models.Service` objects.
    """
296
    queryset = preferences.Service.objects.all()
297
    serializer_class = serializers.HomeServiceSerializer
298 299 300


class AssoOptionView(generics.RetrieveAPIView):
301 302
    """Exposes details of `preferences.models.AssoOption` settings.
    """
303 304 305 306 307 308 309 310 311
    permission_classes = (ACLPermission, )
    perms_map = {'GET' : [preferences.AssoOption.can_view_all]}
    serializer_class = serializers.AssoOptionSerializer

    def get_object(self):
        return preferences.AssoOption.objects.first()


class HomeOptionView(generics.RetrieveAPIView):
312 313
    """Exposes details of `preferences.models.HomeOption` settings.
    """
314 315 316 317 318 319 320 321 322
    permission_classes = (ACLPermission, )
    perms_map = {'GET' : [preferences.HomeOption.can_view_all]}
    serializer_class = serializers.HomeOptionSerializer

    def get_object(self):
        return preferences.HomeOption.objects.first()


class MailMessageOptionView(generics.RetrieveAPIView):
323 324
    """Exposes details of `preferences.models.MailMessageOption` settings.
    """
325 326 327 328 329 330
    permission_classes = (ACLPermission, )
    perms_map = {'GET' : [preferences.MailMessageOption.can_view_all]}
    serializer_class = serializers.MailMessageOptionSerializer

    def get_object(self):
        return preferences.MailMessageOption.objects.first()
331 332


333
# TOPOLOGIE
334 335 336


class StackViewSet(viewsets.ReadOnlyModelViewSet):
337 338
    """Exposes list and details of `topologie.models.Stack` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
339 340
    queryset = topologie.Stack.objects.all()
    serializer_class = serializers.StackSerializer
341 342 343


class AccessPointViewSet(viewsets.ReadOnlyModelViewSet):
344 345
    """Exposes list and details of `topologie.models.AccessPoint` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
346 347
    queryset = topologie.AccessPoint.objects.all()
    serializer_class = serializers.AccessPointSerializer
348 349 350


class SwitchViewSet(viewsets.ReadOnlyModelViewSet):
351 352
    """Exposes list and details of `topologie.models.Switch` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
353 354
    queryset = topologie.Switch.objects.all()
    serializer_class = serializers.SwitchSerializer
355 356


357 358 359 360 361 362 363
class ServerViewSet(viewsets.ReadOnlyModelViewSet):
    """Exposes list and details of `topologie.models.Server` objects.
    """
    queryset = topologie.Server.objects.all()
    serializer_class = serializers.ServerSerializer


364
class ModelSwitchViewSet(viewsets.ReadOnlyModelViewSet):
365 366
    """Exposes list and details of `topologie.models.ModelSwitch` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
367 368
    queryset = topologie.ModelSwitch.objects.all()
    serializer_class = serializers.ModelSwitchSerializer
369 370 371


class ConstructorSwitchViewSet(viewsets.ReadOnlyModelViewSet):
372 373 374
    """Exposes list and details of `topologie.models.ConstructorSwitch`
    objects.
    """
Maël Kervella's avatar
Maël Kervella committed
375 376
    queryset = topologie.ConstructorSwitch.objects.all()
    serializer_class = serializers.ConstructorSwitchSerializer
377 378 379


class SwitchBayViewSet(viewsets.ReadOnlyModelViewSet):
380 381
    """Exposes list and details of `topologie.models.SwitchBay` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
382 383
    queryset = topologie.SwitchBay.objects.all()
    serializer_class = serializers.SwitchBaySerializer
384 385 386


class BuildingViewSet(viewsets.ReadOnlyModelViewSet):
387 388
    """Exposes list and details of `topologie.models.Building` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
389 390
    queryset = topologie.Building.objects.all()
    serializer_class = serializers.BuildingSerializer
391 392 393


class SwitchPortViewSet(viewsets.ReadOnlyModelViewSet):
394 395
    """Exposes list and details of `topologie.models.Port` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
396 397
    queryset = topologie.Port.objects.all()
    serializer_class = serializers.SwitchPortSerializer
398 399 400


class RoomViewSet(viewsets.ReadOnlyModelViewSet):
401 402
    """Exposes list and details of `topologie.models.Room` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
403 404
    queryset = topologie.Room.objects.all()
    serializer_class = serializers.RoomSerializer
405 406


407 408 409 410 411 412
class PortProfileViewSet(viewsets.ReadOnlyModelViewSet):
    """Exposes list and details of `topologie.models.PortProfile` objects.
    """
    queryset = topologie.PortProfile.objects.all()
    serializer_class = serializers.PortProfileSerializer

413
# USER
414 415


Maël Kervella's avatar
Maël Kervella committed
416
class UserViewSet(viewsets.ReadOnlyModelViewSet):
417 418
    """Exposes list and details of `users.models.Users` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
419 420
    queryset = users.User.objects.all()
    serializer_class = serializers.UserSerializer
Maël Kervella's avatar
Maël Kervella committed
421

422 423 424
class HomeCreationViewSet(viewsets.ReadOnlyModelViewSet):
    """Exposes infos of `users.models.Users` objects to create homes.
    """
detraz's avatar
detraz committed
425
    queryset = users.User.objects.exclude(Q(state=users.User.STATE_DISABLED) | Q(state=users.User.STATE_NOT_YET_ACTIVE))
426
    serializer_class = serializers.HomeCreationSerializer
Maël Kervella's avatar
Maël Kervella committed
427 428

class ClubViewSet(viewsets.ReadOnlyModelViewSet):
429 430
    """Exposes list and details of `users.models.Club` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
431 432
    queryset = users.Club.objects.all()
    serializer_class = serializers.ClubSerializer
Maël Kervella's avatar
Maël Kervella committed
433 434 435


class AdherentViewSet(viewsets.ReadOnlyModelViewSet):
436 437
    """Exposes list and details of `users.models.Adherent` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
438 439
    queryset = users.Adherent.objects.all()
    serializer_class = serializers.AdherentSerializer
Maël Kervella's avatar
Maël Kervella committed
440 441 442


class ServiceUserViewSet(viewsets.ReadOnlyModelViewSet):
443 444
    """Exposes list and details of `users.models.ServiceUser` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
445 446
    queryset = users.ServiceUser.objects.all()
    serializer_class = serializers.ServiceUserSerializer
Maël Kervella's avatar
Maël Kervella committed
447 448 449


class SchoolViewSet(viewsets.ReadOnlyModelViewSet):
450 451
    """Exposes list and details of `users.models.School` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
452 453
    queryset = users.School.objects.all()
    serializer_class = serializers.SchoolSerializer
Maël Kervella's avatar
Maël Kervella committed
454 455 456


class ListRightViewSet(viewsets.ReadOnlyModelViewSet):
457 458
    """Exposes list and details of `users.models.ListRight` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
459 460
    queryset = users.ListRight.objects.all()
    serializer_class = serializers.ListRightSerializer
Maël Kervella's avatar
Maël Kervella committed
461 462 463


class ShellViewSet(viewsets.ReadOnlyModelViewSet):
464 465
    """Exposes list and details of `users.models.ListShell` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
466 467
    queryset = users.ListShell.objects.all()
    serializer_class = serializers.ShellSerializer
Maël Kervella's avatar
Maël Kervella committed
468 469 470


class BanViewSet(viewsets.ReadOnlyModelViewSet):
471 472
    """Exposes list and details of `users.models.Ban` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
473 474
    queryset = users.Ban.objects.all()
    serializer_class = serializers.BanSerializer
Maël Kervella's avatar
Maël Kervella committed
475 476 477


class WhitelistViewSet(viewsets.ReadOnlyModelViewSet):
478 479
    """Exposes list and details of `users.models.Whitelist` objects.
    """
Maël Kervella's avatar
Maël Kervella committed
480 481
    queryset = users.Whitelist.objects.all()
    serializer_class = serializers.WhitelistSerializer
Maël Kervella's avatar
Maël Kervella committed
482

483

484 485
class EMailAddressViewSet(viewsets.ReadOnlyModelViewSet):
    """Exposes list and details of `users.models.EMailAddress` objects.
486
    """
487 488
    serializer_class = serializers.EMailAddressSerializer
    queryset = users.EMailAddress.objects.none()
489 490 491 492

    def get_queryset(self):
        if preferences.OptionalUser.get_cached_value(
            'local_email_accounts_enabled'):
493
            return (users.EMailAddress.objects
494 495
                    .filter(user__local_email_enabled=True))
        else:
496
            return users.EMailAddress.objects.none()
497 498


499
# SERVICE REGEN
500 501


502
class ServiceRegenViewSet(viewsets.ModelViewSet):
503 504
    """Exposes list and details of the services to regen
    """
505 506 507 508 509 510 511 512 513 514 515 516 517 518
    serializer_class = serializers.ServiceRegenSerializer

    def get_queryset(self):
        queryset = machines.Service_link.objects.select_related(
            'server__domain'
        ).select_related(
            'service'
        )
        if 'hostname' in self.request.GET:
            hostname = self.request.GET['hostname']
            queryset = queryset.filter(server__domain__name__iexact=hostname)
        return queryset


519
# LOCAL EMAILS
520 521


522 523
class LocalEmailUsersView(generics.ListAPIView):
    """Exposes all the aliases of the users that activated the internal address
524
    """
525
    serializer_class = serializers.LocalEmailUsersSerializer
526

527 528 529 530 531 532 533
    def get_queryset(self):
        if preferences.OptionalUser.get_cached_value(
            'local_email_accounts_enabled'):
            return (users.User.objects
                    .filter(local_email_enabled=True))
        else:
            return users.User.objects.none()
534 535


536
# DHCP
537

538

539
class HostMacIpView(generics.ListAPIView):
540 541 542
    """Exposes the associations between hostname, mac address and IPv4 in
    order to build the DHCP lease files.
    """
543 544 545 546
    queryset = all_active_interfaces()
    serializer_class = serializers.HostMacIpSerializer


547 548 549 550 551 552
#Firewall

class SubnetPortsOpenView(generics.ListAPIView):
    queryset = machines.IpType.objects.all()
    serializer_class = serializers.SubnetPortsOpenSerializer

553 554 555 556
class InterfacePortsOpenView(generics.ListAPIView):
    queryset = machines.Interface.objects.filter(port_lists__isnull=False).distinct()
    serializer_class = serializers.InterfacePortsOpenSerializer

557
# DNS
558

559

560
class DNSZonesView(generics.ListAPIView):
561
    """Exposes the detailed information about each extension (hostnames,
562 563
    IPs, DNS records, etc.) in order to build the DNS zone files.
    """
564 565 566 567 568 569 570 571
    queryset = (machines.Extension.objects
                .prefetch_related('soa')
                .prefetch_related('ns_set').prefetch_related('ns_set__ns')
                .prefetch_related('origin')
                .prefetch_related('mx_set').prefetch_related('mx_set__name')
                .prefetch_related('txt_set')
                .prefetch_related('srv_set').prefetch_related('srv_set__target')
                .all())
572 573
    serializer_class = serializers.DNSZonesSerializer

574 575 576 577 578 579 580 581 582
class DNSReverseZonesView(generics.ListAPIView):
    """Exposes the detailed information about each extension (hostnames, 
    IPs, DNS records, etc.) in order to build the DNS zone files.
    """
    queryset = (machines.IpType.objects.all())
    serializer_class = serializers.DNSReverseZonesSerializer



583

584
# MAILING
585 586 587


class StandardMailingView(views.APIView):
588 589 590
    """Exposes list and details of standard mailings (name and members) in
    order to building the corresponding mailing lists.
    """
591
    pagination_class = PageSizedPagination
592 593
    permission_classes = (ACLPermission, )
    perms_map = {'GET' : [users.User.can_view_all]}
594 595

    def get(self, request, format=None):
596
        adherents_data = serializers.MailingMemberSerializer(all_has_access(), many=True).data
597 598 599 600 601 602 603
        data = [{'name': 'adherents', 'members': adherents_data}]
        paginator = self.pagination_class()
        paginator.paginate_queryset(data, request)
        return paginator.get_paginated_response(data)


class ClubMailingView(generics.ListAPIView):
604 605 606
    """Exposes list and details of club mailings (name, members and admins) in
    order to build the corresponding mailing lists.
    """
607 608 609 610
    queryset = users.Club.objects.all()
    serializer_class = serializers.MailingSerializer


611 612 613
# TOKEN AUTHENTICATION


614
class ObtainExpiringAuthToken(ObtainAuthToken):
615 616 617 618 619 620
    """Exposes a view to obtain a authentication token.

    This view as the same behavior as the
    `rest_framework.auth_token.views.ObtainAuthToken` view except that the
    expiration time is send along with the token as an addtional information.
    """
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)

        token_duration = datetime.timedelta(
            seconds=settings.API_TOKEN_DURATION
        )
        utc_now = datetime.datetime.now(datetime.timezone.utc)
        if not created and token.created < utc_now - token_duration:
            token.delete()
            token = Token.objects.create(user=user)
            token.created = datetime.datetime.utcnow()
            token.save()

        return Response({
            'token': token.key,
639
            'expiration': token.created + token_duration
640
        })