diff --git a/api/routers.py b/api/routers.py new file mode 100644 index 00000000..cea69690 --- /dev/null +++ b/api/routers.py @@ -0,0 +1,123 @@ +# 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. +"""api.routers + +Definition of the custom routers to generate the URLs of the API +""" + +from collections import OrderedDict +from django.conf.urls import url, include +from django.core.urlresolvers import NoReverseMatch +from rest_framework import views +from rest_framework.routers import DefaultRouter +from rest_framework.response import Response +from rest_framework.reverse import reverse +from rest_framework.schemas import SchemaGenerator +from rest_framework.settings import api_settings + +class AllViewsRouter(DefaultRouter): + def __init__(self, *args, **kwargs): + self.view_registry = [] + super(AllViewsRouter, self).__init__(*args, **kwargs) + + def register_viewset(self, *args, **kwargs): + """ + Register a viewset in the router + Alias of `register` for convenience + """ + return self.register(*args, **kwargs) + + def register_view(self, pattern, view, name=None): + """ + Register a view in the router + """ + if name is None: + name = self.get_default_name(pattern) + self.view_registry.append((pattern, view, name)) + + def get_default_name(self, pattern): + return pattern.split('/')[-1] + + def get_api_root_view(self, schema_urls=None): + """ + Return a view to use as the API root. + """ + api_root_dict = OrderedDict() + list_name = self.routes[0].name + for prefix, viewset, basename in self.registry: + api_root_dict[prefix] = list_name.format(basename=basename) + for pattern, view, name in self.view_registry: + api_root_dict[pattern] = name + + view_renderers = list(api_settings.DEFAULT_RENDERER_CLASSES) + schema_media_types = [] + + if schema_urls and self.schema_title: + view_renderers += list(self.schema_renderers) + schema_generator = SchemaGenerator( + title=self.schema_title, + patterns=schema_urls + ) + schema_media_types = [ + renderer.media_type + for renderer in self.schema_renderers + ] + + class APIRoot(views.APIView): + _ignore_model_permissions = True + renderer_classes = view_renderers + + def get(self, request, *args, **kwargs): + if request.accepted_renderer.media_type in schema_media_types: + # Return a schema response. + schema = schema_generator.get_schema(request) + if schema is None: + raise exceptions.PermissionDenied() + return Response(schema) + + # Return a plain {"name": "hyperlink"} response. + ret = OrderedDict() + namespace = request.resolver_match.namespace + for key, url_name in api_root_dict.items(): + if namespace: + url_name = namespace + ':' + url_name + try: + ret[key] = reverse( + url_name, + args=args, + kwargs=kwargs, + request=request, + format=kwargs.get('format', None) + ) + except NoReverseMatch: + # Don't bail out if eg. no list routes exist, only detail routes. + continue + + return Response(ret) + + return APIRoot.as_view() + + def get_urls(self): + urls = super(AllViewsRouter, self).get_urls() + + for pattern, view, name in self.view_registry: + urls.append(url(pattern, view.as_view(), name=name)) + + return urls diff --git a/api/urls.py b/api/urls.py index dd3783dc..edf399c8 100644 --- a/api/urls.py +++ b/api/urls.py @@ -25,82 +25,80 @@ Urls de l'api, pointant vers les fonctions de views from __future__ import unicode_literals from django.conf.urls import url, include -from rest_framework.routers import DefaultRouter +from .routers import AllViewsRouter from . import views -router = DefaultRouter() +router = AllViewsRouter() # COTISATIONS APP -router.register(r'cotisations/factures', views.FactureViewSet) -router.register(r'cotisations/ventes', views.VenteViewSet) -router.register(r'cotisations/articles', views.ArticleViewSet) -router.register(r'cotisations/banques', views.BanqueViewSet) -router.register(r'cotisations/paiements', views.PaiementViewSet) -router.register(r'cotisations/cotisations', views.CotisationViewSet) +router.register_viewset(r'cotisations/factures', views.FactureViewSet) +router.register_viewset(r'cotisations/ventes', views.VenteViewSet) +router.register_viewset(r'cotisations/articles', views.ArticleViewSet) +router.register_viewset(r'cotisations/banques', views.BanqueViewSet) +router.register_viewset(r'cotisations/paiements', views.PaiementViewSet) +router.register_viewset(r'cotisations/cotisations', views.CotisationViewSet) # MACHINES APP -router.register(r'machines/machines', views.MachineViewSet) -router.register(r'machines/machinetypes', views.MachineTypeViewSet) -router.register(r'machines/iptypes', views.IpTypeViewSet) -router.register(r'machines/vlans', views.VlanViewSet) -router.register(r'machines/nas', views.NasViewSet) -router.register(r'machines/soa', views.SOAViewSet) -router.register(r'machines/extensions', views.ExtensionViewSet) -router.register(r'machines/mx', views.MxViewSet) -router.register(r'machines/ns', views.NsViewSet) -router.register(r'machines/txt', views.TxtViewSet) -router.register(r'machines/srv', views.SrvViewSet) -router.register(r'machines/interfaces', views.InterfaceViewSet) -router.register(r'machines/ipv6lists', views.Ipv6ListViewSet) -router.register(r'machines/domains', views.DomainViewSet) -router.register(r'machines/iplists', views.IpListViewSet) -router.register(r'machines/services', views.ServiceViewSet) -router.register(r'machines/servicelinks', views.ServiceLinkViewSet, base_name='servicelink') -router.register(r'machines/ouvertureportlists', views.OuverturePortListViewSet) -router.register(r'machines/ouvertureports', views.OuverturePortViewSet) +router.register_viewset(r'machines/machines', views.MachineViewSet) +router.register_viewset(r'machines/machinetypes', views.MachineTypeViewSet) +router.register_viewset(r'machines/iptypes', views.IpTypeViewSet) +router.register_viewset(r'machines/vlans', views.VlanViewSet) +router.register_viewset(r'machines/nas', views.NasViewSet) +router.register_viewset(r'machines/soa', views.SOAViewSet) +router.register_viewset(r'machines/extensions', views.ExtensionViewSet) +router.register_viewset(r'machines/mx', views.MxViewSet) +router.register_viewset(r'machines/ns', views.NsViewSet) +router.register_viewset(r'machines/txt', views.TxtViewSet) +router.register_viewset(r'machines/srv', views.SrvViewSet) +router.register_viewset(r'machines/interfaces', views.InterfaceViewSet) +router.register_viewset(r'machines/ipv6lists', views.Ipv6ListViewSet) +router.register_viewset(r'machines/domains', views.DomainViewSet) +router.register_viewset(r'machines/iplists', views.IpListViewSet) +router.register_viewset(r'machines/services', views.ServiceViewSet) +router.register_viewset(r'machines/servicelinks', views.ServiceLinkViewSet, base_name='servicelink') +router.register_viewset(r'machines/ouvertureportlists', views.OuverturePortListViewSet) +router.register_viewset(r'machines/ouvertureports', views.OuverturePortViewSet) # PREFERENCES APP -router.register(r'preferences/service', views.ServiceViewSet), +router.register_viewset(r'preferences/service', views.ServiceViewSet), +router.register_view(r'preferences/optionaluser', views.OptionalUserView), +router.register_view(r'preferences/optionalmachine', views.OptionalMachineView), +router.register_view(r'preferences/optionaltopologie', views.OptionalTopologieView), +router.register_view(r'preferences/generaloption', views.GeneralOptionView), +router.register_view(r'preferences/assooption', views.AssoOptionView), +router.register_view(r'preferences/homeoption', views.HomeOptionView), +router.register_view(r'preferences/mailmessageoption', views.MailMessageOptionView), # TOPOLOGIE APP -router.register(r'topologie/stack', views.StackViewSet) -router.register(r'topologie/acesspoint', views.AccessPointViewSet) -router.register(r'topologie/switch', views.SwitchViewSet) -router.register(r'topologie/modelswitch', views.ModelSwitchViewSet) -router.register(r'topologie/constructorswitch', views.ConstructorSwitchViewSet) -router.register(r'topologie/switchbay', views.SwitchBayViewSet) -router.register(r'topologie/building', views.BuildingViewSet) -router.register(r'topologie/switchport', views.SwitchPortViewSet, base_name='switchport') -router.register(r'topologie/room', views.RoomViewSet) +router.register_viewset(r'topologie/stack', views.StackViewSet) +router.register_viewset(r'topologie/acesspoint', views.AccessPointViewSet) +router.register_viewset(r'topologie/switch', views.SwitchViewSet) +router.register_viewset(r'topologie/modelswitch', views.ModelSwitchViewSet) +router.register_viewset(r'topologie/constructorswitch', views.ConstructorSwitchViewSet) +router.register_viewset(r'topologie/switchbay', views.SwitchBayViewSet) +router.register_viewset(r'topologie/building', views.BuildingViewSet) +router.register_viewset(r'topologie/switchport', views.SwitchPortViewSet, base_name='switchport') +router.register_viewset(r'topologie/room', views.RoomViewSet) # USERS APP -router.register(r'users/users', views.UserViewSet) -router.register(r'users/clubs', views.ClubViewSet) -router.register(r'users/adherents', views.AdherentViewSet) -router.register(r'users/serviceusers', views.ServiceUserViewSet) -router.register(r'users/schools', views.SchoolViewSet) -router.register(r'users/listrights', views.ListRightViewSet) -router.register(r'users/shells', views.ShellViewSet, base_name='shell') -router.register(r'users/bans', views.BanViewSet) -router.register(r'users/whitelists', views.WhitelistViewSet) +router.register_viewset(r'users/users', views.UserViewSet) +router.register_viewset(r'users/clubs', views.ClubViewSet) +router.register_viewset(r'users/adherents', views.AdherentViewSet) +router.register_viewset(r'users/serviceusers', views.ServiceUserViewSet) +router.register_viewset(r'users/schools', views.SchoolViewSet) +router.register_viewset(r'users/listrights', views.ListRightViewSet) +router.register_viewset(r'users/shells', views.ShellViewSet, base_name='shell') +router.register_viewset(r'users/bans', views.BanViewSet) +router.register_viewset(r'users/whitelists', views.WhitelistViewSet) # SERVICES REGEN -router.register(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen') +router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen') +# DHCP +router.register_view(r'dhcp/hostmacip', views.HostMacIpView), +# DNS +router.register_view(r'dns/zones', views.DNSZonesView), +# MAILING +router.register_view(r'mailing/standard', views.StandardMailingView), +router.register_view(r'mailing/club', views.ClubMailingView), +# TOKEN-AUTH +router.register_view(r'token-auth', views.ObtainExpiringAuthToken) urlpatterns = [ - # VIEWSETS url(r'^', include(router.urls)), - # PREFERENCES APP - url(r'^preferences/optionaluser', views.OptionalUserView.as_view()), - url(r'^preferences/optionalmachine', views.OptionalMachineView.as_view()), - url(r'^preferences/optionaltopologie', views.OptionalTopologieView.as_view()), - url(r'^preferences/generaloption', views.GeneralOptionView.as_view()), - url(r'^preferences/assooption', views.AssoOptionView.as_view()), - url(r'^preferences/homeoption', views.HomeOptionView.as_view()), - url(r'^preferences/mailmessageoption', views.MailMessageOptionView.as_view()), - # DHCP - url(r'^dhcp/hostmacip', views.HostMacIpView.as_view()), - # DNS - url(r'^dns/zones', views.DNSZonesView.as_view()), - # MAILING - url(r'^mailing/standard', views.StandardMailingView.as_view()), - url(r'^mailing/club', views.ClubMailingView.as_view()), - # TOKEN-AUTH - url(r'^token-auth', views.ObtainExpiringAuthToken.as_view()) ]