Skip to content

Commit

Permalink
[feature] REST API for main controller features #379
Browse files Browse the repository at this point in the history
Closes #379
  • Loading branch information
ManishShah120 committed Mar 14, 2021
1 parent 4005d9f commit dcd3d29
Show file tree
Hide file tree
Showing 8 changed files with 312 additions and 4 deletions.
Empty file.
89 changes: 89 additions & 0 deletions openwisp_controller/api/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from rest_framework import serializers
from swapper import load_model

from openwisp_users.api.mixins import FilterSerializerByOrgOwned
from openwisp_utils.api.serializers import ValidatedModelSerializer

Template = load_model('config', 'Template')
Vpn = load_model('config', 'Vpn')
Device = load_model('config', 'Device')
Config = load_model('config', 'Config')
TemplateTag = load_model('config', 'TemplateTag')
Organization = load_model('openwisp_users', 'Organization')
import json


class BaseMeta:
read_only_fields = ['created', 'modified']


class TemplateSerializer(ValidatedModelSerializer):
config = serializers.JSONField()
tags = serializers.PrimaryKeyRelatedField(
many=True, queryset=TemplateTag.objects.all()
)
default_values = serializers.JSONField()
organization = serializers.PrimaryKeyRelatedField(
allow_null=False, queryset=Organization.objects.all(), required=True
)

class Meta(BaseMeta):
model = Template
fields = [
'id',
'name',
'tags',
'organization',
'type',
'backend',
'default',
'required',
'default_values',
'config',
'created',
'modified',
]


class VpnSerializer(FilterSerializerByOrgOwned, ValidatedModelSerializer):
config = serializers.JSONField()

class Meta(BaseMeta):
model = Vpn
fields = '__all__'


class DeviceListSerializer(ValidatedModelSerializer):
class Meta(BaseMeta):
model = Device
fields = [
'id',
'name',
'organization',
'mac_address',
'key',
'last_ip',
'management_ip',
'model',
'os',
'system',
'notes',
]


class DeviceConfigSerializer(serializers.ModelSerializer):
config = serializers.JSONField()
context = serializers.JSONField()
device = serializers.StringRelatedField()

class Meta:
model = Config
fields = ['device', 'backend', 'status', 'templates', 'context', 'config']


class DeviceDetailSerializer(serializers.ModelSerializer):
configuration = DeviceConfigSerializer(source='config')

class Meta(BaseMeta):
model = Device
fields = DeviceListSerializer.Meta.fields + ['configuration']
45 changes: 45 additions & 0 deletions openwisp_controller/api/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from django.urls import include, path

from . import views as api_views

urlpatterns = [
path(
'controller/',
include(
[
path('template/', api_views.template_list, name='template_list',),
path(
'template/<str:pk>/',
api_views.template_detail,
name='template_detail',
),
path(
'template/<str:pk>/configuration/',
api_views.download_template_config,
name='download_template_config',
),
path('vpn/', api_views.vpn_list, name='vpn_list',),
path('vpn/<str:pk>/', api_views.vpn_detail, name='vpn_detail',),
path(
'vpn/<str:pk>/configuration/',
api_views.download_vpn_config,
name='download_vpn_config',
),
path('device/', api_views.device_list, name='device_list',),
path(
'device/<str:pk>/', api_views.device_detail, name='device_detail',
),
path(
'device-config/<str:pk>/',
api_views.device_config,
name='device_config',
),
path(
'device/<str:pk>/configuration/',
api_views.download_device_config,
name='download_device_config',
),
]
),
),
]
119 changes: 119 additions & 0 deletions openwisp_controller/api/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from rest_framework import pagination
from rest_framework.authentication import SessionAuthentication
from rest_framework.generics import (
ListCreateAPIView,
RetrieveAPIView,
RetrieveUpdateDestroyAPIView,
)
from rest_framework.permissions import DjangoModelPermissions, IsAuthenticated
from swapper import load_model

from openwisp_users.api.authentication import BearerAuthentication
from openwisp_users.api.mixins import FilterByOrganizationManaged
from openwisp_users.api.permissions import IsOrganizationManager

from ..config.admin import BaseConfigAdmin
from .serializers import (
DeviceConfigSerializer,
DeviceDetailSerializer,
DeviceListSerializer,
TemplateSerializer,
VpnSerializer,
)

Template = load_model('config', 'Template')
Vpn = load_model('config', 'Vpn')
Device = load_model('config', 'Device')
Config = load_model('config', 'Config')


