mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-05 01:16:27 +00:00
Docstrings, docstrings everywhere
This commit is contained in:
parent
374dd8da1e
commit
ecc5ed0b22
10 changed files with 716 additions and 165 deletions
36
api/acl.py
36
api/acl.py
|
@ -1,4 +1,3 @@
|
||||||
# -*- mode: python; coding: utf-8 -*-
|
|
||||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
# 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
|
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
# quelques clics.
|
# quelques clics.
|
||||||
|
@ -19,36 +18,43 @@
|
||||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
"""api.acl
|
"""Defines the ACL for the whole API.
|
||||||
|
|
||||||
Here are defined some functions to check acl on the application.
|
Importing this module, creates the 'can view api' permission if not already
|
||||||
|
done.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
# Creates the 'use_api' permission if not created
|
def _create_api_permission():
|
||||||
# The 'use_api' is a fake permission in the sense
|
"""Creates the 'use_api' permission if not created.
|
||||||
# it is not associated with an existing model and
|
|
||||||
# this ensure the permission is created every tun
|
The 'use_api' is a fake permission in the sense it is not associated with an
|
||||||
api_content_type, created = ContentType.objects.get_or_create(
|
existing model and this ensure the permission is created every time this file
|
||||||
|
is imported.
|
||||||
|
"""
|
||||||
|
api_content_type, created = ContentType.objects.get_or_create(
|
||||||
app_label=settings.API_CONTENT_TYPE_APP_LABEL,
|
app_label=settings.API_CONTENT_TYPE_APP_LABEL,
|
||||||
model=settings.API_CONTENT_TYPE_MODEL
|
model=settings.API_CONTENT_TYPE_MODEL
|
||||||
)
|
)
|
||||||
if created:
|
if created:
|
||||||
api_content_type.save()
|
api_content_type.save()
|
||||||
api_permission, created = Permission.objects.get_or_create(
|
api_permission, created = Permission.objects.get_or_create(
|
||||||
name=settings.API_PERMISSION_NAME,
|
name=settings.API_PERMISSION_NAME,
|
||||||
content_type=api_content_type,
|
content_type=api_content_type,
|
||||||
codename=settings.API_PERMISSION_CODENAME
|
codename=settings.API_PERMISSION_CODENAME
|
||||||
)
|
)
|
||||||
if created:
|
if created:
|
||||||
api_permission.save()
|
api_permission.save()
|
||||||
|
|
||||||
|
|
||||||
|
_create_api_permission()
|
||||||
|
|
||||||
|
|
||||||
def can_view(user):
|
def can_view(user):
|
||||||
"""Check if an user can view the application.
|
"""Check if an user can view the application.
|
||||||
|
|
||||||
|
@ -64,4 +70,4 @@ def can_view(user):
|
||||||
'codename': settings.API_PERMISSION_CODENAME
|
'codename': settings.API_PERMISSION_CODENAME
|
||||||
}
|
}
|
||||||
can = user.has_perm('%(app_label)s.%(codename)s' % kwargs)
|
can = user.has_perm('%(app_label)s.%(codename)s' % kwargs)
|
||||||
return can, None if can else "Vous ne pouvez pas voir cette application."
|
return can, None if can else _("You cannot see this application.")
|
||||||
|
|
|
@ -1,20 +1,43 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""Defines the authentication classes used in the API to authenticate a user.
|
||||||
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework.authentication import TokenAuthentication
|
from rest_framework.authentication import TokenAuthentication
|
||||||
from rest_framework import exceptions
|
from rest_framework import exceptions
|
||||||
|
|
||||||
class ExpiringTokenAuthentication(TokenAuthentication):
|
class ExpiringTokenAuthentication(TokenAuthentication):
|
||||||
|
"""Authenticate a user if the provided token is valid and not expired.
|
||||||
|
"""
|
||||||
def authenticate_credentials(self, key):
|
def authenticate_credentials(self, key):
|
||||||
model = self.get_model()
|
"""See base class. Add the verification the token is not expired.
|
||||||
try:
|
"""
|
||||||
token = model.objects.select_related('user').get(key=key)
|
base = super(ExpiringTokenAuthentication, self)
|
||||||
except model.DoesNotExist:
|
user, token = base.authenticate_credentials(key)
|
||||||
raise exceptions.AuthenticationFailed(_('Invalid token.'))
|
|
||||||
|
|
||||||
if not token.user.is_active:
|
|
||||||
raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))
|
|
||||||
|
|
||||||
|
# Check that the genration time of the token is not too old
|
||||||
token_duration = datetime.timedelta(
|
token_duration = datetime.timedelta(
|
||||||
seconds=settings.API_TOKEN_DURATION
|
seconds=settings.API_TOKEN_DURATION
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,15 +1,57 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""Defines the pagination classes used in the API to paginate the results.
|
||||||
|
"""
|
||||||
|
|
||||||
from rest_framework import pagination
|
from rest_framework import pagination
|
||||||
|
|
||||||
|
|
||||||
class PageSizedPagination(pagination.PageNumberPagination):
|
class PageSizedPagination(pagination.PageNumberPagination):
|
||||||
"""
|
"""Provide the possibility to control the page size by using the
|
||||||
Pagination subclass to all to control the page size
|
'page_size' parameter. The value 'all' can be used for this parameter
|
||||||
|
to retrieve all the results in a single page.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
page_size_query_param: The string to look for in the parameters of
|
||||||
|
a query to get the page_size requested.
|
||||||
|
all_pages_strings: A set of strings that can be used in the query to
|
||||||
|
request all results in a single page.
|
||||||
|
max_page_size: The maximum number of results a page can output no
|
||||||
|
matter what is requested.
|
||||||
"""
|
"""
|
||||||
page_size_query_param = 'page_size'
|
page_size_query_param = 'page_size'
|
||||||
all_pages_strings = ('all',)
|
all_pages_strings = ('all',)
|
||||||
max_page_size = 10000
|
max_page_size = 10000
|
||||||
|
|
||||||
def get_page_size(self, request):
|
def get_page_size(self, request):
|
||||||
|
"""Retrieve the size of the page according to the parameters of the
|
||||||
|
request.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request: the request of the user
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A integer between 0 and `max_page_size` that represent the size
|
||||||
|
of the page to use.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
page_size_str = request.query_params[self.page_size_query_param]
|
page_size_str = request.query_params[self.page_size_query_param]
|
||||||
if page_size_str in self.all_pages_strings:
|
if page_size_str in self.all_pages_strings:
|
||||||
|
|
|
@ -1,13 +1,61 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""Defines the permission classes used in the API.
|
||||||
|
"""
|
||||||
|
|
||||||
from rest_framework import permissions, exceptions
|
from rest_framework import permissions, exceptions
|
||||||
|
|
||||||
from re2o.acl import can_create, can_edit, can_delete, can_view_all
|
from re2o.acl import can_create, can_edit, can_delete, can_view_all
|
||||||
|
|
||||||
from . import acl
|
from . import acl
|
||||||
|
|
||||||
|
|
||||||
def can_see_api(*_, **__):
|
def can_see_api(*_, **__):
|
||||||
|
"""Check if a user can view the API.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A function that takes a user as an argument and returns
|
||||||
|
an ACL tuple that assert this user can see the API.
|
||||||
|
"""
|
||||||
return lambda user: acl.can_view(user)
|
return lambda user: acl.can_view(user)
|
||||||
|
|
||||||
|
|
||||||
def _get_param_in_view(view, param_name):
|
def _get_param_in_view(view, param_name):
|
||||||
|
"""Utility function to retrieve an attribute in a view passed in argument.
|
||||||
|
|
||||||
|
Uses the result of `{view}.get_{param_name}()` if existing else uses the
|
||||||
|
value of `{view}.{param_name}` directly.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
view: The view where to look into.
|
||||||
|
param_name: The name of the attribute to look for.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The result of the getter function if found else the value of the
|
||||||
|
attribute itself.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: None of the getter function or the attribute are
|
||||||
|
defined in the view.
|
||||||
|
"""
|
||||||
assert hasattr(view, 'get_'+param_name) \
|
assert hasattr(view, 'get_'+param_name) \
|
||||||
or getattr(view, param_name, None) is not None, (
|
or getattr(view, param_name, None) is not None, (
|
||||||
'cannot apply {} on a view that does not set '
|
'cannot apply {} on a view that does not set '
|
||||||
|
@ -24,15 +72,30 @@ def _get_param_in_view(view, param_name):
|
||||||
|
|
||||||
|
|
||||||
class ACLPermission(permissions.BasePermission):
|
class ACLPermission(permissions.BasePermission):
|
||||||
"""
|
"""A permission class used to check the ACL to validate the permissions
|
||||||
Permission subclass for views that requires a specific model-based
|
of a user.
|
||||||
permission or don't define a queryset
|
|
||||||
|
The view must define a `.get_perms_map()` or a `.perms_map` attribute.
|
||||||
|
See the wiki for the syntax of this attribute.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_required_permissions(self, method, view):
|
def get_required_permissions(self, method, view):
|
||||||
"""
|
"""Build the list of permissions required for the request to be
|
||||||
Given a list of models and an HTTP method, return the list
|
accepted.
|
||||||
of acl functions that the user is required to verify.
|
|
||||||
|
Args:
|
||||||
|
method: The HTTP method name used for the request.
|
||||||
|
view: The view which is responding to the request.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The list of ACL functions to apply to a user in order to check
|
||||||
|
if he has the right permissions.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: None of `.get_perms_map()` or `.perms_map` are
|
||||||
|
defined in the view.
|
||||||
|
rest_framework.exception.MethodNotAllowed: The requested method
|
||||||
|
is not allowed for this view.
|
||||||
"""
|
"""
|
||||||
perms_map = _get_param_in_view(view, 'perms_map')
|
perms_map = _get_param_in_view(view, 'perms_map')
|
||||||
|
|
||||||
|
@ -42,6 +105,22 @@ class ACLPermission(permissions.BasePermission):
|
||||||
return [can_see_api()] + list(perms_map[method])
|
return [can_see_api()] + list(perms_map[method])
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
|
"""Check that the user has the permissions to perform the request.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request: The request performed.
|
||||||
|
view: The view which is responding to the request.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean indicating if the user has the permission to
|
||||||
|
perform the request.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: None of `.get_perms_map()` or `.perms_map` are
|
||||||
|
defined in the view.
|
||||||
|
rest_framework.exception.MethodNotAllowed: The requested method
|
||||||
|
is not allowed for this view.
|
||||||
|
"""
|
||||||
# Workaround to ensure ACLPermissions are not applied
|
# Workaround to ensure ACLPermissions are not applied
|
||||||
# to the root view when using DefaultRouter.
|
# to the root view when using DefaultRouter.
|
||||||
if getattr(view, '_ignore_model_permissions', False):
|
if getattr(view, '_ignore_model_permissions', False):
|
||||||
|
@ -54,19 +133,20 @@ class ACLPermission(permissions.BasePermission):
|
||||||
|
|
||||||
return all(perm(request.user)[0] for perm in perms)
|
return all(perm(request.user)[0] for perm in perms)
|
||||||
|
|
||||||
def has_object_permission(self, request, view, obj):
|
|
||||||
# Should never be called here but documentation
|
|
||||||
# requires to implement this function
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class AutodetectACLPermission(permissions.BasePermission):
|
class AutodetectACLPermission(permissions.BasePermission):
|
||||||
|
"""A permission class used to autodetect the ACL needed to validate the
|
||||||
|
permissions of a user based on the queryset of the view.
|
||||||
|
|
||||||
|
The view must define a `.get_queryset()` or a `.queryset` attribute.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
perms_map: The mapping of each valid HTTP method to the required
|
||||||
|
model-based ACL permissions.
|
||||||
|
perms_obj_map: The mapping of each valid HTTP method to the required
|
||||||
|
object-based ACL permissions.
|
||||||
"""
|
"""
|
||||||
Permission subclass in charge of checking the ACL to determine
|
|
||||||
if a user can access the models. Autodetect which ACL are required
|
|
||||||
based on a queryset. Requires `.queryset` or `.get_queryset()`
|
|
||||||
to be defined in the view.
|
|
||||||
"""
|
|
||||||
perms_map = {
|
perms_map = {
|
||||||
'GET': [can_see_api, lambda model: model.can_view_all],
|
'GET': [can_see_api, lambda model: model.can_view_all],
|
||||||
'OPTIONS': [can_see_api, lambda model: model.can_view_all],
|
'OPTIONS': [can_see_api, lambda model: model.can_view_all],
|
||||||
|
@ -87,9 +167,20 @@ class AutodetectACLPermission(permissions.BasePermission):
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_required_permissions(self, method, model):
|
def get_required_permissions(self, method, model):
|
||||||
"""
|
"""Build the list of model-based permissions required for the
|
||||||
Given a model and an HTTP method, return the list of acl
|
request to be accepted.
|
||||||
functions that the user is required to verify.
|
|
||||||
|
Args:
|
||||||
|
method: The HTTP method name used for the request.
|
||||||
|
view: The view which is responding to the request.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The list of ACL functions to apply to a user in order to check
|
||||||
|
if he has the right permissions.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
rest_framework.exception.MethodNotAllowed: The requested method
|
||||||
|
is not allowed for this view.
|
||||||
"""
|
"""
|
||||||
if method not in self.perms_map:
|
if method not in self.perms_map:
|
||||||
raise exceptions.MethodNotAllowed(method)
|
raise exceptions.MethodNotAllowed(method)
|
||||||
|
@ -97,9 +188,20 @@ class AutodetectACLPermission(permissions.BasePermission):
|
||||||
return [perm(model) for perm in self.perms_map[method]]
|
return [perm(model) for perm in self.perms_map[method]]
|
||||||
|
|
||||||
def get_required_object_permissions(self, method, obj):
|
def get_required_object_permissions(self, method, obj):
|
||||||
"""
|
"""Build the list of object-based permissions required for the
|
||||||
Given an object and an HTTP method, return the list of acl
|
request to be accepted.
|
||||||
functions that the user is required to verify.
|
|
||||||
|
Args:
|
||||||
|
method: The HTTP method name used for the request.
|
||||||
|
view: The view which is responding to the request.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The list of ACL functions to apply to a user in order to check
|
||||||
|
if he has the right permissions.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
rest_framework.exception.MethodNotAllowed: The requested method
|
||||||
|
is not allowed for this view.
|
||||||
"""
|
"""
|
||||||
if method not in self.perms_obj_map:
|
if method not in self.perms_obj_map:
|
||||||
raise exceptions.MethodNotAllowed(method)
|
raise exceptions.MethodNotAllowed(method)
|
||||||
|
@ -107,13 +209,26 @@ class AutodetectACLPermission(permissions.BasePermission):
|
||||||
return [perm(obj) for perm in self.perms_obj_map[method]]
|
return [perm(obj) for perm in self.perms_obj_map[method]]
|
||||||
|
|
||||||
def _queryset(self, view):
|
def _queryset(self, view):
|
||||||
"""
|
|
||||||
Return the queryset associated with view and raise an error
|
|
||||||
is there is none.
|
|
||||||
"""
|
|
||||||
return _get_param_in_view(view, 'queryset')
|
return _get_param_in_view(view, 'queryset')
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
|
"""Check that the user has the model-based permissions to perform
|
||||||
|
the request.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request: The request performed.
|
||||||
|
view: The view which is responding to the request.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean indicating if the user has the permission to
|
||||||
|
perform the request.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: None of `.get_queryset()` or `.queryset` are
|
||||||
|
defined in the view.
|
||||||
|
rest_framework.exception.MethodNotAllowed: The requested method
|
||||||
|
is not allowed for this view.
|
||||||
|
"""
|
||||||
# Workaround to ensure ACLPermissions are not applied
|
# Workaround to ensure ACLPermissions are not applied
|
||||||
# to the root view when using DefaultRouter.
|
# to the root view when using DefaultRouter.
|
||||||
if getattr(view, '_ignore_model_permissions', False):
|
if getattr(view, '_ignore_model_permissions', False):
|
||||||
|
@ -128,8 +243,22 @@ class AutodetectACLPermission(permissions.BasePermission):
|
||||||
return all(perm(request.user)[0] for perm in perms)
|
return all(perm(request.user)[0] for perm in perms)
|
||||||
|
|
||||||
def has_object_permission(self, request, view, obj):
|
def has_object_permission(self, request, view, obj):
|
||||||
|
"""Check that the user has the object-based permissions to perform
|
||||||
|
the request.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request: The request performed.
|
||||||
|
view: The view which is responding to the request.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean indicating if the user has the permission to
|
||||||
|
perform the request.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
rest_framework.exception.MethodNotAllowed: The requested method
|
||||||
|
is not allowed for this view.
|
||||||
|
"""
|
||||||
# authentication checks have already executed via has_permission
|
# authentication checks have already executed via has_permission
|
||||||
queryset = self._queryset(view)
|
|
||||||
user = request.user
|
user = request.user
|
||||||
|
|
||||||
perms = self.get_required_object_permissions(request.method, obj)
|
perms = self.get_required_object_permissions(request.method, obj)
|
||||||
|
|
|
@ -17,12 +17,12 @@
|
||||||
# You should have received a copy of the GNU General Public License along
|
# 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.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
"""api.routers
|
|
||||||
|
|
||||||
Definition of the custom routers to generate the URLs of the API
|
"""Defines the custom routers to generate the URLs of the API.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
from django.core.urlresolvers import NoReverseMatch
|
from django.core.urlresolvers import NoReverseMatch
|
||||||
from rest_framework import views
|
from rest_framework import views
|
||||||
|
@ -32,32 +32,60 @@ from rest_framework.reverse import reverse
|
||||||
from rest_framework.schemas import SchemaGenerator
|
from rest_framework.schemas import SchemaGenerator
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
|
|
||||||
class AllViewsRouter(DefaultRouter):
|
class AllViewsRouter(DefaultRouter):
|
||||||
|
"""A router that can register both viewsets and views and generates
|
||||||
|
a full API root page with all the generated URLs.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.view_registry = []
|
self.view_registry = []
|
||||||
super(AllViewsRouter, self).__init__(*args, **kwargs)
|
super(AllViewsRouter, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def register_viewset(self, *args, **kwargs):
|
def register_viewset(self, *args, **kwargs):
|
||||||
"""
|
"""Register a viewset in the router. Alias of `register` for
|
||||||
Register a viewset in the router
|
convenience.
|
||||||
Alias of `register` for convenience
|
|
||||||
|
See `register` in the base class for details.
|
||||||
"""
|
"""
|
||||||
return self.register(*args, **kwargs)
|
return self.register(*args, **kwargs)
|
||||||
|
|
||||||
def register_view(self, pattern, view, name=None):
|
def register_view(self, pattern, view, name=None):
|
||||||
"""
|
"""Register a view in the router.
|
||||||
Register a view in the router
|
|
||||||
|
Args:
|
||||||
|
pattern: The URL pattern to use for this view.
|
||||||
|
view: The class-based view to register.
|
||||||
|
name: An optional name for the route generated. Defaults is
|
||||||
|
based on the pattern last section (delimited by '/').
|
||||||
"""
|
"""
|
||||||
if name is None:
|
if name is None:
|
||||||
name = self.get_default_name(pattern)
|
name = self.get_default_name(pattern)
|
||||||
self.view_registry.append((pattern, view, name))
|
self.view_registry.append((pattern, view, name))
|
||||||
|
|
||||||
def get_default_name(self, pattern):
|
def get_default_name(self, pattern):
|
||||||
|
"""Returns the name to use for the route if none was specified.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pattern: The pattern for this route.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The name to use for this route.
|
||||||
|
"""
|
||||||
return pattern.split('/')[-1]
|
return pattern.split('/')[-1]
|
||||||
|
|
||||||
def get_api_root_view(self, schema_urls=None):
|
def get_api_root_view(self, schema_urls=None):
|
||||||
"""
|
"""Create a class-based view to use as the API root.
|
||||||
Return a view to use as the API root.
|
|
||||||
|
Highly inspired by the base class. See details on the implementation
|
||||||
|
in the base class. The only difference is that registered view URLs
|
||||||
|
are added after the registered viewset URLs on this root API page.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
schema_urls: A schema to use for the URLs.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The view to use to display the root API page.
|
||||||
"""
|
"""
|
||||||
api_root_dict = OrderedDict()
|
api_root_dict = OrderedDict()
|
||||||
list_name = self.routes[0].name
|
list_name = self.routes[0].name
|
||||||
|
@ -115,6 +143,12 @@ class AllViewsRouter(DefaultRouter):
|
||||||
return APIRoot.as_view()
|
return APIRoot.as_view()
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
|
"""Builds the list of URLs to register.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of the URLs generated based on the viewsets registered
|
||||||
|
followed by the URLs generated based on the views registered.
|
||||||
|
"""
|
||||||
urls = super(AllViewsRouter, self).get_urls()
|
urls = super(AllViewsRouter, self).get_urls()
|
||||||
|
|
||||||
for pattern, view, name in self.view_registry:
|
for pattern, view, name in self.view_registry:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
# quelques clics.
|
# quelques clics.
|
||||||
#
|
#
|
||||||
# Copyright © 2018 Mael Kervella
|
# Copyright © 2018 Maël Kervella
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,8 +18,7 @@
|
||||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
"""
|
"""Defines the serializers of the API
|
||||||
Serializers for the API app
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
@ -31,12 +30,15 @@ import topologie.models as topologie
|
||||||
import users.models as users
|
import users.models as users
|
||||||
|
|
||||||
|
|
||||||
|
# The namespace used for the API. It must match the namespace used in the
|
||||||
|
# urlpatterns to include the API URLs.
|
||||||
API_NAMESPACE = 'api'
|
API_NAMESPACE = 'api'
|
||||||
|
|
||||||
|
|
||||||
class NamespacedHRField(serializers.HyperlinkedRelatedField):
|
class NamespacedHRField(serializers.HyperlinkedRelatedField):
|
||||||
""" A HyperlinkedRelatedField subclass to automatically prefix
|
"""A `rest_framework.serializers.HyperlinkedRelatedField` subclass to
|
||||||
view names with a namespace """
|
automatically prefix view names with the API namespace.
|
||||||
|
"""
|
||||||
def __init__(self, view_name=None, **kwargs):
|
def __init__(self, view_name=None, **kwargs):
|
||||||
if view_name is not None:
|
if view_name is not None:
|
||||||
view_name = '%s:%s' % (API_NAMESPACE, view_name)
|
view_name = '%s:%s' % (API_NAMESPACE, view_name)
|
||||||
|
@ -44,8 +46,9 @@ class NamespacedHRField(serializers.HyperlinkedRelatedField):
|
||||||
|
|
||||||
|
|
||||||
class NamespacedHIField(serializers.HyperlinkedIdentityField):
|
class NamespacedHIField(serializers.HyperlinkedIdentityField):
|
||||||
""" A HyperlinkedIdentityField subclass to automatically prefix
|
"""A `rest_framework.serializers.HyperlinkedIdentityField` subclass to
|
||||||
view names with a namespace """
|
automatically prefix view names with teh API namespace.
|
||||||
|
"""
|
||||||
def __init__(self, view_name=None, **kwargs):
|
def __init__(self, view_name=None, **kwargs):
|
||||||
if view_name is not None:
|
if view_name is not None:
|
||||||
view_name = '%s:%s' % (API_NAMESPACE, view_name)
|
view_name = '%s:%s' % (API_NAMESPACE, view_name)
|
||||||
|
@ -53,16 +56,19 @@ class NamespacedHIField(serializers.HyperlinkedIdentityField):
|
||||||
|
|
||||||
|
|
||||||
class NamespacedHMSerializer(serializers.HyperlinkedModelSerializer):
|
class NamespacedHMSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
""" A HyperlinkedModelSerializer subclass to use `NamespacedHRField` as
|
"""A `rest_framework.serializers.HyperlinkedModelSerializer` subclass to
|
||||||
field and automatically prefix view names with a namespace """
|
automatically prefix view names with the API namespace.
|
||||||
|
"""
|
||||||
serializer_related_field = NamespacedHRField
|
serializer_related_field = NamespacedHRField
|
||||||
serializer_url_field = NamespacedHIField
|
serializer_url_field = NamespacedHIField
|
||||||
|
|
||||||
|
|
||||||
# COTISATIONS APP
|
# COTISATIONS
|
||||||
|
|
||||||
|
|
||||||
class FactureSerializer(NamespacedHMSerializer):
|
class FactureSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `cotisations.models.Facture` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Facture
|
model = cotisations.Facture
|
||||||
fields = ('user', 'paiement', 'banque', 'cheque', 'date', 'valid',
|
fields = ('user', 'paiement', 'banque', 'cheque', 'date', 'valid',
|
||||||
|
@ -70,6 +76,8 @@ class FactureSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class VenteSerializer(NamespacedHMSerializer):
|
class VenteSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `cotisations.models.Vente` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Vente
|
model = cotisations.Vente
|
||||||
fields = ('facture', 'number', 'name', 'prix', 'duration',
|
fields = ('facture', 'number', 'name', 'prix', 'duration',
|
||||||
|
@ -77,6 +85,8 @@ class VenteSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ArticleSerializer(NamespacedHMSerializer):
|
class ArticleSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `cotisations.models.Article` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Article
|
model = cotisations.Article
|
||||||
fields = ('name', 'prix', 'duration', 'type_user',
|
fields = ('name', 'prix', 'duration', 'type_user',
|
||||||
|
@ -84,40 +94,52 @@ class ArticleSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class BanqueSerializer(NamespacedHMSerializer):
|
class BanqueSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `cotisations.models.Banque` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Banque
|
model = cotisations.Banque
|
||||||
fields = ('name', 'api_url')
|
fields = ('name', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class PaiementSerializer(NamespacedHMSerializer):
|
class PaiementSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `cotisations.models.Paiement` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Paiement
|
model = cotisations.Paiement
|
||||||
fields = ('moyen', 'type_paiement', 'api_url')
|
fields = ('moyen', 'type_paiement', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class CotisationSerializer(NamespacedHMSerializer):
|
class CotisationSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `cotisations.models.Cotisation` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Cotisation
|
model = cotisations.Cotisation
|
||||||
fields = ('vente', 'type_cotisation', 'date_start', 'date_end',
|
fields = ('vente', 'type_cotisation', 'date_start', 'date_end',
|
||||||
'api_url')
|
'api_url')
|
||||||
|
|
||||||
|
|
||||||
# MACHINES APP
|
# MACHINES
|
||||||
|
|
||||||
|
|
||||||
class MachineSerializer(NamespacedHMSerializer):
|
class MachineSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Machine` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Machine
|
model = machines.Machine
|
||||||
fields = ('user', 'name', 'active', 'api_url')
|
fields = ('user', 'name', 'active', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class MachineTypeSerializer(NamespacedHMSerializer):
|
class MachineTypeSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.MachineType` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.MachineType
|
model = machines.MachineType
|
||||||
fields = ('type', 'ip_type', 'api_url')
|
fields = ('type', 'ip_type', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class IpTypeSerializer(NamespacedHMSerializer):
|
class IpTypeSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.IpType` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.IpType
|
model = machines.IpType
|
||||||
fields = ('type', 'extension', 'need_infra', 'domaine_ip_start',
|
fields = ('type', 'extension', 'need_infra', 'domaine_ip_start',
|
||||||
|
@ -126,12 +148,16 @@ class IpTypeSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class VlanSerializer(NamespacedHMSerializer):
|
class VlanSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Vlan` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Vlan
|
model = machines.Vlan
|
||||||
fields = ('vlan_id', 'name', 'comment', 'api_url')
|
fields = ('vlan_id', 'name', 'comment', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class NasSerializer(NamespacedHMSerializer):
|
class NasSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Nas` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Nas
|
model = machines.Nas
|
||||||
fields = ('name', 'nas_type', 'machine_type', 'port_access_mode',
|
fields = ('name', 'nas_type', 'machine_type', 'port_access_mode',
|
||||||
|
@ -139,6 +165,8 @@ class NasSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SOASerializer(NamespacedHMSerializer):
|
class SOASerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.SOA` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.SOA
|
model = machines.SOA
|
||||||
fields = ('name', 'mail', 'refresh', 'retry', 'expire', 'ttl',
|
fields = ('name', 'mail', 'refresh', 'retry', 'expire', 'ttl',
|
||||||
|
@ -146,6 +174,8 @@ class SOASerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ExtensionSerializer(NamespacedHMSerializer):
|
class ExtensionSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Extension` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Extension
|
model = machines.Extension
|
||||||
fields = ('name', 'need_infra', 'origin', 'origin_v6', 'soa',
|
fields = ('name', 'need_infra', 'origin', 'origin_v6', 'soa',
|
||||||
|
@ -153,24 +183,32 @@ class ExtensionSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class MxSerializer(NamespacedHMSerializer):
|
class MxSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Mx` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Mx
|
model = machines.Mx
|
||||||
fields = ('zone', 'priority', 'name', 'api_url')
|
fields = ('zone', 'priority', 'name', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class NsSerializer(NamespacedHMSerializer):
|
class NsSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Ns` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Ns
|
model = machines.Ns
|
||||||
fields = ('zone', 'ns', 'api_url')
|
fields = ('zone', 'ns', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class TxtSerializer(NamespacedHMSerializer):
|
class TxtSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Txt` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Txt
|
model = machines.Txt
|
||||||
fields = ('zone', 'field1', 'field2', 'api_url')
|
fields = ('zone', 'field1', 'field2', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class SrvSerializer(NamespacedHMSerializer):
|
class SrvSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Srv` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Srv
|
model = machines.Srv
|
||||||
fields = ('service', 'protocole', 'extension', 'ttl', 'priority',
|
fields = ('service', 'protocole', 'extension', 'ttl', 'priority',
|
||||||
|
@ -178,6 +216,8 @@ class SrvSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class InterfaceSerializer(NamespacedHMSerializer):
|
class InterfaceSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Interface` objects.
|
||||||
|
"""
|
||||||
mac_address = serializers.CharField()
|
mac_address = serializers.CharField()
|
||||||
active = serializers.BooleanField(source='is_active')
|
active = serializers.BooleanField(source='is_active')
|
||||||
|
|
||||||
|
@ -188,12 +228,16 @@ class InterfaceSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class Ipv6ListSerializer(NamespacedHMSerializer):
|
class Ipv6ListSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Ipv6List` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Ipv6List
|
model = machines.Ipv6List
|
||||||
fields = ('ipv6', 'interface', 'slaac_ip', 'api_url')
|
fields = ('ipv6', 'interface', 'slaac_ip', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class DomainSerializer(NamespacedHMSerializer):
|
class DomainSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Domain` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Domain
|
model = machines.Domain
|
||||||
fields = ('interface_parent', 'name', 'extension', 'cname',
|
fields = ('interface_parent', 'name', 'extension', 'cname',
|
||||||
|
@ -201,12 +245,16 @@ class DomainSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class IpListSerializer(NamespacedHMSerializer):
|
class IpListSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.IpList` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.IpList
|
model = machines.IpList
|
||||||
fields = ('ipv4', 'ip_type', 'need_infra', 'api_url')
|
fields = ('ipv4', 'ip_type', 'need_infra', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class ServiceSerializer(NamespacedHMSerializer):
|
class ServiceSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Service` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Service
|
model = machines.Service
|
||||||
fields = ('service_type', 'min_time_regen', 'regular_time_regen',
|
fields = ('service_type', 'min_time_regen', 'regular_time_regen',
|
||||||
|
@ -214,6 +262,8 @@ class ServiceSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ServiceLinkSerializer(NamespacedHMSerializer):
|
class ServiceLinkSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.Service_link` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Service_link
|
model = machines.Service_link
|
||||||
fields = ('service', 'server', 'last_regen', 'asked_regen',
|
fields = ('service', 'server', 'last_regen', 'asked_regen',
|
||||||
|
@ -224,6 +274,8 @@ class ServiceLinkSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortListSerializer(NamespacedHMSerializer):
|
class OuverturePortListSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.OuverturePortList` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.OuverturePortList
|
model = machines.OuverturePortList
|
||||||
fields = ('name', 'tcp_ports_in', 'udp_ports_in', 'tcp_ports_out',
|
fields = ('name', 'tcp_ports_in', 'udp_ports_in', 'tcp_ports_out',
|
||||||
|
@ -231,15 +283,19 @@ class OuverturePortListSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortSerializer(NamespacedHMSerializer):
|
class OuverturePortSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.OuverturePort` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.OuverturePort
|
model = machines.OuverturePort
|
||||||
fields = ('begin', 'end', 'port_list', 'protocole', 'io', 'api_url')
|
fields = ('begin', 'end', 'port_list', 'protocole', 'io', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
# PREFERENCES APP
|
# PREFERENCES
|
||||||
|
|
||||||
|
|
||||||
class OptionalUserSerializer(NamespacedHMSerializer):
|
class OptionalUserSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `preferences.models.OptionalUser` objects.
|
||||||
|
"""
|
||||||
tel_mandatory = serializers.BooleanField(source='is_tel_mandatory')
|
tel_mandatory = serializers.BooleanField(source='is_tel_mandatory')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -250,6 +306,8 @@ class OptionalUserSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class OptionalMachineSerializer(NamespacedHMSerializer):
|
class OptionalMachineSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `preferences.models.OptionalMachine` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.OptionalMachine
|
model = preferences.OptionalMachine
|
||||||
fields = ('password_machine', 'max_lambdauser_interfaces',
|
fields = ('password_machine', 'max_lambdauser_interfaces',
|
||||||
|
@ -258,6 +316,8 @@ class OptionalMachineSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class OptionalTopologieSerializer(NamespacedHMSerializer):
|
class OptionalTopologieSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `preferences.models.OptionalTopologie` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.OptionalTopologie
|
model = preferences.OptionalTopologie
|
||||||
fields = ('radius_general_policy', 'vlan_decision_ok',
|
fields = ('radius_general_policy', 'vlan_decision_ok',
|
||||||
|
@ -265,6 +325,8 @@ class OptionalTopologieSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class GeneralOptionSerializer(NamespacedHMSerializer):
|
class GeneralOptionSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `preferences.models.GeneralOption` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.GeneralOption
|
model = preferences.GeneralOption
|
||||||
fields = ('general_message', 'search_display_page',
|
fields = ('general_message', 'search_display_page',
|
||||||
|
@ -274,12 +336,16 @@ class GeneralOptionSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ServiceSerializer(NamespacedHMSerializer):
|
class ServiceSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `preferences.models.Service` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.Service
|
model = preferences.Service
|
||||||
fields = ('name', 'url', 'description', 'image', 'api_url')
|
fields = ('name', 'url', 'description', 'image', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class AssoOptionSerializer(NamespacedHMSerializer):
|
class AssoOptionSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `preferences.models.AssoOption` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.AssoOption
|
model = preferences.AssoOption
|
||||||
fields = ('name', 'siret', 'adresse1', 'adresse2', 'contact',
|
fields = ('name', 'siret', 'adresse1', 'adresse2', 'contact',
|
||||||
|
@ -288,22 +354,28 @@ class AssoOptionSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class HomeOptionSerializer(NamespacedHMSerializer):
|
class HomeOptionSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `preferences.models.HomeOption` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.HomeOption
|
model = preferences.HomeOption
|
||||||
fields = ('facebook_url', 'twitter_url', 'twitter_account_name')
|
fields = ('facebook_url', 'twitter_url', 'twitter_account_name')
|
||||||
|
|
||||||
|
|
||||||
class MailMessageOptionSerializer(NamespacedHMSerializer):
|
class MailMessageOptionSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `preferences.models.MailMessageOption` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.MailMessageOption
|
model = preferences.MailMessageOption
|
||||||
fields = ('welcome_mail_fr', 'welcome_mail_en')
|
fields = ('welcome_mail_fr', 'welcome_mail_en')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# TOPOLOGIE APP
|
# TOPOLOGIE
|
||||||
|
|
||||||
|
|
||||||
class StackSerializer(NamespacedHMSerializer):
|
class StackSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.Stack` objects
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.Stack
|
model = topologie.Stack
|
||||||
fields = ('name', 'stack_id', 'details', 'member_id_min',
|
fields = ('name', 'stack_id', 'details', 'member_id_min',
|
||||||
|
@ -311,12 +383,16 @@ class StackSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AccessPointSerializer(NamespacedHMSerializer):
|
class AccessPointSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.AccessPoint` objects
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.AccessPoint
|
model = topologie.AccessPoint
|
||||||
fields = ('user', 'name', 'active', 'location', 'api_url')
|
fields = ('user', 'name', 'active', 'location', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class SwitchSerializer(NamespacedHMSerializer):
|
class SwitchSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.Switch` objects
|
||||||
|
"""
|
||||||
port_amount = serializers.IntegerField(source='number')
|
port_amount = serializers.IntegerField(source='number')
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.Switch
|
model = topologie.Switch
|
||||||
|
@ -325,30 +401,40 @@ class SwitchSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ModelSwitchSerializer(NamespacedHMSerializer):
|
class ModelSwitchSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.ModelSwitch` objects
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.ModelSwitch
|
model = topologie.ModelSwitch
|
||||||
fields = ('reference', 'constructor', 'api_url')
|
fields = ('reference', 'constructor', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class ConstructorSwitchSerializer(NamespacedHMSerializer):
|
class ConstructorSwitchSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.ConstructorSwitch` objects
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.ConstructorSwitch
|
model = topologie.ConstructorSwitch
|
||||||
fields = ('name', 'api_url')
|
fields = ('name', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class SwitchBaySerializer(NamespacedHMSerializer):
|
class SwitchBaySerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.SwitchBay` objects
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.SwitchBay
|
model = topologie.SwitchBay
|
||||||
fields = ('name', 'building', 'info', 'api_url')
|
fields = ('name', 'building', 'info', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class BuildingSerializer(NamespacedHMSerializer):
|
class BuildingSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.Building` objects
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.Building
|
model = topologie.Building
|
||||||
fields = ('name', 'api_url')
|
fields = ('name', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class SwitchPortSerializer(NamespacedHMSerializer):
|
class SwitchPortSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.Port` objects
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.Port
|
model = topologie.Port
|
||||||
fields = ('switch', 'port', 'room', 'machine_interface', 'related',
|
fields = ('switch', 'port', 'room', 'machine_interface', 'related',
|
||||||
|
@ -360,15 +446,19 @@ class SwitchPortSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class RoomSerializer(NamespacedHMSerializer):
|
class RoomSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `topologie.models.Room` objects
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = topologie.Room
|
model = topologie.Room
|
||||||
fields = ('name', 'details', 'api_url')
|
fields = ('name', 'details', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
# USERS APP
|
# USERS
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(NamespacedHMSerializer):
|
class UserSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.User` objects.
|
||||||
|
"""
|
||||||
access = serializers.BooleanField(source='has_access')
|
access = serializers.BooleanField(source='has_access')
|
||||||
uid = serializers.IntegerField(source='uid_number')
|
uid = serializers.IntegerField(source='uid_number')
|
||||||
|
|
||||||
|
@ -383,6 +473,8 @@ class UserSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ClubSerializer(NamespacedHMSerializer):
|
class ClubSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.Club` objects.
|
||||||
|
"""
|
||||||
name = serializers.CharField(source='surname')
|
name = serializers.CharField(source='surname')
|
||||||
access = serializers.BooleanField(source='has_access')
|
access = serializers.BooleanField(source='has_access')
|
||||||
uid = serializers.IntegerField(source='uid_number')
|
uid = serializers.IntegerField(source='uid_number')
|
||||||
|
@ -399,6 +491,8 @@ class ClubSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AdherentSerializer(NamespacedHMSerializer):
|
class AdherentSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.Adherent` objects.
|
||||||
|
"""
|
||||||
access = serializers.BooleanField(source='has_access')
|
access = serializers.BooleanField(source='has_access')
|
||||||
uid = serializers.IntegerField(source='uid_number')
|
uid = serializers.IntegerField(source='uid_number')
|
||||||
|
|
||||||
|
@ -413,24 +507,32 @@ class AdherentSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ServiceUserSerializer(NamespacedHMSerializer):
|
class ServiceUserSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.ServiceUser` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = users.ServiceUser
|
model = users.ServiceUser
|
||||||
fields = ('pseudo', 'access_group', 'comment', 'api_url')
|
fields = ('pseudo', 'access_group', 'comment', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class SchoolSerializer(NamespacedHMSerializer):
|
class SchoolSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.School` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = users.School
|
model = users.School
|
||||||
fields = ('name', 'api_url')
|
fields = ('name', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class ListRightSerializer(NamespacedHMSerializer):
|
class ListRightSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.ListRight` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = users.ListRight
|
model = users.ListRight
|
||||||
fields = ('unix_name', 'gid', 'critical', 'details', 'api_url')
|
fields = ('unix_name', 'gid', 'critical', 'details', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class ShellSerializer(NamespacedHMSerializer):
|
class ShellSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.ListShell` objects.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = users.ListShell
|
model = users.ListShell
|
||||||
fields = ('shell', 'api_url')
|
fields = ('shell', 'api_url')
|
||||||
|
@ -440,6 +542,8 @@ class ShellSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class BanSerializer(NamespacedHMSerializer):
|
class BanSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.Ban` objects.
|
||||||
|
"""
|
||||||
active = serializers.BooleanField(source='is_active')
|
active = serializers.BooleanField(source='is_active')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -449,6 +553,8 @@ class BanSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class WhitelistSerializer(NamespacedHMSerializer):
|
class WhitelistSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `users.models.Whitelist` objects.
|
||||||
|
"""
|
||||||
active = serializers.BooleanField(source='is_active')
|
active = serializers.BooleanField(source='is_active')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -456,10 +562,12 @@ class WhitelistSerializer(NamespacedHMSerializer):
|
||||||
fields = ('user', 'raison', 'date_start', 'date_end', 'active', 'api_url')
|
fields = ('user', 'raison', 'date_start', 'date_end', 'active', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
# Services
|
# SERVICE REGEN
|
||||||
|
|
||||||
|
|
||||||
class ServiceRegenSerializer(NamespacedHMSerializer):
|
class ServiceRegenSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize the data about the services to regen.
|
||||||
|
"""
|
||||||
hostname = serializers.CharField(source='server.domain.name', read_only=True)
|
hostname = serializers.CharField(source='server.domain.name', read_only=True)
|
||||||
service_name = serializers.CharField(source='service.service_type', read_only=True)
|
service_name = serializers.CharField(source='service.service_type', read_only=True)
|
||||||
need_regen = serializers.BooleanField()
|
need_regen = serializers.BooleanField()
|
||||||
|
@ -476,6 +584,9 @@ class ServiceRegenSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class HostMacIpSerializer(serializers.ModelSerializer):
|
class HostMacIpSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialize the data about the hostname-ipv4-mac address association
|
||||||
|
to build the DHCP lease files.
|
||||||
|
"""
|
||||||
hostname = serializers.CharField(source='domain.name', read_only=True)
|
hostname = serializers.CharField(source='domain.name', read_only=True)
|
||||||
extension = serializers.CharField(source='domain.extension.name', read_only=True)
|
extension = serializers.CharField(source='domain.extension.name', read_only=True)
|
||||||
mac_address = serializers.CharField(read_only=True)
|
mac_address = serializers.CharField(read_only=True)
|
||||||
|
@ -490,22 +601,34 @@ class HostMacIpSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SOARecordSerializer(SOASerializer):
|
class SOARecordSerializer(SOASerializer):
|
||||||
|
"""Serialize `machines.models.SOA` objects with the data needed to
|
||||||
|
generate a SOA DNS record.
|
||||||
|
"""
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.SOA
|
model = machines.SOA
|
||||||
fields = ('name', 'mail', 'refresh', 'retry', 'expire', 'ttl')
|
fields = ('name', 'mail', 'refresh', 'retry', 'expire', 'ttl')
|
||||||
|
|
||||||
|
|
||||||
class OriginV4RecordSerializer(IpListSerializer):
|
class OriginV4RecordSerializer(IpListSerializer):
|
||||||
|
"""Serialize `machines.models.IpList` objects with the data needed to
|
||||||
|
generate an IPv4 Origin DNS record.
|
||||||
|
"""
|
||||||
class Meta(IpListSerializer.Meta):
|
class Meta(IpListSerializer.Meta):
|
||||||
fields = ('ipv4',)
|
fields = ('ipv4',)
|
||||||
|
|
||||||
|
|
||||||
class OriginV6RecordSerializer(Ipv6ListSerializer):
|
class OriginV6RecordSerializer(Ipv6ListSerializer):
|
||||||
|
"""Serialize `machines.models.Ipv6List` objects with the data needed to
|
||||||
|
generate an IPv6 Origin DNS record.
|
||||||
|
"""
|
||||||
class Meta(Ipv6ListSerializer.Meta):
|
class Meta(Ipv6ListSerializer.Meta):
|
||||||
fields = ('ipv6',)
|
fields = ('ipv6',)
|
||||||
|
|
||||||
|
|
||||||
class NSRecordSerializer(NsSerializer):
|
class NSRecordSerializer(NsSerializer):
|
||||||
|
"""Serialize `machines.models.Ns` objects with the data needed to
|
||||||
|
generate a NS DNS record.
|
||||||
|
"""
|
||||||
target = serializers.CharField(source='ns.name', read_only=True)
|
target = serializers.CharField(source='ns.name', read_only=True)
|
||||||
|
|
||||||
class Meta(NsSerializer.Meta):
|
class Meta(NsSerializer.Meta):
|
||||||
|
@ -513,6 +636,9 @@ class NSRecordSerializer(NsSerializer):
|
||||||
|
|
||||||
|
|
||||||
class MXRecordSerializer(MxSerializer):
|
class MXRecordSerializer(MxSerializer):
|
||||||
|
"""Serialize `machines.models.Mx` objects with the data needed to
|
||||||
|
generate a MX DNS record.
|
||||||
|
"""
|
||||||
target = serializers.CharField(source='name.name', read_only=True)
|
target = serializers.CharField(source='name.name', read_only=True)
|
||||||
|
|
||||||
class Meta(MxSerializer.Meta):
|
class Meta(MxSerializer.Meta):
|
||||||
|
@ -520,11 +646,17 @@ class MXRecordSerializer(MxSerializer):
|
||||||
|
|
||||||
|
|
||||||
class TXTRecordSerializer(TxtSerializer):
|
class TXTRecordSerializer(TxtSerializer):
|
||||||
|
"""Serialize `machines.models.Txt` objects with the data needed to
|
||||||
|
generate a TXT DNS record.
|
||||||
|
"""
|
||||||
class Meta(TxtSerializer.Meta):
|
class Meta(TxtSerializer.Meta):
|
||||||
fields = ('field1', 'field2')
|
fields = ('field1', 'field2')
|
||||||
|
|
||||||
|
|
||||||
class SRVRecordSerializer(SrvSerializer):
|
class SRVRecordSerializer(SrvSerializer):
|
||||||
|
"""Serialize `machines.models.Srv` objects with the data needed to
|
||||||
|
generate a SRV DNS record.
|
||||||
|
"""
|
||||||
target = serializers.CharField(source='target.name', read_only=True)
|
target = serializers.CharField(source='target.name', read_only=True)
|
||||||
|
|
||||||
class Meta(SrvSerializer.Meta):
|
class Meta(SrvSerializer.Meta):
|
||||||
|
@ -532,6 +664,9 @@ class SRVRecordSerializer(SrvSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ARecordSerializer(serializers.ModelSerializer):
|
class ARecordSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialize `machines.models.Interface` objects with the data needed to
|
||||||
|
generate a A DNS record.
|
||||||
|
"""
|
||||||
hostname = serializers.CharField(source='domain.name', read_only=True)
|
hostname = serializers.CharField(source='domain.name', read_only=True)
|
||||||
ipv4 = serializers.CharField(source='ipv4.ipv4', read_only=True)
|
ipv4 = serializers.CharField(source='ipv4.ipv4', read_only=True)
|
||||||
|
|
||||||
|
@ -541,6 +676,9 @@ class ARecordSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AAAARecordSerializer(serializers.ModelSerializer):
|
class AAAARecordSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialize `machines.models.Interface` objects with the data needed to
|
||||||
|
generate a AAAA DNS record.
|
||||||
|
"""
|
||||||
hostname = serializers.CharField(source='domain.name', read_only=True)
|
hostname = serializers.CharField(source='domain.name', read_only=True)
|
||||||
ipv6 = Ipv6ListSerializer(many=True, read_only=True)
|
ipv6 = Ipv6ListSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
|
@ -550,6 +688,9 @@ class AAAARecordSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class CNAMERecordSerializer(serializers.ModelSerializer):
|
class CNAMERecordSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialize `machines.models.Domain` objects with the data needed to
|
||||||
|
generate a CNAME DNS record.
|
||||||
|
"""
|
||||||
alias = serializers.CharField(source='cname.name', read_only=True)
|
alias = serializers.CharField(source='cname.name', read_only=True)
|
||||||
hostname = serializers.CharField(source='name', read_only=True)
|
hostname = serializers.CharField(source='name', read_only=True)
|
||||||
|
|
||||||
|
@ -559,6 +700,8 @@ class CNAMERecordSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class DNSZonesSerializer(serializers.ModelSerializer):
|
class DNSZonesSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialize the data about DNS Zones.
|
||||||
|
"""
|
||||||
soa = SOARecordSerializer()
|
soa = SOARecordSerializer()
|
||||||
ns_records = NSRecordSerializer(many=True, source='ns_set')
|
ns_records = NSRecordSerializer(many=True, source='ns_set')
|
||||||
originv4 = OriginV4RecordSerializer(source='origin')
|
originv4 = OriginV4RecordSerializer(source='origin')
|
||||||
|
@ -577,14 +720,18 @@ class DNSZonesSerializer(serializers.ModelSerializer):
|
||||||
'aaaa_records', 'cname_records')
|
'aaaa_records', 'cname_records')
|
||||||
|
|
||||||
|
|
||||||
# Mailing
|
# MAILING
|
||||||
|
|
||||||
|
|
||||||
class MailingMemberSerializer(UserSerializer):
|
class MailingMemberSerializer(UserSerializer):
|
||||||
|
"""Serialize the data about a mailing member.
|
||||||
|
"""
|
||||||
class Meta(UserSerializer.Meta):
|
class Meta(UserSerializer.Meta):
|
||||||
fields = ('name', 'pseudo', 'email')
|
fields = ('name', 'pseudo', 'email')
|
||||||
|
|
||||||
class MailingSerializer(ClubSerializer):
|
class MailingSerializer(ClubSerializer):
|
||||||
|
"""Serialize the data about a mailing.
|
||||||
|
"""
|
||||||
members = MailingMemberSerializer(many=True)
|
members = MailingMemberSerializer(many=True)
|
||||||
admins = MailingMemberSerializer(source='administrators', many=True)
|
admins = MailingMemberSerializer(source='administrators', many=True)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
# -*- mode: python; coding: utf-8 -*-
|
|
||||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
# 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
|
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
# quelques clics.
|
# quelques clics.
|
||||||
#
|
#
|
||||||
# Copyright © 2017 Gabriel Détraz
|
# Copyright © 2018 Maël Kervella
|
||||||
# Copyright © 2017 Goulven Kermarec
|
|
||||||
# Copyright © 2017 Augustin Lemesle
|
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -21,8 +18,7 @@
|
||||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
"""api.settings
|
"""Settings specific to the API.
|
||||||
Django settings specific to the API.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# RestFramework config for API
|
# RestFramework config for API
|
||||||
|
@ -49,4 +45,6 @@ API_PERMISSION_CODENAME = 'use_api'
|
||||||
API_APPS = (
|
API_APPS = (
|
||||||
'rest_framework.authtoken',
|
'rest_framework.authtoken',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# The expiration time for an authentication token
|
||||||
API_TOKEN_DURATION = 86400 # 24 hours
|
API_TOKEN_DURATION = 86400 # 24 hours
|
||||||
|
|
133
api/tests.py
133
api/tests.py
|
@ -2,9 +2,7 @@
|
||||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
# quelques clics.
|
# quelques clics.
|
||||||
#
|
#
|
||||||
# Copyright © 2017 Gabriel Détraz
|
# Copyright © 2018 Maël Kervella
|
||||||
# Copyright © 2017 Goulven Kermarec
|
|
||||||
# Copyright © 2017 Augustin Lemesle
|
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,8 +17,7 @@
|
||||||
# You should have received a copy of the GNU General Public License along
|
# 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.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
"""api.tests
|
"""Defines the test suite for the API
|
||||||
The tests for the API module.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
@ -34,13 +31,25 @@ import users.models as users
|
||||||
|
|
||||||
|
|
||||||
class APIEndpointsTestCase(APITestCase):
|
class APIEndpointsTestCase(APITestCase):
|
||||||
# URLs that don't require to be authenticated
|
"""Test case to test that all endpoints are reachable with respects to
|
||||||
|
authentication and permission checks.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
no_auth_endpoints: A list of endpoints that should be reachable
|
||||||
|
without authentication.
|
||||||
|
auth_no_perm_endpoints: A list of endpoints that should be reachable
|
||||||
|
when being authenticated but without permissions.
|
||||||
|
auth_perm_endpoints: A list of endpoints that should be reachable
|
||||||
|
when being authenticated and having the correct permissions.
|
||||||
|
stduser: A standard user with no permission used for the tests and
|
||||||
|
initialized at the beggining of this test case.
|
||||||
|
superuser: A superuser (with all permissions) used for the tests and
|
||||||
|
initialized at the beggining of this test case.
|
||||||
|
"""
|
||||||
no_auth_endpoints = [
|
no_auth_endpoints = [
|
||||||
'/api/'
|
'/api/'
|
||||||
]
|
]
|
||||||
# URLs that require to be authenticated and have no special permissions
|
|
||||||
auth_no_perm_endpoints = []
|
auth_no_perm_endpoints = []
|
||||||
# URLs that require to be authenticated and have special permissions
|
|
||||||
auth_perm_endpoints = [
|
auth_perm_endpoints = [
|
||||||
'/api/cotisations/articles/',
|
'/api/cotisations/articles/',
|
||||||
# '/api/cotisations/articles/<pk>/',
|
# '/api/cotisations/articles/<pk>/',
|
||||||
|
@ -160,49 +169,62 @@ class APIEndpointsTestCase(APITestCase):
|
||||||
cls.superuser.delete()
|
cls.superuser.delete()
|
||||||
super().tearDownClass()
|
super().tearDownClass()
|
||||||
|
|
||||||
def check_responses_code(self, urls, expected_code, formats=[None],
|
def check_responses_code(self, urls, expected_code, formats=None,
|
||||||
assert_more=None):
|
assert_more=None):
|
||||||
"""
|
"""Utility function to test if a list of urls answer an expected code.
|
||||||
Utility function to test if a list of urls answer an expected code
|
|
||||||
|
|
||||||
:param urls: (list) The list of urls to test
|
Args:
|
||||||
:param expected_code: (int) The HTTP return code expected
|
urls: The list of urls to test
|
||||||
:param formats: (list) The list of formats to use for the request
|
expected_code: The HTTP return code expected
|
||||||
(Default: [None])
|
formats: The list of formats to use for the request. Default is to
|
||||||
:param assert_more: (func) A function to assert more specific data
|
only test `None` format.
|
||||||
in the same test. It is evaluated with the responsem object, the
|
assert_more: An optional function to assert more specific data in
|
||||||
url and the format used.
|
the same test. The response object, the url and the format
|
||||||
|
used are passed as arguments.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: The response got did not have the expected status
|
||||||
|
code.
|
||||||
|
Any exception raised in the evalutation of `assert_more`.
|
||||||
"""
|
"""
|
||||||
|
if formats is None:
|
||||||
|
formats = [None]
|
||||||
for url in urls:
|
for url in urls:
|
||||||
for format in formats:
|
for format in formats:
|
||||||
with self.subTest(url=url, format=format):
|
with self.subTest(url=url, format=format):
|
||||||
response = self.client.get(url, format=format)
|
response = self.client.get(url, format=format)
|
||||||
assert response.status_code == expected_code
|
assert response.status_code == expected_code
|
||||||
if assert_more:
|
if assert_more is not None:
|
||||||
assert_more(response, url, format)
|
assert_more(response, url, format)
|
||||||
|
|
||||||
def test_no_auth_endpoints_with_no_auth(self):
|
def test_no_auth_endpoints_with_no_auth(self):
|
||||||
"""
|
"""Tests that every endpoint that does not require to be
|
||||||
Test that every endpoint that does not require to be authenticated,
|
authenticated, returns a Ok (200) response when not authenticated.
|
||||||
returns a Ok (200) response when not authenticated.
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have a 200 status code.
|
||||||
"""
|
"""
|
||||||
urls = [endpoint.replace('<pk>', '1')
|
urls = [endpoint.replace('<pk>', '1')
|
||||||
for endpoint in self.no_auth_endpoints]
|
for endpoint in self.no_auth_endpoints]
|
||||||
self.check_responses_code(urls, codes.ok)
|
self.check_responses_code(urls, codes.ok)
|
||||||
|
|
||||||
def test_auth_endpoints_with_no_auth(self):
|
def test_auth_endpoints_with_no_auth(self):
|
||||||
"""
|
"""Tests that every endpoint that does require to be authenticated,
|
||||||
Test that every endpoint that does require to be authenticated,
|
|
||||||
returns a Unauthorized (401) response when not authenticated.
|
returns a Unauthorized (401) response when not authenticated.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have a 401 status code.
|
||||||
"""
|
"""
|
||||||
urls = [endpoint.replace('<pk>', '1') for endpoint in \
|
urls = [endpoint.replace('<pk>', '1') for endpoint in \
|
||||||
self.auth_no_perm_endpoints + self.auth_perm_endpoints]
|
self.auth_no_perm_endpoints + self.auth_perm_endpoints]
|
||||||
self.check_responses_code(urls, codes.unauthorized)
|
self.check_responses_code(urls, codes.unauthorized)
|
||||||
|
|
||||||
def test_no_auth_endpoints_with_auth(self):
|
def test_no_auth_endpoints_with_auth(self):
|
||||||
"""
|
"""Tests that every endpoint that does not require to be
|
||||||
Test that every endpoint that does not require to be authenticated,
|
authenticated, returns a Ok (200) response when authenticated.
|
||||||
returns a Ok (200) response when authenticated.
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have a 200 status code.
|
||||||
"""
|
"""
|
||||||
self.client.force_authenticate(user=self.stduser)
|
self.client.force_authenticate(user=self.stduser)
|
||||||
urls = [endpoint.replace('<pk>', '1')
|
urls = [endpoint.replace('<pk>', '1')
|
||||||
|
@ -210,10 +232,12 @@ class APIEndpointsTestCase(APITestCase):
|
||||||
self.check_responses_code(urls, codes.ok)
|
self.check_responses_code(urls, codes.ok)
|
||||||
|
|
||||||
def test_auth_no_perm_endpoints_with_auth_and_no_perm(self):
|
def test_auth_no_perm_endpoints_with_auth_and_no_perm(self):
|
||||||
"""
|
"""Tests that every endpoint that does require to be authenticated and
|
||||||
Test that every endpoint that does require to be authenticated and
|
no special permissions, returns a Ok (200) response when authenticated
|
||||||
no special permissions, returns a Ok (200) response when
|
but without permissions.
|
||||||
authenticated but without permissions.
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have a 200 status code.
|
||||||
"""
|
"""
|
||||||
self.client.force_authenticate(user=self.stduser)
|
self.client.force_authenticate(user=self.stduser)
|
||||||
urls = [endpoint.replace('<pk>', '1')
|
urls = [endpoint.replace('<pk>', '1')
|
||||||
|
@ -221,10 +245,12 @@ class APIEndpointsTestCase(APITestCase):
|
||||||
self.check_responses_code(urls, codes.ok)
|
self.check_responses_code(urls, codes.ok)
|
||||||
|
|
||||||
def test_auth_perm_endpoints_with_auth_and_no_perm(self):
|
def test_auth_perm_endpoints_with_auth_and_no_perm(self):
|
||||||
"""
|
"""Tests that every endpoint that does require to be authenticated and
|
||||||
Test that every endpoint that does require to be authenticated and
|
|
||||||
special permissions, returns a Forbidden (403) response when
|
special permissions, returns a Forbidden (403) response when
|
||||||
authenticated but without permissions.
|
authenticated but without permissions.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have a 403 status code.
|
||||||
"""
|
"""
|
||||||
self.client.force_authenticate(user=self.stduser)
|
self.client.force_authenticate(user=self.stduser)
|
||||||
urls = [endpoint.replace('<pk>', '1')
|
urls = [endpoint.replace('<pk>', '1')
|
||||||
|
@ -232,9 +258,11 @@ class APIEndpointsTestCase(APITestCase):
|
||||||
self.check_responses_code(urls, codes.forbidden)
|
self.check_responses_code(urls, codes.forbidden)
|
||||||
|
|
||||||
def test_auth_endpoints_with_auth_and_perm(self):
|
def test_auth_endpoints_with_auth_and_perm(self):
|
||||||
"""
|
"""Tests that every endpoint that does require to be authenticated,
|
||||||
Test that every endpoint that does require to be authenticated,
|
returns a Ok (200) response when authenticated with all permissions.
|
||||||
returns a Ok (200) response when authenticated with all permissions
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have a 200 status code.
|
||||||
"""
|
"""
|
||||||
self.client.force_authenticate(user=self.superuser)
|
self.client.force_authenticate(user=self.superuser)
|
||||||
urls = [endpoint.replace('<pk>', '1') for endpoint \
|
urls = [endpoint.replace('<pk>', '1') for endpoint \
|
||||||
|
@ -242,10 +270,12 @@ class APIEndpointsTestCase(APITestCase):
|
||||||
self.check_responses_code(urls, codes.ok)
|
self.check_responses_code(urls, codes.ok)
|
||||||
|
|
||||||
def test_endpoints_not_found(self):
|
def test_endpoints_not_found(self):
|
||||||
"""
|
"""Tests that every endpoint that uses a primary key parameter,
|
||||||
Test that every endpoint that uses a primary key parameter,
|
|
||||||
returns a Not Found (404) response when queried with non-existing
|
returns a Not Found (404) response when queried with non-existing
|
||||||
primary key
|
primary key.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have a 404 status code.
|
||||||
"""
|
"""
|
||||||
self.client.force_authenticate(user=self.superuser)
|
self.client.force_authenticate(user=self.superuser)
|
||||||
# Select only the URLs with '<pk>' and replace it with '42'
|
# Select only the URLs with '<pk>' and replace it with '42'
|
||||||
|
@ -255,9 +285,12 @@ class APIEndpointsTestCase(APITestCase):
|
||||||
self.check_responses_code(urls, codes.not_found)
|
self.check_responses_code(urls, codes.not_found)
|
||||||
|
|
||||||
def test_formats(self):
|
def test_formats(self):
|
||||||
"""
|
"""Tests that every endpoint returns a Ok (200) response when using
|
||||||
Test that every endpoint returns a Ok (200) response when using
|
different formats. Also checks that 'json' format returns a valid
|
||||||
different formats. Also checks that 'json' format returns a valid json
|
JSON object.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have a 200 status code.
|
||||||
"""
|
"""
|
||||||
self.client.force_authenticate(user=self.superuser)
|
self.client.force_authenticate(user=self.superuser)
|
||||||
|
|
||||||
|
@ -275,6 +308,14 @@ class APIEndpointsTestCase(APITestCase):
|
||||||
assert_more=assert_more)
|
assert_more=assert_more)
|
||||||
|
|
||||||
class APIPaginationTestCase(APITestCase):
|
class APIPaginationTestCase(APITestCase):
|
||||||
|
"""Test case to check that the pagination is used on all endpoints that
|
||||||
|
should use it.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
endpoints: A list of endpoints that should use the pagination.
|
||||||
|
superuser: A superuser used in the tests to access the endpoints.
|
||||||
|
"""
|
||||||
|
|
||||||
endpoints = [
|
endpoints = [
|
||||||
'/api/cotisations/articles/',
|
'/api/cotisations/articles/',
|
||||||
'/api/cotisations/banques/',
|
'/api/cotisations/banques/',
|
||||||
|
@ -338,8 +379,12 @@ class APIPaginationTestCase(APITestCase):
|
||||||
super().tearDownClass()
|
super().tearDownClass()
|
||||||
|
|
||||||
def test_pagination(self):
|
def test_pagination(self):
|
||||||
"""
|
"""Tests that every endpoint is using the pagination correctly.
|
||||||
Test that every endpoint is using the pagination correctly
|
|
||||||
|
Raises:
|
||||||
|
AssertionError: An endpoint did not have one the following keyword
|
||||||
|
in the JSOn response: 'count', 'next', 'previous', 'results'
|
||||||
|
or more that 100 results were returned.
|
||||||
"""
|
"""
|
||||||
self.client.force_authenticate(self.superuser)
|
self.client.force_authenticate(self.superuser)
|
||||||
for url in self.endpoints:
|
for url in self.endpoints:
|
||||||
|
|
29
api/urls.py
29
api/urls.py
|
@ -2,7 +2,7 @@
|
||||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
# quelques clics.
|
# quelques clics.
|
||||||
#
|
#
|
||||||
# Copyright © 2018 Mael Kervella
|
# Copyright © 2018 Maël Kervella
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,27 +17,30 @@
|
||||||
# You should have received a copy of the GNU General Public License along
|
# 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.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
"""api.urls
|
|
||||||
|
|
||||||
Urls de l'api, pointant vers les fonctions de views
|
"""Defines the URLs of the API
|
||||||
|
|
||||||
|
A custom router is used to register all the routes. That allows to register
|
||||||
|
all the URL patterns from the viewsets as a standard router but, the views
|
||||||
|
can also be register. That way a complete API root page presenting all URLs
|
||||||
|
can be generated automatically.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
|
|
||||||
from .routers import AllViewsRouter
|
|
||||||
from . import views
|
from . import views
|
||||||
|
from .routers import AllViewsRouter
|
||||||
|
|
||||||
|
|
||||||
router = AllViewsRouter()
|
router = AllViewsRouter()
|
||||||
# COTISATIONS APP
|
# COTISATIONS
|
||||||
router.register_viewset(r'cotisations/factures', views.FactureViewSet)
|
router.register_viewset(r'cotisations/factures', views.FactureViewSet)
|
||||||
router.register_viewset(r'cotisations/ventes', views.VenteViewSet)
|
router.register_viewset(r'cotisations/ventes', views.VenteViewSet)
|
||||||
router.register_viewset(r'cotisations/articles', views.ArticleViewSet)
|
router.register_viewset(r'cotisations/articles', views.ArticleViewSet)
|
||||||
router.register_viewset(r'cotisations/banques', views.BanqueViewSet)
|
router.register_viewset(r'cotisations/banques', views.BanqueViewSet)
|
||||||
router.register_viewset(r'cotisations/paiements', views.PaiementViewSet)
|
router.register_viewset(r'cotisations/paiements', views.PaiementViewSet)
|
||||||
router.register_viewset(r'cotisations/cotisations', views.CotisationViewSet)
|
router.register_viewset(r'cotisations/cotisations', views.CotisationViewSet)
|
||||||
# MACHINES APP
|
# MACHINES
|
||||||
router.register_viewset(r'machines/machines', views.MachineViewSet)
|
router.register_viewset(r'machines/machines', views.MachineViewSet)
|
||||||
router.register_viewset(r'machines/machinetypes', views.MachineTypeViewSet)
|
router.register_viewset(r'machines/machinetypes', views.MachineTypeViewSet)
|
||||||
router.register_viewset(r'machines/iptypes', views.IpTypeViewSet)
|
router.register_viewset(r'machines/iptypes', views.IpTypeViewSet)
|
||||||
|
@ -57,7 +60,7 @@ router.register_viewset(r'machines/services', views.ServiceViewSet)
|
||||||
router.register_viewset(r'machines/servicelinks', views.ServiceLinkViewSet, base_name='servicelink')
|
router.register_viewset(r'machines/servicelinks', views.ServiceLinkViewSet, base_name='servicelink')
|
||||||
router.register_viewset(r'machines/ouvertureportlists', views.OuverturePortListViewSet)
|
router.register_viewset(r'machines/ouvertureportlists', views.OuverturePortListViewSet)
|
||||||
router.register_viewset(r'machines/ouvertureports', views.OuverturePortViewSet)
|
router.register_viewset(r'machines/ouvertureports', views.OuverturePortViewSet)
|
||||||
# PREFERENCES APP
|
# PREFERENCES
|
||||||
router.register_viewset(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/optionaluser', views.OptionalUserView),
|
||||||
router.register_view(r'preferences/optionalmachine', views.OptionalMachineView),
|
router.register_view(r'preferences/optionalmachine', views.OptionalMachineView),
|
||||||
|
@ -66,7 +69,7 @@ router.register_view(r'preferences/generaloption', views.GeneralOptionView),
|
||||||
router.register_view(r'preferences/assooption', views.AssoOptionView),
|
router.register_view(r'preferences/assooption', views.AssoOptionView),
|
||||||
router.register_view(r'preferences/homeoption', views.HomeOptionView),
|
router.register_view(r'preferences/homeoption', views.HomeOptionView),
|
||||||
router.register_view(r'preferences/mailmessageoption', views.MailMessageOptionView),
|
router.register_view(r'preferences/mailmessageoption', views.MailMessageOptionView),
|
||||||
# TOPOLOGIE APP
|
# TOPOLOGIE
|
||||||
router.register_viewset(r'topologie/stack', views.StackViewSet)
|
router.register_viewset(r'topologie/stack', views.StackViewSet)
|
||||||
router.register_viewset(r'topologie/acesspoint', views.AccessPointViewSet)
|
router.register_viewset(r'topologie/acesspoint', views.AccessPointViewSet)
|
||||||
router.register_viewset(r'topologie/switch', views.SwitchViewSet)
|
router.register_viewset(r'topologie/switch', views.SwitchViewSet)
|
||||||
|
@ -76,7 +79,7 @@ router.register_viewset(r'topologie/switchbay', views.SwitchBayViewSet)
|
||||||
router.register_viewset(r'topologie/building', views.BuildingViewSet)
|
router.register_viewset(r'topologie/building', views.BuildingViewSet)
|
||||||
router.register_viewset(r'topologie/switchport', views.SwitchPortViewSet, base_name='switchport')
|
router.register_viewset(r'topologie/switchport', views.SwitchPortViewSet, base_name='switchport')
|
||||||
router.register_viewset(r'topologie/room', views.RoomViewSet)
|
router.register_viewset(r'topologie/room', views.RoomViewSet)
|
||||||
# USERS APP
|
# USERS
|
||||||
router.register_viewset(r'users/users', views.UserViewSet)
|
router.register_viewset(r'users/users', views.UserViewSet)
|
||||||
router.register_viewset(r'users/clubs', views.ClubViewSet)
|
router.register_viewset(r'users/clubs', views.ClubViewSet)
|
||||||
router.register_viewset(r'users/adherents', views.AdherentViewSet)
|
router.register_viewset(r'users/adherents', views.AdherentViewSet)
|
||||||
|
@ -86,7 +89,7 @@ router.register_viewset(r'users/listrights', views.ListRightViewSet)
|
||||||
router.register_viewset(r'users/shells', views.ShellViewSet, base_name='shell')
|
router.register_viewset(r'users/shells', views.ShellViewSet, base_name='shell')
|
||||||
router.register_viewset(r'users/bans', views.BanViewSet)
|
router.register_viewset(r'users/bans', views.BanViewSet)
|
||||||
router.register_viewset(r'users/whitelists', views.WhitelistViewSet)
|
router.register_viewset(r'users/whitelists', views.WhitelistViewSet)
|
||||||
# SERVICES REGEN
|
# SERVICE REGEN
|
||||||
router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen')
|
router.register_viewset(r'services/regen', views.ServiceRegenViewSet, base_name='serviceregen')
|
||||||
# DHCP
|
# DHCP
|
||||||
router.register_view(r'dhcp/hostmacip', views.HostMacIpView),
|
router.register_view(r'dhcp/hostmacip', views.HostMacIpView),
|
||||||
|
@ -95,7 +98,7 @@ router.register_view(r'dns/zones', views.DNSZonesView),
|
||||||
# MAILING
|
# MAILING
|
||||||
router.register_view(r'mailing/standard', views.StandardMailingView),
|
router.register_view(r'mailing/standard', views.StandardMailingView),
|
||||||
router.register_view(r'mailing/club', views.ClubMailingView),
|
router.register_view(r'mailing/club', views.ClubMailingView),
|
||||||
# TOKEN-AUTH
|
# TOKEN AUTHENTICATION
|
||||||
router.register_view(r'token-auth', views.ObtainExpiringAuthToken)
|
router.register_view(r'token-auth', views.ObtainExpiringAuthToken)
|
||||||
|
|
||||||
|
|
||||||
|
|
156
api/views.py
156
api/views.py
|
@ -18,16 +18,16 @@
|
||||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
"""api.views
|
"""Defines the views of the API
|
||||||
|
|
||||||
The views for the API app. They should all return JSON data and not fallback on
|
All views inherits the `rest_framework.views.APIview` to respect the
|
||||||
HTML pages such as the login and index pages for a better integration.
|
REST API requirements such as dealing with HTTP status code, format of
|
||||||
|
the response (JSON or other), the CSRF exempting, ...
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from rest_framework.authtoken.views import ObtainAuthToken
|
from rest_framework.authtoken.views import ObtainAuthToken
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
@ -38,7 +38,6 @@ import machines.models as machines
|
||||||
import preferences.models as preferences
|
import preferences.models as preferences
|
||||||
import topologie.models as topologie
|
import topologie.models as topologie
|
||||||
import users.models as users
|
import users.models as users
|
||||||
|
|
||||||
from re2o.utils import all_active_interfaces, all_has_access
|
from re2o.utils import all_active_interfaces, all_has_access
|
||||||
|
|
||||||
from . import serializers
|
from . import serializers
|
||||||
|
@ -46,142 +45,195 @@ from .pagination import PageSizedPagination
|
||||||
from .permissions import ACLPermission
|
from .permissions import ACLPermission
|
||||||
|
|
||||||
|
|
||||||
# COTISATIONS APP
|
# COTISATIONS
|
||||||
|
|
||||||
|
|
||||||
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `cotisations.models.Facture` objects.
|
||||||
|
"""
|
||||||
queryset = cotisations.Facture.objects.all()
|
queryset = cotisations.Facture.objects.all()
|
||||||
serializer_class = serializers.FactureSerializer
|
serializer_class = serializers.FactureSerializer
|
||||||
|
|
||||||
|
|
||||||
class VenteViewSet(viewsets.ReadOnlyModelViewSet):
|
class VenteViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `cotisations.models.Vente` objects.
|
||||||
|
"""
|
||||||
queryset = cotisations.Vente.objects.all()
|
queryset = cotisations.Vente.objects.all()
|
||||||
serializer_class = serializers.VenteSerializer
|
serializer_class = serializers.VenteSerializer
|
||||||
|
|
||||||
|
|
||||||
class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
|
class ArticleViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `cotisations.models.Article` objects.
|
||||||
|
"""
|
||||||
queryset = cotisations.Article.objects.all()
|
queryset = cotisations.Article.objects.all()
|
||||||
serializer_class = serializers.ArticleSerializer
|
serializer_class = serializers.ArticleSerializer
|
||||||
|
|
||||||
|
|
||||||
class BanqueViewSet(viewsets.ReadOnlyModelViewSet):
|
class BanqueViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `cotisations.models.Banque` objects.
|
||||||
|
"""
|
||||||
queryset = cotisations.Banque.objects.all()
|
queryset = cotisations.Banque.objects.all()
|
||||||
serializer_class = serializers.BanqueSerializer
|
serializer_class = serializers.BanqueSerializer
|
||||||
|
|
||||||
|
|
||||||
class PaiementViewSet(viewsets.ReadOnlyModelViewSet):
|
class PaiementViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `cotisations.models.Paiement` objects.
|
||||||
|
"""
|
||||||
queryset = cotisations.Paiement.objects.all()
|
queryset = cotisations.Paiement.objects.all()
|
||||||
serializer_class = serializers.PaiementSerializer
|
serializer_class = serializers.PaiementSerializer
|
||||||
|
|
||||||
|
|
||||||
class CotisationViewSet(viewsets.ReadOnlyModelViewSet):
|
class CotisationViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `cotisations.models.Cotisation` objects.
|
||||||
|
"""
|
||||||
queryset = cotisations.Cotisation.objects.all()
|
queryset = cotisations.Cotisation.objects.all()
|
||||||
serializer_class = serializers.CotisationSerializer
|
serializer_class = serializers.CotisationSerializer
|
||||||
|
|
||||||
|
|
||||||
# MACHINES APP
|
# MACHINES
|
||||||
|
|
||||||
|
|
||||||
class MachineViewSet(viewsets.ReadOnlyModelViewSet):
|
class MachineViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Machine` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Machine.objects.all()
|
queryset = machines.Machine.objects.all()
|
||||||
serializer_class = serializers.MachineSerializer
|
serializer_class = serializers.MachineSerializer
|
||||||
|
|
||||||
|
|
||||||
class MachineTypeViewSet(viewsets.ReadOnlyModelViewSet):
|
class MachineTypeViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.MachineType` objects.
|
||||||
|
"""
|
||||||
queryset = machines.MachineType.objects.all()
|
queryset = machines.MachineType.objects.all()
|
||||||
serializer_class = serializers.MachineTypeSerializer
|
serializer_class = serializers.MachineTypeSerializer
|
||||||
|
|
||||||
|
|
||||||
class IpTypeViewSet(viewsets.ReadOnlyModelViewSet):
|
class IpTypeViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.IpType` objects.
|
||||||
|
"""
|
||||||
queryset = machines.IpType.objects.all()
|
queryset = machines.IpType.objects.all()
|
||||||
serializer_class = serializers.IpTypeSerializer
|
serializer_class = serializers.IpTypeSerializer
|
||||||
|
|
||||||
|
|
||||||
class VlanViewSet(viewsets.ReadOnlyModelViewSet):
|
class VlanViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Vlan` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Vlan.objects.all()
|
queryset = machines.Vlan.objects.all()
|
||||||
serializer_class = serializers.VlanSerializer
|
serializer_class = serializers.VlanSerializer
|
||||||
|
|
||||||
|
|
||||||
class NasViewSet(viewsets.ReadOnlyModelViewSet):
|
class NasViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Nas` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Nas.objects.all()
|
queryset = machines.Nas.objects.all()
|
||||||
serializer_class = serializers.NasSerializer
|
serializer_class = serializers.NasSerializer
|
||||||
|
|
||||||
|
|
||||||
class SOAViewSet(viewsets.ReadOnlyModelViewSet):
|
class SOAViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.SOA` objects.
|
||||||
|
"""
|
||||||
queryset = machines.SOA.objects.all()
|
queryset = machines.SOA.objects.all()
|
||||||
serializer_class = serializers.SOASerializer
|
serializer_class = serializers.SOASerializer
|
||||||
|
|
||||||
|
|
||||||
class ExtensionViewSet(viewsets.ReadOnlyModelViewSet):
|
class ExtensionViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Extension` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Extension.objects.all()
|
queryset = machines.Extension.objects.all()
|
||||||
serializer_class = serializers.ExtensionSerializer
|
serializer_class = serializers.ExtensionSerializer
|
||||||
|
|
||||||
|
|
||||||
class MxViewSet(viewsets.ReadOnlyModelViewSet):
|
class MxViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Mx` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Mx.objects.all()
|
queryset = machines.Mx.objects.all()
|
||||||
serializer_class = serializers.MxSerializer
|
serializer_class = serializers.MxSerializer
|
||||||
|
|
||||||
|
|
||||||
class NsViewSet(viewsets.ReadOnlyModelViewSet):
|
class NsViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Ns` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Ns.objects.all()
|
queryset = machines.Ns.objects.all()
|
||||||
serializer_class = serializers.NsSerializer
|
serializer_class = serializers.NsSerializer
|
||||||
|
|
||||||
|
|
||||||
class TxtViewSet(viewsets.ReadOnlyModelViewSet):
|
class TxtViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Txt` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Txt.objects.all()
|
queryset = machines.Txt.objects.all()
|
||||||
serializer_class = serializers.TxtSerializer
|
serializer_class = serializers.TxtSerializer
|
||||||
|
|
||||||
|
|
||||||
class SrvViewSet(viewsets.ReadOnlyModelViewSet):
|
class SrvViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Srv` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Srv.objects.all()
|
queryset = machines.Srv.objects.all()
|
||||||
serializer_class = serializers.SrvSerializer
|
serializer_class = serializers.SrvSerializer
|
||||||
|
|
||||||
|
|
||||||
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
|
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Interface` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Interface.objects.all()
|
queryset = machines.Interface.objects.all()
|
||||||
serializer_class = serializers.InterfaceSerializer
|
serializer_class = serializers.InterfaceSerializer
|
||||||
|
|
||||||
|
|
||||||
class Ipv6ListViewSet(viewsets.ReadOnlyModelViewSet):
|
class Ipv6ListViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Ipv6List` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Ipv6List.objects.all()
|
queryset = machines.Ipv6List.objects.all()
|
||||||
serializer_class = serializers.Ipv6ListSerializer
|
serializer_class = serializers.Ipv6ListSerializer
|
||||||
|
|
||||||
|
|
||||||
class DomainViewSet(viewsets.ReadOnlyModelViewSet):
|
class DomainViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Domain` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Domain.objects.all()
|
queryset = machines.Domain.objects.all()
|
||||||
serializer_class = serializers.DomainSerializer
|
serializer_class = serializers.DomainSerializer
|
||||||
|
|
||||||
|
|
||||||
class IpListViewSet(viewsets.ReadOnlyModelViewSet):
|
class IpListViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.IpList` objects.
|
||||||
|
"""
|
||||||
queryset = machines.IpList.objects.all()
|
queryset = machines.IpList.objects.all()
|
||||||
serializer_class = serializers.IpListSerializer
|
serializer_class = serializers.IpListSerializer
|
||||||
|
|
||||||
|
|
||||||
class ServiceViewSet(viewsets.ReadOnlyModelViewSet):
|
class ServiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Service` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Service.objects.all()
|
queryset = machines.Service.objects.all()
|
||||||
serializer_class = serializers.ServiceSerializer
|
serializer_class = serializers.ServiceSerializer
|
||||||
|
|
||||||
|
|
||||||
class ServiceLinkViewSet(viewsets.ReadOnlyModelViewSet):
|
class ServiceLinkViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.Service_link` objects.
|
||||||
|
"""
|
||||||
queryset = machines.Service_link.objects.all()
|
queryset = machines.Service_link.objects.all()
|
||||||
serializer_class = serializers.ServiceLinkSerializer
|
serializer_class = serializers.ServiceLinkSerializer
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortListViewSet(viewsets.ReadOnlyModelViewSet):
|
class OuverturePortListViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.OuverturePortList`
|
||||||
|
objects.
|
||||||
|
"""
|
||||||
queryset = machines.OuverturePortList.objects.all()
|
queryset = machines.OuverturePortList.objects.all()
|
||||||
serializer_class = serializers.OuverturePortListSerializer
|
serializer_class = serializers.OuverturePortListSerializer
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
|
class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.OuverturePort` objects.
|
||||||
|
"""
|
||||||
queryset = machines.OuverturePort.objects.all()
|
queryset = machines.OuverturePort.objects.all()
|
||||||
serializer_class = serializers.OuverturePortSerializer
|
serializer_class = serializers.OuverturePortSerializer
|
||||||
|
|
||||||
|
|
||||||
# PREFERENCES APP
|
# PREFERENCES
|
||||||
# Those views differ a bit because there is only one object
|
# Those views differ a bit because there is only one object
|
||||||
# to display, so we don't bother with the listing part
|
# to display, so we don't bother with the listing part
|
||||||
|
|
||||||
class OptionalUserView(generics.RetrieveAPIView):
|
class OptionalUserView(generics.RetrieveAPIView):
|
||||||
|
"""Exposes details of `preferences.models.` settings.
|
||||||
|
"""
|
||||||
permission_classes = (ACLPermission, )
|
permission_classes = (ACLPermission, )
|
||||||
perms_map = {'GET' : [preferences.OptionalUser.can_view_all]}
|
perms_map = {'GET' : [preferences.OptionalUser.can_view_all]}
|
||||||
serializer_class = serializers.OptionalUserSerializer
|
serializer_class = serializers.OptionalUserSerializer
|
||||||
|
@ -191,6 +243,8 @@ class OptionalUserView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class OptionalMachineView(generics.RetrieveAPIView):
|
class OptionalMachineView(generics.RetrieveAPIView):
|
||||||
|
"""Exposes details of `preferences.models.OptionalMachine` settings.
|
||||||
|
"""
|
||||||
permission_classes = (ACLPermission, )
|
permission_classes = (ACLPermission, )
|
||||||
perms_map = {'GET' : [preferences.OptionalMachine.can_view_all]}
|
perms_map = {'GET' : [preferences.OptionalMachine.can_view_all]}
|
||||||
serializer_class = serializers.OptionalMachineSerializer
|
serializer_class = serializers.OptionalMachineSerializer
|
||||||
|
@ -200,6 +254,8 @@ class OptionalMachineView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class OptionalTopologieView(generics.RetrieveAPIView):
|
class OptionalTopologieView(generics.RetrieveAPIView):
|
||||||
|
"""Exposes details of `preferences.models.OptionalTopologie` settings.
|
||||||
|
"""
|
||||||
permission_classes = (ACLPermission, )
|
permission_classes = (ACLPermission, )
|
||||||
perms_map = {'GET' : [preferences.OptionalTopologie.can_view_all]}
|
perms_map = {'GET' : [preferences.OptionalTopologie.can_view_all]}
|
||||||
serializer_class = serializers.OptionalTopologieSerializer
|
serializer_class = serializers.OptionalTopologieSerializer
|
||||||
|
@ -209,6 +265,8 @@ class OptionalTopologieView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class GeneralOptionView(generics.RetrieveAPIView):
|
class GeneralOptionView(generics.RetrieveAPIView):
|
||||||
|
"""Exposes details of `preferences.models.GeneralOption` settings.
|
||||||
|
"""
|
||||||
permission_classes = (ACLPermission, )
|
permission_classes = (ACLPermission, )
|
||||||
perms_map = {'GET' : [preferences.GeneralOption.can_view_all]}
|
perms_map = {'GET' : [preferences.GeneralOption.can_view_all]}
|
||||||
serializer_class = serializers.GeneralOptionSerializer
|
serializer_class = serializers.GeneralOptionSerializer
|
||||||
|
@ -218,11 +276,15 @@ class GeneralOptionView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class ServiceViewSet(viewsets.ReadOnlyModelViewSet):
|
class ServiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `preferences.models.Service` objects.
|
||||||
|
"""
|
||||||
queryset = preferences.Service.objects.all()
|
queryset = preferences.Service.objects.all()
|
||||||
serializer_class = serializers.ServiceSerializer
|
serializer_class = serializers.ServiceSerializer
|
||||||
|
|
||||||
|
|
||||||
class AssoOptionView(generics.RetrieveAPIView):
|
class AssoOptionView(generics.RetrieveAPIView):
|
||||||
|
"""Exposes details of `preferences.models.AssoOption` settings.
|
||||||
|
"""
|
||||||
permission_classes = (ACLPermission, )
|
permission_classes = (ACLPermission, )
|
||||||
perms_map = {'GET' : [preferences.AssoOption.can_view_all]}
|
perms_map = {'GET' : [preferences.AssoOption.can_view_all]}
|
||||||
serializer_class = serializers.AssoOptionSerializer
|
serializer_class = serializers.AssoOptionSerializer
|
||||||
|
@ -232,6 +294,8 @@ class AssoOptionView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class HomeOptionView(generics.RetrieveAPIView):
|
class HomeOptionView(generics.RetrieveAPIView):
|
||||||
|
"""Exposes details of `preferences.models.HomeOption` settings.
|
||||||
|
"""
|
||||||
permission_classes = (ACLPermission, )
|
permission_classes = (ACLPermission, )
|
||||||
perms_map = {'GET' : [preferences.HomeOption.can_view_all]}
|
perms_map = {'GET' : [preferences.HomeOption.can_view_all]}
|
||||||
serializer_class = serializers.HomeOptionSerializer
|
serializer_class = serializers.HomeOptionSerializer
|
||||||
|
@ -241,6 +305,8 @@ class HomeOptionView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class MailMessageOptionView(generics.RetrieveAPIView):
|
class MailMessageOptionView(generics.RetrieveAPIView):
|
||||||
|
"""Exposes details of `preferences.models.MailMessageOption` settings.
|
||||||
|
"""
|
||||||
permission_classes = (ACLPermission, )
|
permission_classes = (ACLPermission, )
|
||||||
perms_map = {'GET' : [preferences.MailMessageOption.can_view_all]}
|
perms_map = {'GET' : [preferences.MailMessageOption.can_view_all]}
|
||||||
serializer_class = serializers.MailMessageOptionSerializer
|
serializer_class = serializers.MailMessageOptionSerializer
|
||||||
|
@ -249,106 +315,145 @@ class MailMessageOptionView(generics.RetrieveAPIView):
|
||||||
return preferences.MailMessageOption.objects.first()
|
return preferences.MailMessageOption.objects.first()
|
||||||
|
|
||||||
|
|
||||||
# TOPOLOGIE APP
|
# TOPOLOGIE
|
||||||
|
|
||||||
|
|
||||||
class StackViewSet(viewsets.ReadOnlyModelViewSet):
|
class StackViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.Stack` objects.
|
||||||
|
"""
|
||||||
queryset = topologie.Stack.objects.all()
|
queryset = topologie.Stack.objects.all()
|
||||||
serializer_class = serializers.StackSerializer
|
serializer_class = serializers.StackSerializer
|
||||||
|
|
||||||
|
|
||||||
class AccessPointViewSet(viewsets.ReadOnlyModelViewSet):
|
class AccessPointViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.AccessPoint` objects.
|
||||||
|
"""
|
||||||
queryset = topologie.AccessPoint.objects.all()
|
queryset = topologie.AccessPoint.objects.all()
|
||||||
serializer_class = serializers.AccessPointSerializer
|
serializer_class = serializers.AccessPointSerializer
|
||||||
|
|
||||||
|
|
||||||
class SwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
class SwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.Switch` objects.
|
||||||
|
"""
|
||||||
queryset = topologie.Switch.objects.all()
|
queryset = topologie.Switch.objects.all()
|
||||||
serializer_class = serializers.SwitchSerializer
|
serializer_class = serializers.SwitchSerializer
|
||||||
|
|
||||||
|
|
||||||
class ModelSwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
class ModelSwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.ModelSwitch` objects.
|
||||||
|
"""
|
||||||
queryset = topologie.ModelSwitch.objects.all()
|
queryset = topologie.ModelSwitch.objects.all()
|
||||||
serializer_class = serializers.ModelSwitchSerializer
|
serializer_class = serializers.ModelSwitchSerializer
|
||||||
|
|
||||||
|
|
||||||
class ConstructorSwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
class ConstructorSwitchViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.ConstructorSwitch`
|
||||||
|
objects.
|
||||||
|
"""
|
||||||
queryset = topologie.ConstructorSwitch.objects.all()
|
queryset = topologie.ConstructorSwitch.objects.all()
|
||||||
serializer_class = serializers.ConstructorSwitchSerializer
|
serializer_class = serializers.ConstructorSwitchSerializer
|
||||||
|
|
||||||
|
|
||||||
class SwitchBayViewSet(viewsets.ReadOnlyModelViewSet):
|
class SwitchBayViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.SwitchBay` objects.
|
||||||
|
"""
|
||||||
queryset = topologie.SwitchBay.objects.all()
|
queryset = topologie.SwitchBay.objects.all()
|
||||||
serializer_class = serializers.SwitchBaySerializer
|
serializer_class = serializers.SwitchBaySerializer
|
||||||
|
|
||||||
|
|
||||||
class BuildingViewSet(viewsets.ReadOnlyModelViewSet):
|
class BuildingViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.Building` objects.
|
||||||
|
"""
|
||||||
queryset = topologie.Building.objects.all()
|
queryset = topologie.Building.objects.all()
|
||||||
serializer_class = serializers.BuildingSerializer
|
serializer_class = serializers.BuildingSerializer
|
||||||
|
|
||||||
|
|
||||||
class SwitchPortViewSet(viewsets.ReadOnlyModelViewSet):
|
class SwitchPortViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.Port` objects.
|
||||||
|
"""
|
||||||
queryset = topologie.Port.objects.all()
|
queryset = topologie.Port.objects.all()
|
||||||
serializer_class = serializers.SwitchPortSerializer
|
serializer_class = serializers.SwitchPortSerializer
|
||||||
|
|
||||||
|
|
||||||
class RoomViewSet(viewsets.ReadOnlyModelViewSet):
|
class RoomViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `topologie.models.Room` objects.
|
||||||
|
"""
|
||||||
queryset = topologie.Room.objects.all()
|
queryset = topologie.Room.objects.all()
|
||||||
serializer_class = serializers.RoomSerializer
|
serializer_class = serializers.RoomSerializer
|
||||||
|
|
||||||
|
|
||||||
# USER APP
|
# USER
|
||||||
|
|
||||||
|
|
||||||
class UserViewSet(viewsets.ReadOnlyModelViewSet):
|
class UserViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.Users` objects.
|
||||||
|
"""
|
||||||
queryset = users.User.objects.all()
|
queryset = users.User.objects.all()
|
||||||
serializer_class = serializers.UserSerializer
|
serializer_class = serializers.UserSerializer
|
||||||
|
|
||||||
|
|
||||||
class ClubViewSet(viewsets.ReadOnlyModelViewSet):
|
class ClubViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.Club` objects.
|
||||||
|
"""
|
||||||
queryset = users.Club.objects.all()
|
queryset = users.Club.objects.all()
|
||||||
serializer_class = serializers.ClubSerializer
|
serializer_class = serializers.ClubSerializer
|
||||||
|
|
||||||
|
|
||||||
class AdherentViewSet(viewsets.ReadOnlyModelViewSet):
|
class AdherentViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.Adherent` objects.
|
||||||
|
"""
|
||||||
queryset = users.Adherent.objects.all()
|
queryset = users.Adherent.objects.all()
|
||||||
serializer_class = serializers.AdherentSerializer
|
serializer_class = serializers.AdherentSerializer
|
||||||
|
|
||||||
|
|
||||||
class ServiceUserViewSet(viewsets.ReadOnlyModelViewSet):
|
class ServiceUserViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.ServiceUser` objects.
|
||||||
|
"""
|
||||||
queryset = users.ServiceUser.objects.all()
|
queryset = users.ServiceUser.objects.all()
|
||||||
serializer_class = serializers.ServiceUserSerializer
|
serializer_class = serializers.ServiceUserSerializer
|
||||||
|
|
||||||
|
|
||||||
class SchoolViewSet(viewsets.ReadOnlyModelViewSet):
|
class SchoolViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.School` objects.
|
||||||
|
"""
|
||||||
queryset = users.School.objects.all()
|
queryset = users.School.objects.all()
|
||||||
serializer_class = serializers.SchoolSerializer
|
serializer_class = serializers.SchoolSerializer
|
||||||
|
|
||||||
|
|
||||||
class ListRightViewSet(viewsets.ReadOnlyModelViewSet):
|
class ListRightViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.ListRight` objects.
|
||||||
|
"""
|
||||||
queryset = users.ListRight.objects.all()
|
queryset = users.ListRight.objects.all()
|
||||||
serializer_class = serializers.ListRightSerializer
|
serializer_class = serializers.ListRightSerializer
|
||||||
|
|
||||||
|
|
||||||
class ShellViewSet(viewsets.ReadOnlyModelViewSet):
|
class ShellViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.ListShell` objects.
|
||||||
|
"""
|
||||||
queryset = users.ListShell.objects.all()
|
queryset = users.ListShell.objects.all()
|
||||||
serializer_class = serializers.ShellSerializer
|
serializer_class = serializers.ShellSerializer
|
||||||
|
|
||||||
|
|
||||||
class BanViewSet(viewsets.ReadOnlyModelViewSet):
|
class BanViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.Ban` objects.
|
||||||
|
"""
|
||||||
queryset = users.Ban.objects.all()
|
queryset = users.Ban.objects.all()
|
||||||
serializer_class = serializers.BanSerializer
|
serializer_class = serializers.BanSerializer
|
||||||
|
|
||||||
|
|
||||||
class WhitelistViewSet(viewsets.ReadOnlyModelViewSet):
|
class WhitelistViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `users.models.Whitelist` objects.
|
||||||
|
"""
|
||||||
queryset = users.Whitelist.objects.all()
|
queryset = users.Whitelist.objects.all()
|
||||||
serializer_class = serializers.WhitelistSerializer
|
serializer_class = serializers.WhitelistSerializer
|
||||||
|
|
||||||
|
|
||||||
# Services views
|
# SERVICE REGEN
|
||||||
|
|
||||||
|
|
||||||
class ServiceRegenViewSet(viewsets.ModelViewSet):
|
class ServiceRegenViewSet(viewsets.ModelViewSet):
|
||||||
|
"""Exposes list and details of the services to regen
|
||||||
|
"""
|
||||||
serializer_class = serializers.ServiceRegenSerializer
|
serializer_class = serializers.ServiceRegenSerializer
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
@ -363,24 +468,33 @@ class ServiceRegenViewSet(viewsets.ModelViewSet):
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
# DHCP views
|
# DHCP
|
||||||
|
|
||||||
class HostMacIpView(generics.ListAPIView):
|
class HostMacIpView(generics.ListAPIView):
|
||||||
|
"""Exposes the associations between hostname, mac address and IPv4 in
|
||||||
|
order to build the DHCP lease files.
|
||||||
|
"""
|
||||||
queryset = all_active_interfaces()
|
queryset = all_active_interfaces()
|
||||||
serializer_class = serializers.HostMacIpSerializer
|
serializer_class = serializers.HostMacIpSerializer
|
||||||
|
|
||||||
|
|
||||||
# DNS views
|
# DNS
|
||||||
|
|
||||||
class DNSZonesView(generics.ListAPIView):
|
class DNSZonesView(generics.ListAPIView):
|
||||||
|
"""Exposes the detailed information about each extension (hostnames,
|
||||||
|
IPs, DNS records, etc.) in order to build the DNS zone files.
|
||||||
|
"""
|
||||||
queryset = machines.Extension.objects.all()
|
queryset = machines.Extension.objects.all()
|
||||||
serializer_class = serializers.DNSZonesSerializer
|
serializer_class = serializers.DNSZonesSerializer
|
||||||
|
|
||||||
|
|
||||||
# Mailing views
|
# MAILING
|
||||||
|
|
||||||
|
|
||||||
class StandardMailingView(views.APIView):
|
class StandardMailingView(views.APIView):
|
||||||
|
"""Exposes list and details of standard mailings (name and members) in
|
||||||
|
order to building the corresponding mailing lists.
|
||||||
|
"""
|
||||||
pagination_class = PageSizedPagination
|
pagination_class = PageSizedPagination
|
||||||
permission_classes = (ACLPermission, )
|
permission_classes = (ACLPermission, )
|
||||||
perms_map = {'GET' : [users.User.can_view_all]}
|
perms_map = {'GET' : [users.User.can_view_all]}
|
||||||
|
@ -394,13 +508,23 @@ class StandardMailingView(views.APIView):
|
||||||
|
|
||||||
|
|
||||||
class ClubMailingView(generics.ListAPIView):
|
class ClubMailingView(generics.ListAPIView):
|
||||||
|
"""Exposes list and details of club mailings (name, members and admins) in
|
||||||
|
order to build the corresponding mailing lists.
|
||||||
|
"""
|
||||||
queryset = users.Club.objects.all()
|
queryset = users.Club.objects.all()
|
||||||
serializer_class = serializers.MailingSerializer
|
serializer_class = serializers.MailingSerializer
|
||||||
|
|
||||||
|
|
||||||
# Subclass the standard rest_framework.auth_token.views.ObtainAuthToken
|
# TOKEN AUTHENTICATION
|
||||||
# in order to renew the lease of the token and add expiration time
|
|
||||||
|
|
||||||
class ObtainExpiringAuthToken(ObtainAuthToken):
|
class ObtainExpiringAuthToken(ObtainAuthToken):
|
||||||
|
"""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.
|
||||||
|
"""
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
serializer = self.serializer_class(data=request.data)
|
serializer = self.serializer_class(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
Loading…
Reference in a new issue