class ListViewPagination(pagination.PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100


class ProtectedAPIMixin(FilterByOrganizationManaged):
authentication_classes = [BearerAuthentication, SessionAuthentication]
permission_classes = [
IsAuthenticated,
IsOrganizationManager,
DjangoModelPermissions,
]


class TemplateListCreateView(ProtectedAPIMixin, ListCreateAPIView):
serializer_class = TemplateSerializer
queryset = Template.objects.all()
pagination_class = ListViewPagination


class TemplateDetailView(ProtectedAPIMixin, RetrieveUpdateDestroyAPIView):
serializer_class = TemplateSerializer
queryset = Template.objects.all()


class DownloadTemplateconfiguration(ProtectedAPIMixin, RetrieveAPIView):
serializer_class = TemplateSerializer
queryset = Template.objects.none()
model = Template

def retrieve(self, request, *args, **kwargs):
return BaseConfigAdmin.download_view(self, request, pk=kwargs['pk'])


class VpnListCreateView(ProtectedAPIMixin, ListCreateAPIView):
serializer_class = VpnSerializer
queryset = Vpn.objects.all()
pagination_class = ListViewPagination


class VpnDetailView(ProtectedAPIMixin, RetrieveUpdateDestroyAPIView):
serializer_class = VpnSerializer
queryset = Vpn.objects.all()


class DownloadVpnView(ProtectedAPIMixin, RetrieveAPIView):
serializer_class = VpnSerializer
queryset = Vpn.objects.none()
model = Vpn

def retrieve(self, request, *args, **kwargs):
return BaseConfigAdmin.download_view(self, request, pk=kwargs['pk'])


class DeviceListCreateView(ProtectedAPIMixin, ListCreateAPIView):
serializer_class = DeviceListSerializer
queryset = Device.objects.all()
pagination_class = ListViewPagination


class DeviceConfigView(RetrieveUpdateDestroyAPIView):
serializer_class = DeviceConfigSerializer
queryset = Config.objects.all()


class DeviceDetailView(RetrieveUpdateDestroyAPIView):
serializer_class = DeviceDetailSerializer
queryset = Device.objects.all()


class DownloadDeviceView(ProtectedAPIMixin, RetrieveAPIView):
serializer_class = DeviceListSerializer
queryset = Device.objects.none()
model = Device

def retrieve(self, request, *args, **kwargs):
return BaseConfigAdmin.download_view(self, request, pk=kwargs['pk'])


template_list = TemplateListCreateView.as_view()
template_detail = TemplateDetailView.as_view()
download_template_config = DownloadTemplateconfiguration.as_view()
vpn_list = VpnListCreateView.as_view()
vpn_detail = VpnDetailView.as_view()
download_vpn_config = DownloadVpnView.as_view()
device_list = DeviceListCreateView.as_view()
device_config = DeviceConfigView.as_view()
device_detail = DeviceDetailView.as_view()
download_device_config = DownloadDeviceView().as_view()
11 changes: 11 additions & 0 deletions openwisp_controller/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import json

from swapper import load_model

from openwisp_users.models import Organization
from openwisp_users.tests.utils import TestOrganizationMixin

Template = load_model('config', 'Template')
Vpn = load_model('config', 'Vpn')
Device = load_model('config', 'Device')
Config = load_model('config', 'Config')
39 changes: 39 additions & 0 deletions openwisp_controller/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import json

from django.test import Client, TestCase
from django.urls import reverse
from swapper import load_model

from openwisp_controller.config.tests.utils import CreateConfigTemplateMixin
from openwisp_users.tests.utils import TestMultitenantAdminMixin, TestOrganizationMixin

from .utils import TestAdminMixin

Template = load_model('config', 'Template')
Vpn = load_model('config', 'Vpn')
Device = load_model('config', 'Device')
Config = load_model('config', 'Config')


class TestApi(
CreateConfigTemplateMixin,
TestAdminMixin,
TestOrganizationMixin,
TestMultitenantAdminMixin,
):
def setUp(self):
super().setUp()
self._create_org(name='org_a', slug='org_a')
self._login()

def test_get_template_api(self):
org1 = self._get_org()
print(org1)
post_data = self._create_template(organization=org1)
print(post_data)
response = self.client.post(
reverse('controller:template_list'),
data=post_data,
content_type='application/json',
)
print(response)
7 changes: 5 additions & 2 deletions tests/openwisp2/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@
'flat_json_widget',
# rest framework
'rest_framework',
'rest_framework.authtoken',
'rest_framework_gis',
'django_filters',
'drf_yasg',
# channels
'channels',
# 'debug_toolbar',
'debug_toolbar',
]
EXTENDED_APPS = ('django_x509', 'django_loci')

Expand All @@ -75,7 +78,7 @@
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# 'debug_toolbar.middleware.DebugToolbarMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
]

INTERNAL_IPS = ['127.0.0.1']
Expand Down
6 changes: 4 additions & 2 deletions tests/openwisp2/urls.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import os

from django.conf import settings
from django.conf.urls import include, url
from django.conf.urls import url
from django.conf.urls.static import static
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import reverse_lazy
from django.urls import include, path, reverse_lazy
from django.views.generic import RedirectView

from openwisp_controller.config.utils import get_controller_urls
Expand Down Expand Up @@ -38,6 +38,8 @@
url(r'^$', redirect_view, name='index'),
url(r'^admin/', admin.site.urls),
url(r'', include('openwisp_controller.urls')),
path('api/v1/', include('openwisp_utils.api.urls')),
path('api/v1/', include('openwisp_controller.api.urls')),
]

urlpatterns += staticfiles_urlpatterns()
Expand Down

0 comments on commit dcd3d29

Please sign in to comment.