mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-12-23 15:33:45 +00:00
Merge branch 'update_django' into 'dev'
feat: ⬆️ Support for django 2.2 (#308) See merge request re2o/re2o!604
This commit is contained in:
commit
8c88b6a6c9
169 changed files with 4818 additions and 2415 deletions
11
api/apps.py
Normal file
11
api/apps.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""
|
||||||
|
Configuration of api app.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ApiConfig(AppConfig):
|
||||||
|
"""Configuration of api app."""
|
||||||
|
|
||||||
|
name = "api"
|
|
@ -31,12 +31,10 @@ from rest_framework.authentication import TokenAuthentication
|
||||||
|
|
||||||
|
|
||||||
class ExpiringTokenAuthentication(TokenAuthentication):
|
class ExpiringTokenAuthentication(TokenAuthentication):
|
||||||
"""Authenticate a user if the provided token is valid and not expired.
|
"""Authenticate a user if the provided token is valid and not expired."""
|
||||||
"""
|
|
||||||
|
|
||||||
def authenticate_credentials(self, key):
|
def authenticate_credentials(self, key):
|
||||||
"""See base class. Add the verification the token is not expired.
|
"""See base class. Add the verification the token is not expired."""
|
||||||
"""
|
|
||||||
base = super(ExpiringTokenAuthentication, self)
|
base = super(ExpiringTokenAuthentication, self)
|
||||||
user, token = base.authenticate_credentials(key)
|
user, token = base.authenticate_credentials(key)
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,9 @@
|
||||||
"""Defines the permission classes used in the API.
|
"""Defines the permission classes used in the API.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from rest_framework import permissions, exceptions
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
|
from rest_framework import exceptions, permissions
|
||||||
|
|
||||||
from . import acl
|
from . import acl
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.core.urlresolvers import NoReverseMatch
|
from django.urls import NoReverseMatch
|
||||||
from rest_framework import views
|
from rest_framework import views
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
# The namespace used for the API. It must match the namespace used in the
|
# The namespace used for the API. It must match the namespace used in the
|
||||||
# urlpatterns to include the API URLs.
|
# urlpatterns to include the API URLs.
|
||||||
API_NAMESPACE = "api"
|
API_NAMESPACE = "api"
|
||||||
|
@ -59,7 +58,3 @@ class NamespacedHMSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
|
||||||
serializer_related_field = NamespacedHRField
|
serializer_related_field = NamespacedHRField
|
||||||
serializer_url_field = NamespacedHIField
|
serializer_url_field = NamespacedHIField
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,15 @@ can also be register. That way a complete API root page presenting all URLs
|
||||||
can be generated automatically.
|
can be generated automatically.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.conf.urls import url, include
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.urls import include, path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
from .routers import AllViewsRouter
|
from .routers import AllViewsRouter
|
||||||
from django.conf import settings
|
|
||||||
|
app_name = "api"
|
||||||
|
|
||||||
router = AllViewsRouter()
|
router = AllViewsRouter()
|
||||||
|
|
||||||
|
@ -65,4 +68,4 @@ for _url, view, name in urls_functional_view:
|
||||||
# TOKEN AUTHENTICATION
|
# TOKEN AUTHENTICATION
|
||||||
router.register_view(r"token-auth", views.ObtainExpiringAuthToken)
|
router.register_view(r"token-auth", views.ObtainExpiringAuthToken)
|
||||||
|
|
||||||
urlpatterns = [url(r"^", include(router.urls))]
|
urlpatterns = [path("", include(router.urls))]
|
||||||
|
|
|
@ -29,9 +29,9 @@ the response (JSON or other), the CSRF exempting, ...
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.models import Q
|
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from rest_framework import viewsets, generics, views
|
from django.db.models import Q
|
||||||
|
from rest_framework import generics, views, viewsets
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
from rest_framework.authtoken.views import ObtainAuthToken
|
from rest_framework.authtoken.views import ObtainAuthToken
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
@ -41,7 +41,6 @@ from .pagination import PageSizedPagination
|
||||||
from .permissions import ACLPermission
|
from .permissions import ACLPermission
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ObtainExpiringAuthToken(ObtainAuthToken):
|
class ObtainExpiringAuthToken(ObtainAuthToken):
|
||||||
"""Exposes a view to obtain a authentication token.
|
"""Exposes a view to obtain a authentication token.
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ from __future__ import unicode_literals
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from reversion.admin import VersionAdmin
|
from reversion.admin import VersionAdmin
|
||||||
|
|
||||||
from .models import Facture, Article, Banque, Paiement, Cotisation, Vente
|
from .models import (Article, Banque, CostEstimate, Cotisation, CustomInvoice,
|
||||||
from .models import CustomInvoice, CostEstimate
|
Facture, Paiement, Vente)
|
||||||
|
|
||||||
|
|
||||||
class FactureAdmin(VersionAdmin):
|
class FactureAdmin(VersionAdmin):
|
||||||
|
|
|
@ -23,13 +23,13 @@ from rest_framework import serializers
|
||||||
|
|
||||||
import cotisations.models as cotisations
|
import cotisations.models as cotisations
|
||||||
import preferences.models as preferences
|
import preferences.models as preferences
|
||||||
from api.serializers import NamespacedHRField, NamespacedHIField, NamespacedHMSerializer
|
from api.serializers import (NamespacedHIField, NamespacedHMSerializer,
|
||||||
|
NamespacedHRField)
|
||||||
from users.api.serializers import UserSerializer
|
from users.api.serializers import UserSerializer
|
||||||
|
|
||||||
|
|
||||||
class FactureSerializer(NamespacedHMSerializer):
|
class FactureSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `cotisations.models.Facture` objects.
|
"""Serialize `cotisations.models.Facture` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Facture
|
model = cotisations.Facture
|
||||||
|
@ -54,8 +54,7 @@ class BaseInvoiceSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class VenteSerializer(NamespacedHMSerializer):
|
class VenteSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `cotisations.models.Vente` objects.
|
"""Serialize `cotisations.models.Vente` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Vente
|
model = cotisations.Vente
|
||||||
|
@ -74,17 +73,24 @@ class VenteSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ArticleSerializer(NamespacedHMSerializer):
|
class ArticleSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `cotisations.models.Article` objects.
|
"""Serialize `cotisations.models.Article` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Article
|
model = cotisations.Article
|
||||||
fields = ("name", "prix", "duration_membership", "duration_days_membership", "duration_connection", "duration_days_connection", "type_user", "api_url")
|
fields = (
|
||||||
|
"name",
|
||||||
|
"prix",
|
||||||
|
"duration_membership",
|
||||||
|
"duration_days_membership",
|
||||||
|
"duration_connection",
|
||||||
|
"duration_days_connection",
|
||||||
|
"type_user",
|
||||||
|
"api_url",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BanqueSerializer(NamespacedHMSerializer):
|
class BanqueSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `cotisations.models.Banque` objects.
|
"""Serialize `cotisations.models.Banque` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Banque
|
model = cotisations.Banque
|
||||||
|
@ -92,8 +98,7 @@ class BanqueSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class PaiementSerializer(NamespacedHMSerializer):
|
class PaiementSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `cotisations.models.Paiement` objects.
|
"""Serialize `cotisations.models.Paiement` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Paiement
|
model = cotisations.Paiement
|
||||||
|
@ -101,17 +106,23 @@ class PaiementSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class CotisationSerializer(NamespacedHMSerializer):
|
class CotisationSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `cotisations.models.Cotisation` objects.
|
"""Serialize `cotisations.models.Cotisation` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = cotisations.Cotisation
|
model = cotisations.Cotisation
|
||||||
fields = ("vente", "type_cotisation", "date_start_con", "date_end_con", "date_start_memb", "date_end_memb", "api_url")
|
fields = (
|
||||||
|
"vente",
|
||||||
|
"type_cotisation",
|
||||||
|
"date_start_con",
|
||||||
|
"date_end_con",
|
||||||
|
"date_start_memb",
|
||||||
|
"date_end_memb",
|
||||||
|
"api_url",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ReminderUsersSerializer(UserSerializer):
|
class ReminderUsersSerializer(UserSerializer):
|
||||||
"""Serialize the data about a mailing member.
|
"""Serialize the data about a mailing member."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta(UserSerializer.Meta):
|
class Meta(UserSerializer.Meta):
|
||||||
fields = ("get_full_name", "get_mail")
|
fields = ("get_full_name", "get_mail")
|
||||||
|
|
|
@ -27,12 +27,11 @@ urls_viewset = [
|
||||||
(r"cotisations/article", views.ArticleViewSet, None),
|
(r"cotisations/article", views.ArticleViewSet, None),
|
||||||
(r"cotisations/banque", views.BanqueViewSet, None),
|
(r"cotisations/banque", views.BanqueViewSet, None),
|
||||||
(r"cotisations/paiement", views.PaiementViewSet, None),
|
(r"cotisations/paiement", views.PaiementViewSet, None),
|
||||||
(r"cotisations/cotisation", views.CotisationViewSet, None)
|
(r"cotisations/cotisation", views.CotisationViewSet, None),
|
||||||
]
|
]
|
||||||
|
|
||||||
urls_view = [
|
urls_view = [
|
||||||
(r"cotisations/reminder-get-users", views.ReminderView),
|
(r"cotisations/reminder-get-users", views.ReminderView),
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
(r"reminder/get-users", views.ReminderView),
|
(r"reminder/get-users", views.ReminderView),
|
||||||
]
|
]
|
|
@ -19,71 +19,65 @@
|
||||||
# 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.
|
||||||
|
|
||||||
from rest_framework import viewsets, generics
|
from rest_framework import generics, viewsets
|
||||||
|
|
||||||
from . import serializers
|
|
||||||
import cotisations.models as cotisations
|
import cotisations.models as cotisations
|
||||||
import preferences.models as preferences
|
import preferences.models as preferences
|
||||||
|
|
||||||
|
from . import serializers
|
||||||
|
|
||||||
|
|
||||||
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `cotisations.models.Facture` objects.
|
"""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 FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
class FactureViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `cotisations.models.Facture` objects.
|
"""Exposes list and details of `cotisations.models.Facture` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
queryset = cotisations.BaseInvoice.objects.all()
|
queryset = cotisations.BaseInvoice.objects.all()
|
||||||
serializer_class = serializers.BaseInvoiceSerializer
|
serializer_class = serializers.BaseInvoiceSerializer
|
||||||
|
|
||||||
|
|
||||||
class VenteViewSet(viewsets.ReadOnlyModelViewSet):
|
class VenteViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `cotisations.models.Vente` objects.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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
|
||||||
|
|
||||||
|
|
||||||
class ReminderView(generics.ListAPIView):
|
class ReminderView(generics.ListAPIView):
|
||||||
"""Output for users to remind an end of their subscription.
|
"""Output for users to remind an end of their subscription."""
|
||||||
"""
|
|
||||||
|
|
||||||
queryset = preferences.Reminder.objects.all()
|
queryset = preferences.Reminder.objects.all()
|
||||||
serializer_class = serializers.ReminderSerializer
|
serializer_class = serializers.ReminderSerializer
|
11
cotisations/apps.py
Normal file
11
cotisations/apps.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""
|
||||||
|
Configuration of cotisations app.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class CotisationsConfig(AppConfig):
|
||||||
|
"""Configuration of cotisations app."""
|
||||||
|
|
||||||
|
name = "cotisations"
|
|
@ -37,25 +37,18 @@ of each of the method.
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.db.models import Q
|
|
||||||
from django.forms import ModelForm, Form
|
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
|
from django.db.models import Q
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.forms import Form, ModelForm
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from re2o.field_permissions import FieldPermissionFormMixin
|
from re2o.field_permissions import FieldPermissionFormMixin
|
||||||
from re2o.mixins import FormRevMixin
|
from re2o.mixins import FormRevMixin
|
||||||
from re2o.widgets import AutocompleteModelWidget
|
from re2o.widgets import AutocompleteModelWidget
|
||||||
from .models import (
|
|
||||||
Article,
|
from .models import (Article, Banque, CostEstimate, CustomInvoice, Facture,
|
||||||
Paiement,
|
Paiement, Vente)
|
||||||
Facture,
|
|
||||||
Banque,
|
|
||||||
CustomInvoice,
|
|
||||||
Vente,
|
|
||||||
CostEstimate,
|
|
||||||
)
|
|
||||||
from .payment_methods import balance
|
from .payment_methods import balance
|
||||||
|
|
||||||
|
|
||||||
|
|
49
cotisations/migrations/0004_auto_20210208_1827.py
Normal file
49
cotisations/migrations/0004_auto_20210208_1827.py
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
# Generated by Django 2.2.18 on 2021-02-08 17:27
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('cotisations', '0003_auto_20210124_1105'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='article',
|
||||||
|
options={'permissions': (('buy_every_article', 'Can buy every article'),), 'verbose_name': 'article', 'verbose_name_plural': 'articles'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='banque',
|
||||||
|
options={'verbose_name': 'bank', 'verbose_name_plural': 'banks'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='baseinvoice',
|
||||||
|
options={},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='costestimate',
|
||||||
|
options={},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='cotisation',
|
||||||
|
options={'permissions': (('change_all_cotisation', 'Can edit the previous subscriptions'),), 'verbose_name': 'subscription', 'verbose_name_plural': 'subscriptions'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='custominvoice',
|
||||||
|
options={},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='facture',
|
||||||
|
options={'permissions': (('change_facture_control', 'Can edit the "controlled" state'), ('change_all_facture', 'Can edit all the previous invoices')), 'verbose_name': 'invoice', 'verbose_name_plural': 'invoices'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='paiement',
|
||||||
|
options={'permissions': (('use_every_payment', 'Can use every payment method'),), 'verbose_name': 'payment method', 'verbose_name_plural': 'payment methods'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='vente',
|
||||||
|
options={'permissions': (('change_all_vente', 'Can edit all the previous purchases'),), 'verbose_name': 'purchase', 'verbose_name_plural': 'purchases'},
|
||||||
|
),
|
||||||
|
]
|
|
@ -40,12 +40,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="cotisation",
|
model_name="cotisation",
|
||||||
name="facture",
|
name="facture",
|
||||||
field=models.OneToOneField(to="cotisations.Facture"),
|
field=models.OneToOneField(to="cotisations.Facture", on_delete=models.CASCADE),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="vente",
|
model_name="vente",
|
||||||
name="facture",
|
name="facture",
|
||||||
field=models.ForeignKey(to="cotisations.Facture"),
|
field=models.ForeignKey(to="cotisations.Facture", on_delete=models.CASCADE),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="vente",
|
model_name="vente",
|
||||||
|
|
|
@ -41,7 +41,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="cotisation",
|
model_name="cotisation",
|
||||||
name="vente",
|
name="vente",
|
||||||
field=models.OneToOneField(to="cotisations.Vente", null=True),
|
field=models.OneToOneField(to="cotisations.Vente", null=True, on_delete=models.CASCADE),
|
||||||
preserve_default=False,
|
preserve_default=False,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -32,29 +32,29 @@ each.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from django.contrib import messages
|
||||||
|
from django.core.validators import MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q, Max
|
from django.db.models import Max, Q
|
||||||
from django.db.models.signals import post_save, post_delete
|
from django.db.models.signals import post_delete, post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
from django.core.validators import MinValueValidator
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.urls import reverse
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
from django.contrib import messages
|
|
||||||
|
|
||||||
from preferences.models import CotisationsOption
|
import users.models
|
||||||
|
import users.signals
|
||||||
|
from cotisations.utils import (find_payment_method, send_mail_invoice,
|
||||||
|
send_mail_voucher)
|
||||||
|
from cotisations.validators import check_no_balance
|
||||||
from machines.models import regen
|
from machines.models import regen
|
||||||
|
from preferences.models import CotisationsOption
|
||||||
from re2o.field_permissions import FieldPermissionModelMixin
|
from re2o.field_permissions import FieldPermissionModelMixin
|
||||||
from re2o.mixins import AclMixin, RevMixin
|
from re2o.mixins import AclMixin, RevMixin
|
||||||
import users.signals
|
|
||||||
import users.models
|
|
||||||
|
|
||||||
from cotisations.utils import find_payment_method, send_mail_invoice, send_mail_voucher
|
|
||||||
from cotisations.validators import check_no_balance
|
|
||||||
|
|
||||||
|
|
||||||
class BaseInvoice(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
class BaseInvoice(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
|
@ -62,9 +62,6 @@ class BaseInvoice(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = False
|
abstract = False
|
||||||
permissions = (
|
|
||||||
("view_baseinvoice", _("Can view an base invoice object")),
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO : change prix to price
|
# TODO : change prix to price
|
||||||
def prix(self):
|
def prix(self):
|
||||||
|
@ -157,7 +154,6 @@ class Facture(BaseInvoice):
|
||||||
permissions = (
|
permissions = (
|
||||||
# TODO : change facture to invoice
|
# TODO : change facture to invoice
|
||||||
("change_facture_control", _('Can edit the "controlled" state')),
|
("change_facture_control", _('Can edit the "controlled" state')),
|
||||||
("view_facture", _("Can view an invoice object")),
|
|
||||||
("change_all_facture", _("Can edit all the previous invoices")),
|
("change_all_facture", _("Can edit all the previous invoices")),
|
||||||
)
|
)
|
||||||
verbose_name = _("invoice")
|
verbose_name = _("invoice")
|
||||||
|
@ -364,7 +360,13 @@ def facture_post_save(**kwargs):
|
||||||
if facture.valid:
|
if facture.valid:
|
||||||
user = facture.user
|
user = facture.user
|
||||||
user.set_active()
|
user.set_active()
|
||||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=False, access_refresh=True, mac_refresh=False)
|
users.signals.synchronise.send(
|
||||||
|
sender=users.models.User,
|
||||||
|
instance=user,
|
||||||
|
base=False,
|
||||||
|
access_refresh=True,
|
||||||
|
mac_refresh=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_delete, sender=Facture)
|
@receiver(post_delete, sender=Facture)
|
||||||
|
@ -373,12 +375,16 @@ def facture_post_delete(**kwargs):
|
||||||
Synchronise the LDAP user after an invoice has been deleted.
|
Synchronise the LDAP user after an invoice has been deleted.
|
||||||
"""
|
"""
|
||||||
user = kwargs["instance"].user
|
user = kwargs["instance"].user
|
||||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=False, access_refresh=True, mac_refresh=False)
|
users.signals.synchronise.send(
|
||||||
|
sender=users.models.User,
|
||||||
|
instance=user,
|
||||||
|
base=False,
|
||||||
|
access_refresh=True,
|
||||||
|
mac_refresh=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CustomInvoice(BaseInvoice):
|
class CustomInvoice(BaseInvoice):
|
||||||
class Meta:
|
|
||||||
permissions = (("view_custominvoice", _("Can view a custom invoice object")),)
|
|
||||||
|
|
||||||
recipient = models.CharField(max_length=255, verbose_name=_("recipient"))
|
recipient = models.CharField(max_length=255, verbose_name=_("recipient"))
|
||||||
payment = models.CharField(max_length=255, verbose_name=_("payment type"))
|
payment = models.CharField(max_length=255, verbose_name=_("payment type"))
|
||||||
|
@ -388,8 +394,6 @@ class CustomInvoice(BaseInvoice):
|
||||||
|
|
||||||
|
|
||||||
class CostEstimate(CustomInvoice):
|
class CostEstimate(CustomInvoice):
|
||||||
class Meta:
|
|
||||||
permissions = (("view_costestimate", _("Can view a cost estimate object")),)
|
|
||||||
|
|
||||||
validity = models.DurationField(
|
validity = models.DurationField(
|
||||||
verbose_name=_("period of validity"), help_text="DD HH:MM:SS"
|
verbose_name=_("period of validity"), help_text="DD HH:MM:SS"
|
||||||
|
@ -489,10 +493,7 @@ class Vente(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("change_all_vente", _("Can edit all the previous purchases")),)
|
||||||
("view_vente", _("Can view a purchase object")),
|
|
||||||
("change_all_vente", _("Can edit all the previous purchases")),
|
|
||||||
)
|
|
||||||
verbose_name = _("purchase")
|
verbose_name = _("purchase")
|
||||||
verbose_name_plural = _("purchases")
|
verbose_name_plural = _("purchases")
|
||||||
|
|
||||||
|
@ -669,7 +670,13 @@ def vente_post_save(**kwargs):
|
||||||
purchase.cotisation.save()
|
purchase.cotisation.save()
|
||||||
user = purchase.facture.facture.user
|
user = purchase.facture.facture.user
|
||||||
user.set_active()
|
user.set_active()
|
||||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=True, access_refresh=True, mac_refresh=False)
|
users.signals.synchronise.send(
|
||||||
|
sender=users.models.User,
|
||||||
|
instance=user,
|
||||||
|
base=True,
|
||||||
|
access_refresh=True,
|
||||||
|
mac_refresh=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# TODO : change vente to purchase
|
# TODO : change vente to purchase
|
||||||
|
@ -685,7 +692,13 @@ def vente_post_delete(**kwargs):
|
||||||
return
|
return
|
||||||
if purchase.type_cotisation:
|
if purchase.type_cotisation:
|
||||||
user = invoice.user
|
user = invoice.user
|
||||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=True, access_refresh=True, mac_refresh=False)
|
users.signals.synchronise.send(
|
||||||
|
sender=users.models.User,
|
||||||
|
instance=user,
|
||||||
|
base=True,
|
||||||
|
access_refresh=True,
|
||||||
|
mac_refresh=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Article(RevMixin, AclMixin, models.Model):
|
class Article(RevMixin, AclMixin, models.Model):
|
||||||
|
@ -749,10 +762,7 @@ class Article(RevMixin, AclMixin, models.Model):
|
||||||
unique_together = ("name", "type_user")
|
unique_together = ("name", "type_user")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("buy_every_article", _("Can buy every article")),)
|
||||||
("view_article", _("Can view an article object")),
|
|
||||||
("buy_every_article", _("Can buy every article")),
|
|
||||||
)
|
|
||||||
verbose_name = "article"
|
verbose_name = "article"
|
||||||
verbose_name_plural = "articles"
|
verbose_name_plural = "articles"
|
||||||
|
|
||||||
|
@ -824,7 +834,6 @@ class Banque(RevMixin, AclMixin, models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_banque", _("Can view a bank object")),)
|
|
||||||
verbose_name = _("bank")
|
verbose_name = _("bank")
|
||||||
verbose_name_plural = _("banks")
|
verbose_name_plural = _("banks")
|
||||||
|
|
||||||
|
@ -855,10 +864,7 @@ class Paiement(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("use_every_payment", _("Can use every payment method")),)
|
||||||
("view_paiement", _("Can view a payment method object")),
|
|
||||||
("use_every_payment", _("Can use every payment method")),
|
|
||||||
)
|
|
||||||
verbose_name = _("payment method")
|
verbose_name = _("payment method")
|
||||||
verbose_name_plural = _("payment methods")
|
verbose_name_plural = _("payment methods")
|
||||||
|
|
||||||
|
@ -980,7 +986,6 @@ class Cotisation(RevMixin, AclMixin, models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_cotisation", _("Can view a subscription object")),
|
|
||||||
("change_all_cotisation", _("Can edit the previous subscriptions")),
|
("change_all_cotisation", _("Can edit the previous subscriptions")),
|
||||||
)
|
)
|
||||||
verbose_name = _("subscription")
|
verbose_name = _("subscription")
|
||||||
|
|
|
@ -127,6 +127,6 @@ method to your model, where `form` is an instance of
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from . import comnpay, cheque, balance, note_kfet, free, urls
|
from . import balance, cheque, comnpay, free, note_kfet, urls
|
||||||
|
|
||||||
PAYMENT_METHODS = [comnpay, cheque, balance, note_kfet, free]
|
PAYMENT_METHODS = [comnpay, cheque, balance, note_kfet, free]
|
||||||
|
|
|
@ -18,12 +18,11 @@
|
||||||
# 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.
|
||||||
|
from django.contrib import messages
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.contrib import messages
|
|
||||||
|
|
||||||
|
|
||||||
from cotisations.models import Paiement
|
from cotisations.models import Paiement
|
||||||
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from re2o.mixins import FormRevMixin
|
|
||||||
from cotisations.models import Facture as Invoice
|
from cotisations.models import Facture as Invoice
|
||||||
|
from re2o.mixins import FormRevMixin
|
||||||
|
|
||||||
|
|
||||||
class InvoiceForm(FormRevMixin, forms.ModelForm):
|
class InvoiceForm(FormRevMixin, forms.ModelForm):
|
||||||
|
|
|
@ -19,6 +19,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.
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [url(r"^validate/(?P<invoice_pk>[0-9]+)$", views.cheque, name="validate")]
|
urlpatterns = [url(r"^validate/(?P<invoice_pk>[0-9]+)$", views.cheque, name="validate")]
|
||||||
|
|
|
@ -23,17 +23,17 @@
|
||||||
Here are defined some views dedicated to cheque payement.
|
Here are defined some views dedicated to cheque payement.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.shortcuts import redirect, render, get_object_or_404
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from cotisations.models import Facture as Invoice
|
from cotisations.models import Facture as Invoice
|
||||||
from cotisations.utils import find_payment_method
|
from cotisations.utils import find_payment_method
|
||||||
|
|
||||||
from .models import ChequePayment
|
|
||||||
from .forms import InvoiceForm
|
from .forms import InvoiceForm
|
||||||
|
from .models import ChequePayment
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|
|
@ -3,15 +3,15 @@ The module in charge of handling the negociation with Comnpay
|
||||||
for online payment
|
for online payment
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import time
|
|
||||||
from random import randrange
|
|
||||||
import base64
|
import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import time
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from random import randrange
|
||||||
|
|
||||||
|
|
||||||
class Transaction:
|
class Transaction:
|
||||||
""" The class representing a transaction with all the functions
|
"""The class representing a transaction with all the functions
|
||||||
used during the negociation
|
used during the negociation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ class Transaction:
|
||||||
self.idTransaction = ""
|
self.idTransaction = ""
|
||||||
|
|
||||||
def buildSecretHTML(self, produit="Produit", montant="0.00", idTransaction=""):
|
def buildSecretHTML(self, produit="Produit", montant="0.00", idTransaction=""):
|
||||||
""" Build an HTML hidden form with the different parameters for the
|
"""Build an HTML hidden form with the different parameters for the
|
||||||
transaction
|
transaction
|
||||||
"""
|
"""
|
||||||
if idTransaction == "":
|
if idTransaction == "":
|
||||||
|
|
|
@ -25,8 +25,8 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from cotisations.models import Paiement
|
from cotisations.models import Paiement
|
||||||
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
||||||
|
|
||||||
from re2o.aes_field import AESEncryptedField
|
from re2o.aes_field import AESEncryptedField
|
||||||
|
|
||||||
from .comnpay import Transaction
|
from .comnpay import Transaction
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,8 +53,7 @@ class ComnpayPayment(PaymentMethodMixin, models.Model):
|
||||||
minimum_payment = models.DecimalField(
|
minimum_payment = models.DecimalField(
|
||||||
verbose_name=_("minimum payment"),
|
verbose_name=_("minimum payment"),
|
||||||
help_text=_(
|
help_text=_(
|
||||||
"The minimal amount of money you have to use when paying with"
|
"The minimal amount of money you have to use when paying with" " ComNpay."
|
||||||
" ComNpay."
|
|
||||||
),
|
),
|
||||||
max_digits=5,
|
max_digits=5,
|
||||||
decimal_places=2,
|
decimal_places=2,
|
||||||
|
@ -107,8 +106,7 @@ class ComnpayPayment(PaymentMethodMixin, models.Model):
|
||||||
return render(request, "cotisations/payment.html", r)
|
return render(request, "cotisations/payment.html", r)
|
||||||
|
|
||||||
def check_price(self, price, *args, **kwargs):
|
def check_price(self, price, *args, **kwargs):
|
||||||
"""Checks that the price meets the requirement to be paid with ComNpay.
|
"""Checks that the price meets the requirement to be paid with ComNpay."""
|
||||||
"""
|
|
||||||
return (
|
return (
|
||||||
(price >= self.minimum_payment),
|
(price >= self.minimum_payment),
|
||||||
_(
|
_(
|
||||||
|
|
|
@ -19,6 +19,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.
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
|
@ -25,16 +25,17 @@ Here are the views needed by comnpay
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.shortcuts import redirect, get_object_or_404
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.http import HttpResponse, HttpResponseBadRequest
|
||||||
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.datastructures import MultiValueDictKeyError
|
from django.utils.datastructures import MultiValueDictKeyError
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
from cotisations.models import Facture
|
from cotisations.models import Facture
|
||||||
|
|
||||||
from .comnpay import Transaction
|
from .comnpay import Transaction
|
||||||
from .models import ComnpayPayment
|
from .models import ComnpayPayment
|
||||||
|
|
||||||
|
@ -55,7 +56,10 @@ def accept_payment(request, factureid):
|
||||||
)
|
)
|
||||||
# In case a cotisation was bought, inform the user, the
|
# In case a cotisation was bought, inform the user, the
|
||||||
# cotisation time has been extended too
|
# cotisation time has been extended too
|
||||||
if any(purchase.test_membership_or_connection() for purchase in invoice.vente_set.all()):
|
if any(
|
||||||
|
purchase.test_membership_or_connection()
|
||||||
|
for purchase in invoice.vente_set.all()
|
||||||
|
):
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
_(
|
_(
|
||||||
|
|
|
@ -21,9 +21,10 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from . import PAYMENT_METHODS
|
|
||||||
from cotisations.utils import find_payment_method
|
from cotisations.utils import find_payment_method
|
||||||
|
|
||||||
|
from . import PAYMENT_METHODS
|
||||||
|
|
||||||
|
|
||||||
def payment_method_factory(payment, *args, creation=True, **kwargs):
|
def payment_method_factory(payment, *args, creation=True, **kwargs):
|
||||||
"""This function finds the right payment method form for a given payment.
|
"""This function finds the right payment method form for a given payment.
|
||||||
|
|
|
@ -18,10 +18,9 @@
|
||||||
# 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.
|
||||||
|
from django.contrib import messages
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.contrib import messages
|
|
||||||
|
|
||||||
|
|
||||||
from cotisations.models import Paiement
|
from cotisations.models import Paiement
|
||||||
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
||||||
|
@ -43,8 +42,7 @@ class FreePayment(PaymentMethodMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
def end_payment(self, invoice, request):
|
def end_payment(self, invoice, request):
|
||||||
"""Ends the payment normally.
|
"""Ends the payment normally."""
|
||||||
"""
|
|
||||||
return invoice.paiement.end_payment(invoice, request, use_payment_method=False)
|
return invoice.paiement.end_payment(invoice, request, use_payment_method=False)
|
||||||
|
|
||||||
def check_price(self, price, user, *args, **kwargs):
|
def check_price(self, price, user, *args, **kwargs):
|
||||||
|
|
|
@ -19,17 +19,15 @@
|
||||||
# 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.
|
||||||
|
from django.contrib import messages
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.shortcuts import render
|
from django.shortcuts import redirect, render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.contrib import messages
|
|
||||||
|
|
||||||
from cotisations.models import Paiement
|
from cotisations.models import Paiement
|
||||||
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
from cotisations.payment_methods.mixins import PaymentMethodMixin
|
||||||
|
|
||||||
from django.shortcuts import render, redirect
|
|
||||||
|
|
||||||
|
|
||||||
class NotePayment(PaymentMethodMixin, models.Model):
|
class NotePayment(PaymentMethodMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
""" Module pour dialoguer avec la NoteKfet2015 """
|
""" Module pour dialoguer avec la NoteKfet2015 """
|
||||||
|
|
||||||
import socket
|
|
||||||
import json
|
import json
|
||||||
|
import socket
|
||||||
import ssl
|
import ssl
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,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.
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
|
@ -26,22 +26,23 @@ Here are the views needed by comnpay
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.shortcuts import redirect, get_object_or_404
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.http import HttpResponse, HttpResponseBadRequest
|
||||||
|
from django.shortcuts import get_object_or_404, redirect
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.datastructures import MultiValueDictKeyError
|
from django.utils.datastructures import MultiValueDictKeyError
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
from cotisations.models import Facture
|
from cotisations.models import Facture
|
||||||
from cotisations.utils import find_payment_method
|
from cotisations.utils import find_payment_method
|
||||||
from .models import NotePayment
|
|
||||||
from re2o.views import form
|
|
||||||
from re2o.acl import can_create, can_edit
|
from re2o.acl import can_create, can_edit
|
||||||
from .note import login, don
|
from re2o.views import form
|
||||||
|
|
||||||
from .forms import NoteCredentialForm
|
from .forms import NoteCredentialForm
|
||||||
|
from .models import NotePayment
|
||||||
|
from .note import don, login
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|
|
@ -19,10 +19,11 @@
|
||||||
# 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.
|
||||||
from django.conf.urls import include, url
|
from django.conf.urls import include, url
|
||||||
from . import comnpay, cheque, note_kfet
|
|
||||||
|
from . import cheque, comnpay, note_kfet
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r"^comnpay/", include(comnpay.urls, namespace="comnpay")),
|
url(r"^comnpay/", include((comnpay.urls, "comnpay"), namespace="comnpay")),
|
||||||
url(r"^cheque/", include(cheque.urls, namespace="cheque")),
|
url(r"^cheque/", include((cheque.urls, "cheque"), namespace="cheque")),
|
||||||
url(r"^note_kfet/", include(note_kfet.urls, namespace="note_kfet")),
|
url(r"^note_kfet/", include((note_kfet.urls, "note_kfet"), namespace="note_kfet")),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from django.utils import timezone
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from .models import Vente, Facture, Cotisation, Paiement
|
|
||||||
|
from .models import Cotisation, Facture, Paiement, Vente
|
||||||
|
|
||||||
|
|
||||||
class VenteModelTests(TestCase):
|
class VenteModelTests(TestCase):
|
||||||
|
@ -111,12 +112,21 @@ class VenteModelTests(TestCase):
|
||||||
duration_days_connection=1,
|
duration_days_connection=1,
|
||||||
duration_membership=0,
|
duration_membership=0,
|
||||||
duration_deys_membership=1,
|
duration_deys_membership=1,
|
||||||
prix=0
|
prix=0,
|
||||||
|
)
|
||||||
|
v.create_cotis(
|
||||||
|
date_start_con=timezone.make_aware(datetime.datetime(1998, 10, 16)),
|
||||||
|
date_start_memb=timezone.make_aware(datetime.datetime(1998, 10, 16)),
|
||||||
)
|
)
|
||||||
v.create_cotis(date_start_con=timezone.make_aware(datetime.datetime(1998, 10, 16)), date_start_memb=timezone.make_aware(datetime.datetime(1998, 10, 16)))
|
|
||||||
v.save()
|
v.save()
|
||||||
self.assertEqual(v.cotisation.date_end_con, timezone.make_aware(datetime.datetime(1998, 10, 17)))
|
self.assertEqual(
|
||||||
self.assertEqual(v.cotisation.date_end_memb, timezone.make_aware(datetime.datetime(1998, 10, 17)))
|
v.cotisation.date_end_con,
|
||||||
|
timezone.make_aware(datetime.datetime(1998, 10, 17)),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
v.cotisation.date_end_memb,
|
||||||
|
timezone.make_aware(datetime.datetime(1998, 10, 17)),
|
||||||
|
)
|
||||||
|
|
||||||
def test_one_day_cotisation_membership_only(self):
|
def test_one_day_cotisation_membership_only(self):
|
||||||
"""
|
"""
|
||||||
|
@ -207,12 +217,21 @@ class VenteModelTests(TestCase):
|
||||||
duration_days_connection=0,
|
duration_days_connection=0,
|
||||||
duration_membership=0,
|
duration_membership=0,
|
||||||
duration_days_membership=1,
|
duration_days_membership=1,
|
||||||
prix=0
|
prix=0,
|
||||||
|
)
|
||||||
|
v.create_cotis(
|
||||||
|
date_start_con=timezone.make_aware(datetime.datetime(1998, 10, 16)),
|
||||||
|
date_start_memb=timezone.make_aware(datetime.datetime(1998, 10, 16)),
|
||||||
)
|
)
|
||||||
v.create_cotis(date_start_con=timezone.make_aware(datetime.datetime(1998, 10, 16)), date_start_memb=timezone.make_aware(datetime.datetime(1998, 10, 16)))
|
|
||||||
v.save()
|
v.save()
|
||||||
self.assertEqual(v.cotisation.date_end_con, timezone.make_aware(datetime.datetime(1998, 10, 17)))
|
self.assertEqual(
|
||||||
self.assertEqual(v.cotisation.date_end_memb, timezone.make_aware(datetime.datetime(1998, 10, 16)))
|
v.cotisation.date_end_con,
|
||||||
|
timezone.make_aware(datetime.datetime(1998, 10, 17)),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
v.cotisation.date_end_memb,
|
||||||
|
timezone.make_aware(datetime.datetime(1998, 10, 16)),
|
||||||
|
)
|
||||||
|
|
||||||
def test_cotisation_membership_diff_connection(self):
|
def test_cotisation_membership_diff_connection(self):
|
||||||
"""
|
"""
|
||||||
|
@ -252,9 +271,11 @@ class FactureModelTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.user = User.objects.create(pseudo="testUserPlop", email="test@example.org")
|
self.user = User.objects.create(pseudo="testUserPlop", email="test@example.org")
|
||||||
self.paiement = Paiement.objects.create(moyen="test payment")
|
self.paiement = Paiement.objects.create(moyen="test payment")
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.user.delete()
|
self.user.delete()
|
||||||
self.paiement.delete()
|
self.paiement.delete()
|
||||||
|
|
||||||
def test_cotisations_prolongation(self):
|
def test_cotisations_prolongation(self):
|
||||||
"""When user already have one valid cotisation, the new one should be
|
"""When user already have one valid cotisation, the new one should be
|
||||||
added at the end of the existing one."""
|
added at the end of the existing one."""
|
||||||
|
@ -300,4 +321,3 @@ class FactureModelTests(TestCase):
|
||||||
raise e
|
raise e
|
||||||
invoice1.delete()
|
invoice1.delete()
|
||||||
invoice2.delete()
|
invoice2.delete()
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.contrib.auth.models import Permission
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from users.models import Adherent
|
from users.models import Adherent
|
||||||
from .models import Vente, Facture, Cotisation, Paiement, Article
|
|
||||||
|
from .models import Article, Cotisation, Facture, Paiement, Vente
|
||||||
|
|
||||||
|
|
||||||
class NewFactureTests(TestCase):
|
class NewFactureTests(TestCase):
|
||||||
|
|
|
@ -26,20 +26,19 @@ Used to generated PDF invoice.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import tempfile
|
|
||||||
from subprocess import Popen, PIPE
|
|
||||||
import os
|
import os
|
||||||
|
import tempfile
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from subprocess import PIPE, Popen
|
||||||
|
|
||||||
from django.db import models
|
|
||||||
from django.template.loader import get_template
|
|
||||||
from django.http import HttpResponse
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db import models
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.template.loader import get_template
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
|
||||||
from re2o.mixins import AclMixin, RevMixin
|
|
||||||
from preferences.models import CotisationsOption
|
from preferences.models import CotisationsOption
|
||||||
|
from re2o.mixins import AclMixin, RevMixin
|
||||||
|
|
||||||
TEMP_PREFIX = getattr(settings, "TEX_TEMP_PREFIX", "render_tex-")
|
TEMP_PREFIX = getattr(settings, "TEX_TEMP_PREFIX", "render_tex-")
|
||||||
CACHE_PREFIX = getattr(settings, "TEX_CACHE_PREFIX", "render-tex")
|
CACHE_PREFIX = getattr(settings, "TEX_CACHE_PREFIX", "render-tex")
|
||||||
|
|
|
@ -25,85 +25,84 @@ The defined URLs for the Cotisations app
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.urls import path
|
||||||
|
|
||||||
from . import views, views_autocomplete
|
from . import payment_methods, views, views_autocomplete
|
||||||
from . import payment_methods
|
|
||||||
|
app_name = "cotisations"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r"^new_facture/(?P<userid>[0-9]+)$", views.new_facture, name="new-facture"),
|
path("new_facture/<int:userid>", views.new_facture, name="new-facture"),
|
||||||
url(
|
path("edit_facture/<int:factureid>", views.edit_facture, name="edit-facture"),
|
||||||
r"^edit_facture/(?P<factureid>[0-9]+)$", views.edit_facture, name="edit-facture"
|
path("del_facture/<int:factureid>", views.del_facture, name="del-facture"),
|
||||||
),
|
path("facture_pdf/<int:factureid>", views.facture_pdf, name="facture-pdf"),
|
||||||
url(r"^del_facture/(?P<factureid>[0-9]+)$", views.del_facture, name="del-facture"),
|
path("voucher_pdf/<int:factureid>", views.voucher_pdf, name="voucher-pdf"),
|
||||||
url(r"^facture_pdf/(?P<factureid>[0-9]+)$", views.facture_pdf, name="facture-pdf"),
|
path("new_cost_estimate", views.new_cost_estimate, name="new-cost-estimate"),
|
||||||
url(r"^voucher_pdf/(?P<factureid>[0-9]+)$", views.voucher_pdf, name="voucher-pdf"),
|
path("index_cost_estimate", views.index_cost_estimate, name="index-cost-estimate"),
|
||||||
url(r"^new_cost_estimate/$", views.new_cost_estimate, name="new-cost-estimate"),
|
path(
|
||||||
url(
|
"cost_estimate_pdf/<int:costestimateid>",
|
||||||
r"^index_cost_estimate/$", views.index_cost_estimate, name="index-cost-estimate"
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
r"^cost_estimate_pdf/(?P<costestimateid>[0-9]+)$",
|
|
||||||
views.cost_estimate_pdf,
|
views.cost_estimate_pdf,
|
||||||
name="cost-estimate-pdf",
|
name="cost-estimate-pdf",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^index_custom_invoice/$",
|
"index_custom_invoice",
|
||||||
views.index_custom_invoice,
|
views.index_custom_invoice,
|
||||||
name="index-custom-invoice",
|
name="index-custom-invoice",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^edit_cost_estimate/(?P<costestimateid>[0-9]+)$",
|
"edit_cost_estimate/<int:costestimateid>",
|
||||||
views.edit_cost_estimate,
|
views.edit_cost_estimate,
|
||||||
name="edit-cost-estimate",
|
name="edit-cost-estimate",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^cost_estimate_to_invoice/(?P<costestimateid>[0-9]+)$",
|
"cost_estimate_to_invoice/<int:costestimateid>",
|
||||||
views.cost_estimate_to_invoice,
|
views.cost_estimate_to_invoice,
|
||||||
name="cost-estimate-to-invoice",
|
name="cost-estimate-to-invoice",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_cost_estimate/(?P<costestimateid>[0-9]+)$",
|
"del_cost_estimate/<int:costestimateid>",
|
||||||
views.del_cost_estimate,
|
views.del_cost_estimate,
|
||||||
name="del-cost-estimate",
|
name="del-cost-estimate",
|
||||||
),
|
),
|
||||||
url(r"^new_custom_invoice/$", views.new_custom_invoice, name="new-custom-invoice"),
|
path("new_custom_invoice", views.new_custom_invoice, name="new-custom-invoice"),
|
||||||
url(
|
path(
|
||||||
r"^edit_custom_invoice/(?P<custominvoiceid>[0-9]+)$",
|
"edit_custom_invoice/<int:custominvoiceid>",
|
||||||
views.edit_custom_invoice,
|
views.edit_custom_invoice,
|
||||||
name="edit-custom-invoice",
|
name="edit-custom-invoice",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^custom_invoice_pdf/(?P<custominvoiceid>[0-9]+)$",
|
"custom_invoice_pdf/<int:custominvoiceid>",
|
||||||
views.custom_invoice_pdf,
|
views.custom_invoice_pdf,
|
||||||
name="custom-invoice-pdf",
|
name="custom-invoice-pdf",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_custom_invoice/(?P<custominvoiceid>[0-9]+)$",
|
"del_custom_invoice/<int:custominvoiceid>",
|
||||||
views.del_custom_invoice,
|
views.del_custom_invoice,
|
||||||
name="del-custom-invoice",
|
name="del-custom-invoice",
|
||||||
),
|
),
|
||||||
url(r"^credit_solde/(?P<userid>[0-9]+)$", views.credit_solde, name="credit-solde"),
|
path("credit_solde/<int:userid>", views.credit_solde, name="credit-solde"),
|
||||||
url(r"^add_article/$", views.add_article, name="add-article"),
|
path("add_article", views.add_article, name="add-article"),
|
||||||
url(
|
path("edit_article/<int:articleid>", views.edit_article, name="edit-article"),
|
||||||
r"^edit_article/(?P<articleid>[0-9]+)$", views.edit_article, name="edit-article"
|
path("del_article", views.del_article, name="del-article"),
|
||||||
),
|
path("add_paiement", views.add_paiement, name="add-paiement"),
|
||||||
url(r"^del_article/$", views.del_article, name="del-article"),
|
path(
|
||||||
url(r"^add_paiement/$", views.add_paiement, name="add-paiement"),
|
"edit_paiement/<int:paiementid>",
|
||||||
url(
|
|
||||||
r"^edit_paiement/(?P<paiementid>[0-9]+)$",
|
|
||||||
views.edit_paiement,
|
views.edit_paiement,
|
||||||
name="edit-paiement",
|
name="edit-paiement",
|
||||||
),
|
),
|
||||||
url(r"^del_paiement/$", views.del_paiement, name="del-paiement"),
|
path("del_paiement", views.del_paiement, name="del-paiement"),
|
||||||
url(r"^add_banque/$", views.add_banque, name="add-banque"),
|
path("add_banque", views.add_banque, name="add-banque"),
|
||||||
url(r"^edit_banque/(?P<banqueid>[0-9]+)$", views.edit_banque, name="edit-banque"),
|
path("edit_banque/<int:banqueid>", views.edit_banque, name="edit-banque"),
|
||||||
url(r"^del_banque/$", views.del_banque, name="del-banque"),
|
path("del_banque", views.del_banque, name="del-banque"),
|
||||||
url(r"^index_article/$", views.index_article, name="index-article"),
|
path("index_article", views.index_article, name="index-article"),
|
||||||
url(r"^index_banque/$", views.index_banque, name="index-banque"),
|
path("index_banque", views.index_banque, name="index-banque"),
|
||||||
url(r"^index_paiement/$", views.index_paiement, name="index-paiement"),
|
path("index_paiement", views.index_paiement, name="index-paiement"),
|
||||||
url(r"^control/$", views.control, name="control"),
|
path("control", views.control, name="control"),
|
||||||
url(r"^$", views.index, name="index"),
|
path("", views.index, name="index"),
|
||||||
### Autocomplete Views
|
### Autocomplete Views
|
||||||
url(r'^banque-autocomplete/$', views_autocomplete.BanqueAutocomplete.as_view(), name='banque-autocomplete',),
|
path(
|
||||||
|
"banque-autocomplete",
|
||||||
|
views_autocomplete.BanqueAutocomplete.as_view(),
|
||||||
|
name="banque-autocomplete",
|
||||||
|
),
|
||||||
] + payment_methods.urls.urlpatterns
|
] + payment_methods.urls.urlpatterns
|
||||||
|
|
|
@ -21,14 +21,16 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.template.loader import get_template
|
|
||||||
from django.core.mail import EmailMessage
|
from django.core.mail import EmailMessage
|
||||||
|
from django.template.loader import get_template
|
||||||
|
|
||||||
|
from preferences.models import (AssoOption, CotisationsOption, GeneralOption,
|
||||||
|
Mandate)
|
||||||
|
from re2o import settings
|
||||||
from re2o.mail_utils import send_mail_object
|
from re2o.mail_utils import send_mail_object
|
||||||
|
from re2o.settings import LOGO_PATH
|
||||||
|
|
||||||
from .tex import create_pdf
|
from .tex import create_pdf
|
||||||
from preferences.models import AssoOption, GeneralOption, CotisationsOption, Mandate
|
|
||||||
from re2o.settings import LOGO_PATH
|
|
||||||
from re2o import settings
|
|
||||||
|
|
||||||
|
|
||||||
def find_payment_method(payment):
|
def find_payment_method(payment):
|
||||||
|
@ -74,7 +76,9 @@ def send_mail_invoice(invoice, request=None):
|
||||||
"tpl_path": os.path.join(settings.BASE_DIR, LOGO_PATH),
|
"tpl_path": os.path.join(settings.BASE_DIR, LOGO_PATH),
|
||||||
}
|
}
|
||||||
|
|
||||||
template = CotisationsOption.get_cached_value("invoice_template").template.name.split("/")[-1]
|
template = CotisationsOption.get_cached_value(
|
||||||
|
"invoice_template"
|
||||||
|
).template.name.split("/")[-1]
|
||||||
pdf = create_pdf(template, ctx)
|
pdf = create_pdf(template, ctx)
|
||||||
template = get_template("cotisations/email_invoice")
|
template = get_template("cotisations/email_invoice")
|
||||||
|
|
||||||
|
@ -106,7 +110,9 @@ def send_mail_voucher(invoice, request=None):
|
||||||
"email": invoice.user.email,
|
"email": invoice.user.email,
|
||||||
"phone": invoice.user.telephone,
|
"phone": invoice.user.telephone,
|
||||||
"date_end": invoice.get_subscription().latest("date_end_memb").date_end_memb,
|
"date_end": invoice.get_subscription().latest("date_end_memb").date_end_memb,
|
||||||
"date_begin": invoice.get_subscription().earliest("date_start_memb").date_start_memb,
|
"date_begin": invoice.get_subscription()
|
||||||
|
.earliest("date_start_memb")
|
||||||
|
.date_start_memb,
|
||||||
}
|
}
|
||||||
templatename = CotisationsOption.get_cached_value(
|
templatename = CotisationsOption.get_cached_value(
|
||||||
"voucher_template"
|
"voucher_template"
|
||||||
|
|
|
@ -29,62 +29,38 @@ The different views used in the Cotisations module
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.shortcuts import render, redirect, get_object_or_404
|
|
||||||
from django.template.loader import render_to_string
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.db.models import ProtectedError
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.db.models import Q
|
from django.db.models import ProtectedError, Q
|
||||||
from django.forms import modelformset_factory, formset_factory
|
from django.forms import formset_factory, modelformset_factory
|
||||||
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
# Import des models, forms et fonctions re2o
|
# Import des models, forms et fonctions re2o
|
||||||
from reversion import revisions as reversion
|
from reversion import revisions as reversion
|
||||||
from users.models import User
|
|
||||||
from re2o.settings import LOGO_PATH
|
|
||||||
from re2o import settings
|
|
||||||
from re2o.views import form
|
|
||||||
from re2o.base import SortTable, re2o_paginator
|
|
||||||
from re2o.acl import (
|
|
||||||
can_create,
|
|
||||||
can_edit,
|
|
||||||
can_delete,
|
|
||||||
can_view,
|
|
||||||
can_view_all,
|
|
||||||
can_delete_set,
|
|
||||||
can_change,
|
|
||||||
)
|
|
||||||
from preferences.models import AssoOption, GeneralOption, Mandate
|
from preferences.models import AssoOption, GeneralOption, Mandate
|
||||||
from .models import (
|
from re2o import settings
|
||||||
Facture,
|
from re2o.acl import (can_change, can_create, can_delete, can_delete_set,
|
||||||
Article,
|
can_edit, can_view, can_view_all)
|
||||||
Vente,
|
from re2o.base import SortTable, re2o_paginator
|
||||||
Paiement,
|
from re2o.settings import LOGO_PATH
|
||||||
Banque,
|
from re2o.views import form
|
||||||
CustomInvoice,
|
from users.models import User
|
||||||
BaseInvoice,
|
|
||||||
CostEstimate,
|
from .forms import (ArticleForm, BanqueForm, CostEstimateForm,
|
||||||
)
|
CustomInvoiceForm, DelArticleForm, DelBanqueForm,
|
||||||
from .forms import (
|
DelPaiementForm, DiscountForm, FactureForm, PaiementForm,
|
||||||
FactureForm,
|
RechargeForm, SelectArticleForm)
|
||||||
ArticleForm,
|
from .models import (Article, Banque, BaseInvoice, CostEstimate, CustomInvoice,
|
||||||
DelArticleForm,
|
Facture, Paiement, Vente)
|
||||||
PaiementForm,
|
|
||||||
DelPaiementForm,
|
|
||||||
BanqueForm,
|
|
||||||
DelBanqueForm,
|
|
||||||
SelectArticleForm,
|
|
||||||
RechargeForm,
|
|
||||||
CustomInvoiceForm,
|
|
||||||
DiscountForm,
|
|
||||||
CostEstimateForm,
|
|
||||||
)
|
|
||||||
from .tex import render_invoice, render_voucher, escape_chars
|
|
||||||
from .payment_methods.forms import payment_method_factory
|
from .payment_methods.forms import payment_method_factory
|
||||||
|
from .tex import escape_chars, render_invoice, render_voucher
|
||||||
from .utils import find_payment_method
|
from .utils import find_payment_method
|
||||||
|
|
||||||
|
|
||||||
|
@ -1057,12 +1033,15 @@ def voucher_pdf(request, invoice, **_kwargs):
|
||||||
"lastname": invoice.user.surname,
|
"lastname": invoice.user.surname,
|
||||||
"email": invoice.user.email,
|
"email": invoice.user.email,
|
||||||
"phone": invoice.user.telephone,
|
"phone": invoice.user.telephone,
|
||||||
"date_end": invoice.get_subscription().latest("date_end_memb").date_end_memb,
|
"date_end": invoice.get_subscription()
|
||||||
|
.latest("date_end_memb")
|
||||||
|
.date_end_memb,
|
||||||
"date_begin": invoice.date,
|
"date_begin": invoice.date,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def aff_profil(request,user):
|
|
||||||
|
def aff_profil(request, user):
|
||||||
"""View used to display the cotisations on a user's profil."""
|
"""View used to display the cotisations on a user's profil."""
|
||||||
|
|
||||||
factures = Facture.objects.filter(user=user)
|
factures = Facture.objects.filter(user=user)
|
||||||
|
@ -1074,13 +1053,13 @@ def aff_profil(request,user):
|
||||||
)
|
)
|
||||||
|
|
||||||
pagination_large_number = GeneralOption.get_cached_value("pagination_large_number")
|
pagination_large_number = GeneralOption.get_cached_value("pagination_large_number")
|
||||||
factures = re2o_paginator(request, factures,pagination_large_number)
|
factures = re2o_paginator(request, factures, pagination_large_number)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"users":user,
|
"users": user,
|
||||||
"facture_list": factures,
|
"facture_list": factures,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render_to_string(
|
return render_to_string(
|
||||||
"cotisations/aff_profil.html",context=context,request=request,using=None
|
"cotisations/aff_profil.html", context=context, request=request, using=None
|
||||||
)
|
)
|
||||||
|
|
|
@ -31,20 +31,13 @@ Here are defined the autocomplete class based view.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db.models import Q, Value, CharField
|
from django.db.models import CharField, Q, Value
|
||||||
|
|
||||||
from .models import (
|
|
||||||
Banque
|
|
||||||
)
|
|
||||||
|
|
||||||
|
from re2o.acl import can_view_all
|
||||||
from re2o.views import AutocompleteViewMixin
|
from re2o.views import AutocompleteViewMixin
|
||||||
|
|
||||||
from re2o.acl import (
|
from .models import Banque
|
||||||
can_view_all,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class BanqueAutocomplete(AutocompleteViewMixin):
|
class BanqueAutocomplete(AutocompleteViewMixin):
|
||||||
obj_type = Banque
|
obj_type = Banque
|
||||||
|
|
||||||
|
|
||||||
|
|
438
dev-requirements.txt
Normal file
438
dev-requirements.txt
Normal file
|
@ -0,0 +1,438 @@
|
||||||
|
alabaster==0.7.12; python_version >= "3.5" \
|
||||||
|
--hash=sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359 \
|
||||||
|
--hash=sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02
|
||||||
|
appdirs==1.4.4; python_version >= "3.6" \
|
||||||
|
--hash=sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128 \
|
||||||
|
--hash=sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41
|
||||||
|
babel==2.9.0; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5 \
|
||||||
|
--hash=sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05
|
||||||
|
black==20.8b1; python_version >= "3.6" \
|
||||||
|
--hash=sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea
|
||||||
|
certifi==2020.12.5; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830 \
|
||||||
|
--hash=sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c
|
||||||
|
chardet==4.0.0; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5 \
|
||||||
|
--hash=sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa
|
||||||
|
click==7.1.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc \
|
||||||
|
--hash=sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a
|
||||||
|
colorama==0.4.4; python_version >= "3.5" and python_full_version < "3.0.0" and sys_platform == "win32" or sys_platform == "win32" and python_version >= "3.5" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2 \
|
||||||
|
--hash=sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b
|
||||||
|
coverage==5.4; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0" and python_version < "4") \
|
||||||
|
--hash=sha256:6d9c88b787638a451f41f97446a1c9fd416e669b4d9717ae4615bd29de1ac135 \
|
||||||
|
--hash=sha256:66a5aae8233d766a877c5ef293ec5ab9520929c2578fd2069308a98b7374ea8c \
|
||||||
|
--hash=sha256:9754a5c265f991317de2bac0c70a746efc2b695cf4d49f5d2cddeac36544fb44 \
|
||||||
|
--hash=sha256:fbb17c0d0822684b7d6c09915677a32319f16ff1115df5ec05bdcaaee40b35f3 \
|
||||||
|
--hash=sha256:b7f7421841f8db443855d2854e25914a79a1ff48ae92f70d0a5c2f8907ab98c9 \
|
||||||
|
--hash=sha256:4a780807e80479f281d47ee4af2eb2df3e4ccf4723484f77da0bb49d027e40a1 \
|
||||||
|
--hash=sha256:87c4b38288f71acd2106f5d94f575bc2136ea2887fdb5dfe18003c881fa6b370 \
|
||||||
|
--hash=sha256:c6809ebcbf6c1049002b9ac09c127ae43929042ec1f1dbd8bb1615f7cd9f70a0 \
|
||||||
|
--hash=sha256:ba7ca81b6d60a9f7a0b4b4e175dcc38e8fef4992673d9d6e6879fd6de00dd9b8 \
|
||||||
|
--hash=sha256:89fc12c6371bf963809abc46cced4a01ca4f99cba17be5e7d416ed7ef1245d19 \
|
||||||
|
--hash=sha256:4a8eb7785bd23565b542b01fb39115a975fefb4a82f23d407503eee2c0106247 \
|
||||||
|
--hash=sha256:7e40d3f8eb472c1509b12ac2a7e24158ec352fc8567b77ab02c0db053927e339 \
|
||||||
|
--hash=sha256:1ccae21a076d3d5f471700f6d30eb486da1626c380b23c70ae32ab823e453337 \
|
||||||
|
--hash=sha256:755c56beeacac6a24c8e1074f89f34f4373abce8b662470d3aa719ae304931f3 \
|
||||||
|
--hash=sha256:322549b880b2d746a7672bf6ff9ed3f895e9c9f108b714e7360292aa5c5d7cf4 \
|
||||||
|
--hash=sha256:60a3307a84ec60578accd35d7f0c71a3a971430ed7eca6567399d2b50ef37b8c \
|
||||||
|
--hash=sha256:1375bb8b88cb050a2d4e0da901001347a44302aeadb8ceb4b6e5aa373b8ea68f \
|
||||||
|
--hash=sha256:16baa799ec09cc0dcb43a10680573269d407c159325972dd7114ee7649e56c66 \
|
||||||
|
--hash=sha256:2f2cf7a42d4b7654c9a67b9d091ec24374f7c58794858bff632a2039cb15984d \
|
||||||
|
--hash=sha256:b62046592b44263fa7570f1117d372ae3f310222af1fc1407416f037fb3af21b \
|
||||||
|
--hash=sha256:812eaf4939ef2284d29653bcfee9665f11f013724f07258928f849a2306ea9f9 \
|
||||||
|
--hash=sha256:859f0add98707b182b4867359e12bde806b82483fb12a9ae868a77880fc3b7af \
|
||||||
|
--hash=sha256:04b14e45d6a8e159c9767ae57ecb34563ad93440fc1b26516a89ceb5b33c1ad5 \
|
||||||
|
--hash=sha256:ebfa374067af240d079ef97b8064478f3bf71038b78b017eb6ec93ede1b6bcec \
|
||||||
|
--hash=sha256:84df004223fd0550d0ea7a37882e5c889f3c6d45535c639ce9802293b39cd5c9 \
|
||||||
|
--hash=sha256:1b811662ecf72eb2d08872731636aee6559cae21862c36f74703be727b45df90 \
|
||||||
|
--hash=sha256:6b588b5cf51dc0fd1c9e19f622457cc74b7d26fe295432e434525f1c0fae02bc \
|
||||||
|
--hash=sha256:3fe50f1cac369b02d34ad904dfe0771acc483f82a1b54c5e93632916ba847b37 \
|
||||||
|
--hash=sha256:32ab83016c24c5cf3db2943286b85b0a172dae08c58d0f53875235219b676409 \
|
||||||
|
--hash=sha256:68fb816a5dd901c6aff352ce49e2a0ffadacdf9b6fae282a69e7a16a02dad5fb \
|
||||||
|
--hash=sha256:a636160680c6e526b84f85d304e2f0bb4e94f8284dd765a1911de9a40450b10a \
|
||||||
|
--hash=sha256:bb32ca14b4d04e172c541c69eec5f385f9a075b38fb22d765d8b0ce3af3a0c22 \
|
||||||
|
--hash=sha256:6c4d7165a4e8f41eca6b990c12ee7f44fef3932fac48ca32cecb3a1b2223c21f \
|
||||||
|
--hash=sha256:a565f48c4aae72d1d3d3f8e8fb7218f5609c964e9c6f68604608e5958b9c60c3 \
|
||||||
|
--hash=sha256:fff1f3a586246110f34dc762098b5afd2de88de507559e63553d7da643053786 \
|
||||||
|
--hash=sha256:a839e25f07e428a87d17d857d9935dd743130e77ff46524abb992b962eb2076c \
|
||||||
|
--hash=sha256:6625e52b6f346a283c3d563d1fd8bae8956daafc64bb5bbd2b8f8a07608e3994 \
|
||||||
|
--hash=sha256:5bee3970617b3d74759b2d2df2f6a327d372f9732f9ccbf03fa591b5f7581e39 \
|
||||||
|
--hash=sha256:03ed2a641e412e42cc35c244508cf186015c217f0e4d496bf6d7078ebe837ae7 \
|
||||||
|
--hash=sha256:14a9f1887591684fb59fdba8feef7123a0da2424b0652e1b58dd5b9a7bb1188c \
|
||||||
|
--hash=sha256:9564ac7eb1652c3701ac691ca72934dd3009997c81266807aef924012df2f4b3 \
|
||||||
|
--hash=sha256:0f48fc7dc82ee14aeaedb986e175a429d24129b7eada1b7e94a864e4f0644dde \
|
||||||
|
--hash=sha256:107d327071061fd4f4a2587d14c389a27e4e5c93c7cba5f1f59987181903902f \
|
||||||
|
--hash=sha256:0cdde51bfcf6b6bd862ee9be324521ec619b20590787d1655d005c3fb175005f \
|
||||||
|
--hash=sha256:c67734cff78383a1f23ceba3b3239c7deefc62ac2b05fa6a47bcd565771e5880 \
|
||||||
|
--hash=sha256:c669b440ce46ae3abe9b2d44a913b5fd86bb19eb14a8701e88e3918902ecd345 \
|
||||||
|
--hash=sha256:c0ff1c1b4d13e2240821ef23c1efb1f009207cb3f56e16986f713c2b0e7cd37f \
|
||||||
|
--hash=sha256:cd601187476c6bed26a0398353212684c427e10a903aeafa6da40c63309d438b \
|
||||||
|
--hash=sha256:6d2e262e5e8da6fa56e774fb8e2643417351427604c2b177f8e8c5f75fc928ca
|
||||||
|
dataclasses==0.8; python_version >= "3.6" and python_version < "3.7" \
|
||||||
|
--hash=sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf \
|
||||||
|
--hash=sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97
|
||||||
|
django-autocomplete-light==3.8.1 \
|
||||||
|
--hash=sha256:4e84a6d95d272b0d7221614332e2bd54ffff15ec06e78947279398f6507ce225
|
||||||
|
django-bootstrap3==14.2.0; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:1fc3db37f29bcd159c0b00e1f15fd2d6dedf7551ce8bcca09072e33663c110de \
|
||||||
|
--hash=sha256:c7e6912b5127bea913bc8504399613758760954140162e048184624765e61904
|
||||||
|
django-ldapdb==1.5.1; python_version >= "3.6" \
|
||||||
|
--hash=sha256:5ea333c3130abbb86f8629766370a7f490878706469fce4e5008e41fb566392a \
|
||||||
|
--hash=sha256:2daee828a7eb1ce6ad0634ce5311339d77c08128829e575ff14d62a46771b86a
|
||||||
|
django-macaddress==1.7.0 \
|
||||||
|
--hash=sha256:342aa3421ee19acc3661d1705dad2ae674eaa7d06a02799f7a5dc394d6233275 \
|
||||||
|
--hash=sha256:db8beedcbd708aba3a6c9e83de6527efa2f9cc7dbe698406cebdfdbaf98c896d
|
||||||
|
django-rest-framework==0.1.0 \
|
||||||
|
--hash=sha256:47a8f496fa69e3b6bd79f68dd7a1527d907d6b77f009e9db7cf9bb21cc565e4a
|
||||||
|
django-reversion==3.0.9; python_version >= "3.6" \
|
||||||
|
--hash=sha256:a5af55f086a3f9c38be2f049c251e06005b9ed48ba7a109473736b1fc95a066f \
|
||||||
|
--hash=sha256:1b57127a136b969f4b843a915c72af271febe7f336469db6c27121f8adcad35c
|
||||||
|
django==2.2.18; python_version >= "3.5" \
|
||||||
|
--hash=sha256:0eaca08f236bf502a9773e53623f766cc3ceee6453cc41e6de1c8b80f07d2364 \
|
||||||
|
--hash=sha256:c9c994f5e0a032cbd45089798b52e4080f4dea7241c58e3e0636c54146480bb4
|
||||||
|
djangorestframework==3.12.2; python_version >= "3.5" \
|
||||||
|
--hash=sha256:0209bafcb7b5010fdfec784034f059d512256424de2a0f084cb82b096d6dd6a7 \
|
||||||
|
--hash=sha256:0898182b4737a7b584a2c73735d89816343369f259fea932d90dc78e35d8ac33
|
||||||
|
docstr-coverage==2.0.0 \
|
||||||
|
--hash=sha256:c5ff8d81128d2f56204fc9ecbb9c410cb18b654438d1b104868abb6ef400767e \
|
||||||
|
--hash=sha256:ee2c043ccbc6d1847cd93616acf4ebb3e7bc53ea84434111efddae9b69f3737a
|
||||||
|
docutils==0.16; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af \
|
||||||
|
--hash=sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc
|
||||||
|
gitdb==4.0.5; python_version >= "3.4" \
|
||||||
|
--hash=sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac \
|
||||||
|
--hash=sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9
|
||||||
|
gitpython==3.1.13; python_version >= "3.4" \
|
||||||
|
--hash=sha256:c5347c81d232d9b8e7f47b68a83e5dc92e7952127133c5f2df9133f2c75a1b29 \
|
||||||
|
--hash=sha256:8621a7e777e276a5ec838b59280ba5272dd144a18169c36c903d8b38b99f750a
|
||||||
|
idna==2.10; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0 \
|
||||||
|
--hash=sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6
|
||||||
|
imagesize==1.2.0; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1 \
|
||||||
|
--hash=sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1
|
||||||
|
importlib-metadata==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_version >= "3.6" and python_version < "3.8" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070 \
|
||||||
|
--hash=sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83
|
||||||
|
importlib-resources==5.1.0; python_version >= "3.6" and python_version < "3.7" \
|
||||||
|
--hash=sha256:885b8eae589179f661c909d699a546cf10d83692553e34dca1bf5eb06f7f6217 \
|
||||||
|
--hash=sha256:bfdad047bce441405a49cf8eb48ddce5e56c696e185f59147a8b79e75e9e6380
|
||||||
|
jinja2==2.11.3; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419 \
|
||||||
|
--hash=sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6
|
||||||
|
markupsafe==1.1.1; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \
|
||||||
|
--hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \
|
||||||
|
--hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \
|
||||||
|
--hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \
|
||||||
|
--hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \
|
||||||
|
--hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \
|
||||||
|
--hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \
|
||||||
|
--hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \
|
||||||
|
--hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \
|
||||||
|
--hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \
|
||||||
|
--hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \
|
||||||
|
--hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \
|
||||||
|
--hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \
|
||||||
|
--hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \
|
||||||
|
--hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \
|
||||||
|
--hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \
|
||||||
|
--hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \
|
||||||
|
--hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \
|
||||||
|
--hash=sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5 \
|
||||||
|
--hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \
|
||||||
|
--hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \
|
||||||
|
--hash=sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f \
|
||||||
|
--hash=sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0 \
|
||||||
|
--hash=sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7 \
|
||||||
|
--hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \
|
||||||
|
--hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \
|
||||||
|
--hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \
|
||||||
|
--hash=sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193 \
|
||||||
|
--hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \
|
||||||
|
--hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \
|
||||||
|
--hash=sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1 \
|
||||||
|
--hash=sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1 \
|
||||||
|
--hash=sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f \
|
||||||
|
--hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \
|
||||||
|
--hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \
|
||||||
|
--hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \
|
||||||
|
--hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \
|
||||||
|
--hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \
|
||||||
|
--hash=sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2 \
|
||||||
|
--hash=sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032 \
|
||||||
|
--hash=sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b \
|
||||||
|
--hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \
|
||||||
|
--hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be \
|
||||||
|
--hash=sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c \
|
||||||
|
--hash=sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb \
|
||||||
|
--hash=sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014 \
|
||||||
|
--hash=sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850 \
|
||||||
|
--hash=sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85 \
|
||||||
|
--hash=sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621 \
|
||||||
|
--hash=sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39 \
|
||||||
|
--hash=sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8 \
|
||||||
|
--hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b
|
||||||
|
mypy-extensions==0.4.3; python_version >= "3.6" \
|
||||||
|
--hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \
|
||||||
|
--hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8
|
||||||
|
mysqlclient==2.0.3; python_version >= "3.5" \
|
||||||
|
--hash=sha256:3381ca1a4f37ff1155fcfde20836b46416d66531add8843f6aa6d968982731c3 \
|
||||||
|
--hash=sha256:0ac0dd759c4ca02c35a9fedc24bc982cf75171651e8187c2495ec957a87dfff7 \
|
||||||
|
--hash=sha256:71c4b330cf2313bbda0307fc858cc9055e64493ba9bf28454d25cf8b3ee8d7f5 \
|
||||||
|
--hash=sha256:fc575093cf81b6605bed84653e48b277318b880dc9becf42dd47fa11ffd3e2b6 \
|
||||||
|
--hash=sha256:f6ebea7c008f155baeefe16c56cd3ee6239f7a5a9ae42396c2f1860f08a7c432
|
||||||
|
netaddr==0.8.0 \
|
||||||
|
--hash=sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac \
|
||||||
|
--hash=sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243
|
||||||
|
packaging==20.9; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a \
|
||||||
|
--hash=sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5
|
||||||
|
pathspec==0.8.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d \
|
||||||
|
--hash=sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd
|
||||||
|
pillow==8.1.0; python_version >= "3.6" \
|
||||||
|
--hash=sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a \
|
||||||
|
--hash=sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2 \
|
||||||
|
--hash=sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174 \
|
||||||
|
--hash=sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded \
|
||||||
|
--hash=sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d \
|
||||||
|
--hash=sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d \
|
||||||
|
--hash=sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234 \
|
||||||
|
--hash=sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8 \
|
||||||
|
--hash=sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17 \
|
||||||
|
--hash=sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7 \
|
||||||
|
--hash=sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e \
|
||||||
|
--hash=sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b \
|
||||||
|
--hash=sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0 \
|
||||||
|
--hash=sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a \
|
||||||
|
--hash=sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d \
|
||||||
|
--hash=sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae \
|
||||||
|
--hash=sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59 \
|
||||||
|
--hash=sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c \
|
||||||
|
--hash=sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6 \
|
||||||
|
--hash=sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378 \
|
||||||
|
--hash=sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7 \
|
||||||
|
--hash=sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0 \
|
||||||
|
--hash=sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b \
|
||||||
|
--hash=sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865 \
|
||||||
|
--hash=sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9 \
|
||||||
|
--hash=sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913 \
|
||||||
|
--hash=sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206 \
|
||||||
|
--hash=sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9 \
|
||||||
|
--hash=sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032 \
|
||||||
|
--hash=sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820 \
|
||||||
|
--hash=sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5 \
|
||||||
|
--hash=sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba
|
||||||
|
psycopg2==2.8.6; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \
|
||||||
|
--hash=sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725 \
|
||||||
|
--hash=sha256:d160744652e81c80627a909a0e808f3c6653a40af435744de037e3172cf277f5 \
|
||||||
|
--hash=sha256:b8cae8b2f022efa1f011cc753adb9cbadfa5a184431d09b273fb49b4167561ad \
|
||||||
|
--hash=sha256:f22ea9b67aea4f4a1718300908a2fb62b3e4276cf00bd829a97ab5894af42ea3 \
|
||||||
|
--hash=sha256:26e7fd115a6db75267b325de0fba089b911a4a12ebd3d0b5e7acb7028bc46821 \
|
||||||
|
--hash=sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301 \
|
||||||
|
--hash=sha256:a49833abfdede8985ba3f3ec641f771cca215479f41523e99dace96d5b8cce2a \
|
||||||
|
--hash=sha256:f974c96fca34ae9e4f49839ba6b78addf0346777b46c4da27a7bf54f48d3057d \
|
||||||
|
--hash=sha256:6a3d9efb6f36f1fe6aa8dbb5af55e067db802502c55a9defa47c5a1dad41df84 \
|
||||||
|
--hash=sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5 \
|
||||||
|
--hash=sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e \
|
||||||
|
--hash=sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051 \
|
||||||
|
--hash=sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3 \
|
||||||
|
--hash=sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7 \
|
||||||
|
--hash=sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543
|
||||||
|
pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
|
||||||
|
--hash=sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199 \
|
||||||
|
--hash=sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405 \
|
||||||
|
--hash=sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb \
|
||||||
|
--hash=sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8 \
|
||||||
|
--hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74 \
|
||||||
|
--hash=sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d \
|
||||||
|
--hash=sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45 \
|
||||||
|
--hash=sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4 \
|
||||||
|
--hash=sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811 \
|
||||||
|
--hash=sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed \
|
||||||
|
--hash=sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0 \
|
||||||
|
--hash=sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd
|
||||||
|
pyasn1==0.4.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3 \
|
||||||
|
--hash=sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf \
|
||||||
|
--hash=sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00 \
|
||||||
|
--hash=sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8 \
|
||||||
|
--hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
|
||||||
|
--hash=sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86 \
|
||||||
|
--hash=sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7 \
|
||||||
|
--hash=sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576 \
|
||||||
|
--hash=sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12 \
|
||||||
|
--hash=sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2 \
|
||||||
|
--hash=sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359 \
|
||||||
|
--hash=sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776 \
|
||||||
|
--hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
|
||||||
|
pycrypto==2.6.1 \
|
||||||
|
--hash=sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c
|
||||||
|
pygments==2.7.4; python_version >= "3.5" \
|
||||||
|
--hash=sha256:bc9591213a8f0e0ca1a5e68a479b4887fdc3e75d0774e5c71c31920c427de435 \
|
||||||
|
--hash=sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337
|
||||||
|
pyparsing==2.4.7; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \
|
||||||
|
--hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1
|
||||||
|
python-dateutil==2.8.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0") \
|
||||||
|
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
|
||||||
|
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a
|
||||||
|
python-ldap==3.3.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:4711cacf013e298754abd70058ccc995758177fb425f1c2d30e71adfc1d00aa5
|
||||||
|
pytz==2021.1; python_version >= "3.6" and python_version < "4.0" and (python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5") \
|
||||||
|
--hash=sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798 \
|
||||||
|
--hash=sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da
|
||||||
|
pyyaml==5.4.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" \
|
||||||
|
--hash=sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922 \
|
||||||
|
--hash=sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393 \
|
||||||
|
--hash=sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8 \
|
||||||
|
--hash=sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185 \
|
||||||
|
--hash=sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253 \
|
||||||
|
--hash=sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc \
|
||||||
|
--hash=sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5 \
|
||||||
|
--hash=sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df \
|
||||||
|
--hash=sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018 \
|
||||||
|
--hash=sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63 \
|
||||||
|
--hash=sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b \
|
||||||
|
--hash=sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf \
|
||||||
|
--hash=sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46 \
|
||||||
|
--hash=sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb \
|
||||||
|
--hash=sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc \
|
||||||
|
--hash=sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696 \
|
||||||
|
--hash=sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77 \
|
||||||
|
--hash=sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183 \
|
||||||
|
--hash=sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10 \
|
||||||
|
--hash=sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db \
|
||||||
|
--hash=sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e
|
||||||
|
regex==2020.11.13; python_version >= "3.6" \
|
||||||
|
--hash=sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85 \
|
||||||
|
--hash=sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70 \
|
||||||
|
--hash=sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee \
|
||||||
|
--hash=sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5 \
|
||||||
|
--hash=sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7 \
|
||||||
|
--hash=sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31 \
|
||||||
|
--hash=sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa \
|
||||||
|
--hash=sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6 \
|
||||||
|
--hash=sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e \
|
||||||
|
--hash=sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884 \
|
||||||
|
--hash=sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b \
|
||||||
|
--hash=sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88 \
|
||||||
|
--hash=sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0 \
|
||||||
|
--hash=sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1 \
|
||||||
|
--hash=sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0 \
|
||||||
|
--hash=sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512 \
|
||||||
|
--hash=sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba \
|
||||||
|
--hash=sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538 \
|
||||||
|
--hash=sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4 \
|
||||||
|
--hash=sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444 \
|
||||||
|
--hash=sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f \
|
||||||
|
--hash=sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d \
|
||||||
|
--hash=sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af \
|
||||||
|
--hash=sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f \
|
||||||
|
--hash=sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b \
|
||||||
|
--hash=sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8 \
|
||||||
|
--hash=sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5 \
|
||||||
|
--hash=sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b \
|
||||||
|
--hash=sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c \
|
||||||
|
--hash=sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683 \
|
||||||
|
--hash=sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc \
|
||||||
|
--hash=sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364 \
|
||||||
|
--hash=sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e \
|
||||||
|
--hash=sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e \
|
||||||
|
--hash=sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917 \
|
||||||
|
--hash=sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b \
|
||||||
|
--hash=sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9 \
|
||||||
|
--hash=sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c \
|
||||||
|
--hash=sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f \
|
||||||
|
--hash=sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d \
|
||||||
|
--hash=sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562
|
||||||
|
requests==2.25.1; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e \
|
||||||
|
--hash=sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804
|
||||||
|
rope==0.18.0 \
|
||||||
|
--hash=sha256:786b5c38c530d4846aa68a42604f61b4e69a493390e3ca11b88df0fbfdc3ed04
|
||||||
|
six==1.15.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" \
|
||||||
|
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced \
|
||||||
|
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259
|
||||||
|
smmap==3.0.5; python_version >= "3.4" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.4" \
|
||||||
|
--hash=sha256:7bfcf367828031dc893530a29cb35eb8c8f2d7c8f2d0989354d75d24c8573714 \
|
||||||
|
--hash=sha256:84c2751ef3072d4f6b2785ec7ee40244c6f45eb934d9e543e2c51f1bd3d54c50
|
||||||
|
snowballstemmer==2.1.0; python_version >= "3.5" \
|
||||||
|
--hash=sha256:b51b447bea85f9968c13b650126a888aabd4cb4463fca868ec596826325dedc2 \
|
||||||
|
--hash=sha256:e997baa4f2e9139951b6f4c631bad912dfd3c792467e2f03d7239464af90e914
|
||||||
|
sphinx-rtd-theme==0.5.1 \
|
||||||
|
--hash=sha256:fa6bebd5ab9a73da8e102509a86f3fcc36dec04a0b52ea80e5a033b2aba00113 \
|
||||||
|
--hash=sha256:eda689eda0c7301a80cf122dad28b1861e5605cbf455558f3775e1e8200e83a5
|
||||||
|
sphinx==3.4.3; python_version >= "3.5" \
|
||||||
|
--hash=sha256:c314c857e7cd47c856d2c5adff514ac2e6495f8b8e0f886a8a37e9305dfea0d8 \
|
||||||
|
--hash=sha256:41cad293f954f7d37f803d97eb184158cfd90f51195131e94875bc07cd08b93c
|
||||||
|
sphinxcontrib-applehelp==1.0.2; python_version >= "3.5" \
|
||||||
|
--hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58 \
|
||||||
|
--hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a
|
||||||
|
sphinxcontrib-devhelp==1.0.2; python_version >= "3.5" \
|
||||||
|
--hash=sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4 \
|
||||||
|
--hash=sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e
|
||||||
|
sphinxcontrib-htmlhelp==1.0.3; python_version >= "3.5" \
|
||||||
|
--hash=sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b \
|
||||||
|
--hash=sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f
|
||||||
|
sphinxcontrib-jsmath==1.0.1; python_version >= "3.5" \
|
||||||
|
--hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8 \
|
||||||
|
--hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178
|
||||||
|
sphinxcontrib-qthelp==1.0.3; python_version >= "3.5" \
|
||||||
|
--hash=sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72 \
|
||||||
|
--hash=sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6
|
||||||
|
sphinxcontrib-serializinghtml==1.1.4; python_version >= "3.5" \
|
||||||
|
--hash=sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc \
|
||||||
|
--hash=sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a
|
||||||
|
sqlparse==0.4.1; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0 \
|
||||||
|
--hash=sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8
|
||||||
|
toml==0.10.2; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \
|
||||||
|
--hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f
|
||||||
|
typed-ast==1.4.2; python_version >= "3.6" \
|
||||||
|
--hash=sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70 \
|
||||||
|
--hash=sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487 \
|
||||||
|
--hash=sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412 \
|
||||||
|
--hash=sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400 \
|
||||||
|
--hash=sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606 \
|
||||||
|
--hash=sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64 \
|
||||||
|
--hash=sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07 \
|
||||||
|
--hash=sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc \
|
||||||
|
--hash=sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a \
|
||||||
|
--hash=sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151 \
|
||||||
|
--hash=sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3 \
|
||||||
|
--hash=sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41 \
|
||||||
|
--hash=sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f \
|
||||||
|
--hash=sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581 \
|
||||||
|
--hash=sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37 \
|
||||||
|
--hash=sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd \
|
||||||
|
--hash=sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496 \
|
||||||
|
--hash=sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc \
|
||||||
|
--hash=sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10 \
|
||||||
|
--hash=sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea \
|
||||||
|
--hash=sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787 \
|
||||||
|
--hash=sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2 \
|
||||||
|
--hash=sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937 \
|
||||||
|
--hash=sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1 \
|
||||||
|
--hash=sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6 \
|
||||||
|
--hash=sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166 \
|
||||||
|
--hash=sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d \
|
||||||
|
--hash=sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b \
|
||||||
|
--hash=sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440 \
|
||||||
|
--hash=sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a
|
||||||
|
typing-extensions==3.7.4.3; python_version >= "3.6" \
|
||||||
|
--hash=sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f \
|
||||||
|
--hash=sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918 \
|
||||||
|
--hash=sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c
|
||||||
|
urllib3==1.26.3; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" and python_version >= "3.5" \
|
||||||
|
--hash=sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80 \
|
||||||
|
--hash=sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73
|
||||||
|
zipp==3.4.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108 \
|
||||||
|
--hash=sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb
|
|
@ -34,12 +34,12 @@ https://github.com/FreeRADIUS/freeradius-server/blob/master/src/modules/rlm_pyth
|
||||||
Inspired by Daniel Stan in Crans
|
Inspired by Daniel Stan in Crans
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import logging
|
|
||||||
import traceback
|
import traceback
|
||||||
import radiusd # Magic module freeradius (radiusd.py is dummy)
|
|
||||||
|
|
||||||
|
import radiusd # Magic module freeradius (radiusd.py is dummy)
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
|
@ -54,11 +54,10 @@ os.chdir(proj_path)
|
||||||
# This is so models get loaded.
|
# This is so models get loaded.
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
|
|
||||||
from machines.models import Interface, IpList, Nas, Domain
|
from machines.models import Domain, Interface, IpList, Nas
|
||||||
|
from preferences.models import RadiusOption
|
||||||
from topologie.models import Port, Switch
|
from topologie.models import Port, Switch
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from preferences.models import RadiusOption
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
|
@ -162,8 +161,7 @@ def authorize(data):
|
||||||
|
|
||||||
@radius_event
|
@radius_event
|
||||||
def post_auth(data):
|
def post_auth(data):
|
||||||
""" Function called after the user is authenticated
|
"""Function called after the user is authenticated"""
|
||||||
"""
|
|
||||||
|
|
||||||
nas = data.get("NAS-IP-Address", data.get("NAS-Identifier", None))
|
nas = data.get("NAS-IP-Address", data.get("NAS-Identifier", None))
|
||||||
nas_instance = find_nas_from_request(nas)
|
nas_instance = find_nas_from_request(nas)
|
||||||
|
|
142
ldap-requirements.txt
Normal file
142
ldap-requirements.txt
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
django-autocomplete-light==3.8.1 \
|
||||||
|
--hash=sha256:4e84a6d95d272b0d7221614332e2bd54ffff15ec06e78947279398f6507ce225
|
||||||
|
django-bootstrap3==14.2.0; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:1fc3db37f29bcd159c0b00e1f15fd2d6dedf7551ce8bcca09072e33663c110de \
|
||||||
|
--hash=sha256:c7e6912b5127bea913bc8504399613758760954140162e048184624765e61904
|
||||||
|
django-ldapdb==1.5.1; python_version >= "3.6" \
|
||||||
|
--hash=sha256:5ea333c3130abbb86f8629766370a7f490878706469fce4e5008e41fb566392a \
|
||||||
|
--hash=sha256:2daee828a7eb1ce6ad0634ce5311339d77c08128829e575ff14d62a46771b86a
|
||||||
|
django-macaddress==1.7.0 \
|
||||||
|
--hash=sha256:342aa3421ee19acc3661d1705dad2ae674eaa7d06a02799f7a5dc394d6233275 \
|
||||||
|
--hash=sha256:db8beedcbd708aba3a6c9e83de6527efa2f9cc7dbe698406cebdfdbaf98c896d
|
||||||
|
django-rest-framework==0.1.0 \
|
||||||
|
--hash=sha256:47a8f496fa69e3b6bd79f68dd7a1527d907d6b77f009e9db7cf9bb21cc565e4a
|
||||||
|
django-reversion==3.0.9; python_version >= "3.6" \
|
||||||
|
--hash=sha256:a5af55f086a3f9c38be2f049c251e06005b9ed48ba7a109473736b1fc95a066f \
|
||||||
|
--hash=sha256:1b57127a136b969f4b843a915c72af271febe7f336469db6c27121f8adcad35c
|
||||||
|
django==2.2.18; python_version >= "3.5" \
|
||||||
|
--hash=sha256:0eaca08f236bf502a9773e53623f766cc3ceee6453cc41e6de1c8b80f07d2364 \
|
||||||
|
--hash=sha256:c9c994f5e0a032cbd45089798b52e4080f4dea7241c58e3e0636c54146480bb4
|
||||||
|
djangorestframework==3.12.2; python_version >= "3.5" \
|
||||||
|
--hash=sha256:0209bafcb7b5010fdfec784034f059d512256424de2a0f084cb82b096d6dd6a7 \
|
||||||
|
--hash=sha256:0898182b4737a7b584a2c73735d89816343369f259fea932d90dc78e35d8ac33
|
||||||
|
gitdb==4.0.5; python_version >= "3.4" \
|
||||||
|
--hash=sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac \
|
||||||
|
--hash=sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9
|
||||||
|
gitpython==3.1.13; python_version >= "3.4" \
|
||||||
|
--hash=sha256:c5347c81d232d9b8e7f47b68a83e5dc92e7952127133c5f2df9133f2c75a1b29 \
|
||||||
|
--hash=sha256:8621a7e777e276a5ec838b59280ba5272dd144a18169c36c903d8b38b99f750a
|
||||||
|
importlib-metadata==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_version >= "3.6" and python_version < "3.8" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070 \
|
||||||
|
--hash=sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83
|
||||||
|
importlib-resources==5.1.0; python_version >= "3.6" and python_version < "3.7" \
|
||||||
|
--hash=sha256:885b8eae589179f661c909d699a546cf10d83692553e34dca1bf5eb06f7f6217 \
|
||||||
|
--hash=sha256:bfdad047bce441405a49cf8eb48ddce5e56c696e185f59147a8b79e75e9e6380
|
||||||
|
mysqlclient==2.0.3; python_version >= "3.5" \
|
||||||
|
--hash=sha256:3381ca1a4f37ff1155fcfde20836b46416d66531add8843f6aa6d968982731c3 \
|
||||||
|
--hash=sha256:0ac0dd759c4ca02c35a9fedc24bc982cf75171651e8187c2495ec957a87dfff7 \
|
||||||
|
--hash=sha256:71c4b330cf2313bbda0307fc858cc9055e64493ba9bf28454d25cf8b3ee8d7f5 \
|
||||||
|
--hash=sha256:fc575093cf81b6605bed84653e48b277318b880dc9becf42dd47fa11ffd3e2b6 \
|
||||||
|
--hash=sha256:f6ebea7c008f155baeefe16c56cd3ee6239f7a5a9ae42396c2f1860f08a7c432
|
||||||
|
netaddr==0.8.0 \
|
||||||
|
--hash=sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac \
|
||||||
|
--hash=sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243
|
||||||
|
pillow==8.1.0; python_version >= "3.6" \
|
||||||
|
--hash=sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a \
|
||||||
|
--hash=sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2 \
|
||||||
|
--hash=sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174 \
|
||||||
|
--hash=sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded \
|
||||||
|
--hash=sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d \
|
||||||
|
--hash=sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d \
|
||||||
|
--hash=sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234 \
|
||||||
|
--hash=sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8 \
|
||||||
|
--hash=sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17 \
|
||||||
|
--hash=sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7 \
|
||||||
|
--hash=sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e \
|
||||||
|
--hash=sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b \
|
||||||
|
--hash=sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0 \
|
||||||
|
--hash=sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a \
|
||||||
|
--hash=sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d \
|
||||||
|
--hash=sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae \
|
||||||
|
--hash=sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59 \
|
||||||
|
--hash=sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c \
|
||||||
|
--hash=sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6 \
|
||||||
|
--hash=sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378 \
|
||||||
|
--hash=sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7 \
|
||||||
|
--hash=sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0 \
|
||||||
|
--hash=sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b \
|
||||||
|
--hash=sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865 \
|
||||||
|
--hash=sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9 \
|
||||||
|
--hash=sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913 \
|
||||||
|
--hash=sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206 \
|
||||||
|
--hash=sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9 \
|
||||||
|
--hash=sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032 \
|
||||||
|
--hash=sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820 \
|
||||||
|
--hash=sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5 \
|
||||||
|
--hash=sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba
|
||||||
|
psycopg2==2.8.6; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \
|
||||||
|
--hash=sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725 \
|
||||||
|
--hash=sha256:d160744652e81c80627a909a0e808f3c6653a40af435744de037e3172cf277f5 \
|
||||||
|
--hash=sha256:b8cae8b2f022efa1f011cc753adb9cbadfa5a184431d09b273fb49b4167561ad \
|
||||||
|
--hash=sha256:f22ea9b67aea4f4a1718300908a2fb62b3e4276cf00bd829a97ab5894af42ea3 \
|
||||||
|
--hash=sha256:26e7fd115a6db75267b325de0fba089b911a4a12ebd3d0b5e7acb7028bc46821 \
|
||||||
|
--hash=sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301 \
|
||||||
|
--hash=sha256:a49833abfdede8985ba3f3ec641f771cca215479f41523e99dace96d5b8cce2a \
|
||||||
|
--hash=sha256:f974c96fca34ae9e4f49839ba6b78addf0346777b46c4da27a7bf54f48d3057d \
|
||||||
|
--hash=sha256:6a3d9efb6f36f1fe6aa8dbb5af55e067db802502c55a9defa47c5a1dad41df84 \
|
||||||
|
--hash=sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5 \
|
||||||
|
--hash=sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e \
|
||||||
|
--hash=sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051 \
|
||||||
|
--hash=sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3 \
|
||||||
|
--hash=sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7 \
|
||||||
|
--hash=sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543
|
||||||
|
pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
|
||||||
|
--hash=sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199 \
|
||||||
|
--hash=sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405 \
|
||||||
|
--hash=sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb \
|
||||||
|
--hash=sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8 \
|
||||||
|
--hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74 \
|
||||||
|
--hash=sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d \
|
||||||
|
--hash=sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45 \
|
||||||
|
--hash=sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4 \
|
||||||
|
--hash=sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811 \
|
||||||
|
--hash=sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed \
|
||||||
|
--hash=sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0 \
|
||||||
|
--hash=sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd
|
||||||
|
pyasn1==0.4.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3 \
|
||||||
|
--hash=sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf \
|
||||||
|
--hash=sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00 \
|
||||||
|
--hash=sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8 \
|
||||||
|
--hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
|
||||||
|
--hash=sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86 \
|
||||||
|
--hash=sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7 \
|
||||||
|
--hash=sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576 \
|
||||||
|
--hash=sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12 \
|
||||||
|
--hash=sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2 \
|
||||||
|
--hash=sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359 \
|
||||||
|
--hash=sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776 \
|
||||||
|
--hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
|
||||||
|
pycrypto==2.6.1 \
|
||||||
|
--hash=sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c
|
||||||
|
python-dateutil==2.8.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0") \
|
||||||
|
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
|
||||||
|
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a
|
||||||
|
python-ldap==3.3.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:4711cacf013e298754abd70058ccc995758177fb425f1c2d30e71adfc1d00aa5
|
||||||
|
pytz==2021.1; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798 \
|
||||||
|
--hash=sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da
|
||||||
|
six==1.15.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" \
|
||||||
|
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced \
|
||||||
|
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259
|
||||||
|
smmap==3.0.5; python_version >= "3.4" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.4" \
|
||||||
|
--hash=sha256:7bfcf367828031dc893530a29cb35eb8c8f2d7c8f2d0989354d75d24c8573714 \
|
||||||
|
--hash=sha256:84c2751ef3072d4f6b2785ec7ee40244c6f45eb934d9e543e2c51f1bd3d54c50
|
||||||
|
sqlparse==0.4.1; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0 \
|
||||||
|
--hash=sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8
|
||||||
|
zipp==3.4.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108 \
|
||||||
|
--hash=sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb
|
|
@ -1,11 +1,8 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import (
|
from .models import (LdapServiceUser, LdapServiceUserGroup, LdapUser,
|
||||||
LdapUser,
|
LdapUserGroup)
|
||||||
LdapServiceUser,
|
|
||||||
LdapServiceUserGroup,
|
|
||||||
LdapUserGroup,
|
|
||||||
)
|
|
||||||
|
|
||||||
class LdapUserAdmin(admin.ModelAdmin):
|
class LdapUserAdmin(admin.ModelAdmin):
|
||||||
"""LdapUser Admin view. Can't change password, manage
|
"""LdapUser Admin view. Can't change password, manage
|
||||||
|
@ -15,6 +12,7 @@ class LdapUserAdmin(admin.ModelAdmin):
|
||||||
Django ModelAdmin: Apply on django ModelAdmin
|
Django ModelAdmin: Apply on django ModelAdmin
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
list_display = ("name", "uidNumber", "login_shell")
|
list_display = ("name", "uidNumber", "login_shell")
|
||||||
exclude = ("user_password", "sambat_nt_password")
|
exclude = ("user_password", "sambat_nt_password")
|
||||||
search_fields = ("name",)
|
search_fields = ("name",)
|
||||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class LdapSyncConfig(AppConfig):
|
class LdapSyncConfig(AppConfig):
|
||||||
name = 'ldap_sync'
|
name = "ldap_sync"
|
||||||
|
|
|
@ -18,11 +18,12 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
from base64 import decodebytes
|
from base64 import decodebytes
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
from users.models import User, ListRight
|
from ldap_sync.models import (synchronise_serviceuser, synchronise_user,
|
||||||
from ldap_sync.models import synchronise_user, synchronise_serviceuser, synchronise_usergroup
|
synchronise_usergroup)
|
||||||
|
from users.models import ListRight, User
|
||||||
|
|
||||||
|
|
||||||
def split_lines(lines):
|
def split_lines(lines):
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
#
|
#
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
|
||||||
from users.models import User
|
|
||||||
from ldap_sync.models import synchronise_user
|
from ldap_sync.models import synchronise_user
|
||||||
|
from users.models import User
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from django.db import models
|
|
||||||
from django.conf import settings
|
|
||||||
from django.dispatch import receiver
|
|
||||||
|
|
||||||
from django.contrib.auth.models import Group
|
|
||||||
|
|
||||||
import ldapdb.models
|
import ldapdb.models
|
||||||
import ldapdb.models.fields
|
import ldapdb.models.fields
|
||||||
|
from django.conf import settings
|
||||||
import users.signals
|
from django.contrib.auth.models import Group
|
||||||
import users.models
|
from django.db import models
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
import machines.models
|
import machines.models
|
||||||
|
import users.models
|
||||||
|
import users.signals
|
||||||
|
|
||||||
|
|
||||||
class LdapUser(ldapdb.models.Model):
|
class LdapUser(ldapdb.models.Model):
|
||||||
"""A class representing a LdapUser in LDAP, its LDAP conterpart.
|
"""A class representing a LdapUser in LDAP, its LDAP conterpart.
|
||||||
|
@ -110,12 +108,12 @@ def synchronise_user(sender, **kwargs):
|
||||||
* mac_refresh : Default `True`. When True, synchronise the list of mac addresses.
|
* mac_refresh : Default `True`. When True, synchronise the list of mac addresses.
|
||||||
* group_refresh: Default `False`. When `True` synchronise the groups of the instance.
|
* group_refresh: Default `False`. When `True` synchronise the groups of the instance.
|
||||||
"""
|
"""
|
||||||
base=kwargs.get('base', True)
|
base = kwargs.get("base", True)
|
||||||
access_refresh=kwargs.get('access_refresh', True)
|
access_refresh = kwargs.get("access_refresh", True)
|
||||||
mac_refresh=kwargs.get('mac_refresh', True )
|
mac_refresh = kwargs.get("mac_refresh", True)
|
||||||
group_refresh=kwargs.get('group_refresh', False)
|
group_refresh = kwargs.get("group_refresh", False)
|
||||||
|
|
||||||
user=kwargs["instance"]
|
user = kwargs["instance"]
|
||||||
|
|
||||||
if sys.version_info[0] >= 3 and (
|
if sys.version_info[0] >= 3 and (
|
||||||
user.state == user.STATE_ACTIVE
|
user.state == user.STATE_ACTIVE
|
||||||
|
@ -136,9 +134,7 @@ def synchronise_user(sender, **kwargs):
|
||||||
user_ldap.dialupAccess = str(user.has_access())
|
user_ldap.dialupAccess = str(user.has_access())
|
||||||
user_ldap.home_directory = user.home_directory
|
user_ldap.home_directory = user.home_directory
|
||||||
user_ldap.mail = user.get_mail
|
user_ldap.mail = user.get_mail
|
||||||
user_ldap.given_name = (
|
user_ldap.given_name = user.surname.lower() + "_" + user.name.lower()[:3]
|
||||||
user.surname.lower() + "_" + user.name.lower()[:3]
|
|
||||||
)
|
|
||||||
user_ldap.gid = settings.LDAP["user_gid"]
|
user_ldap.gid = settings.LDAP["user_gid"]
|
||||||
if "{SSHA}" in user.password or "{SMD5}" in user.password:
|
if "{SSHA}" in user.password or "{SMD5}" in user.password:
|
||||||
# We remove the extra $ added at import from ldap
|
# We remove the extra $ added at import from ldap
|
||||||
|
@ -169,9 +165,12 @@ def synchronise_user(sender, **kwargs):
|
||||||
# be part of the updated group (case of group removal)
|
# be part of the updated group (case of group removal)
|
||||||
for group in Group.objects.all():
|
for group in Group.objects.all():
|
||||||
if hasattr(group, "listright"):
|
if hasattr(group, "listright"):
|
||||||
synchronise_usergroup(users.models.ListRight, instance=group.listright)
|
synchronise_usergroup(
|
||||||
|
users.models.ListRight, instance=group.listright
|
||||||
|
)
|
||||||
user_ldap.save()
|
user_ldap.save()
|
||||||
|
|
||||||
|
|
||||||
@receiver(users.signals.remove, sender=users.models.User)
|
@receiver(users.signals.remove, sender=users.models.User)
|
||||||
def remove_user(sender, **kwargs):
|
def remove_user(sender, **kwargs):
|
||||||
user = kwargs["instance"]
|
user = kwargs["instance"]
|
||||||
|
@ -181,6 +180,7 @@ def remove_user(sender, **kwargs):
|
||||||
except LdapUser.DoesNotExist:
|
except LdapUser.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@receiver(users.signals.remove_mass, sender=users.models.User)
|
@receiver(users.signals.remove_mass, sender=users.models.User)
|
||||||
def remove_users(sender, **kwargs):
|
def remove_users(sender, **kwargs):
|
||||||
queryset_users = kwargs["queryset"]
|
queryset_users = kwargs["queryset"]
|
||||||
|
@ -217,6 +217,7 @@ class LdapUserGroup(ldapdb.models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
@receiver(users.signals.synchronise, sender=users.models.ListRight)
|
@receiver(users.signals.synchronise, sender=users.models.ListRight)
|
||||||
def synchronise_usergroup(sender, **kwargs):
|
def synchronise_usergroup(sender, **kwargs):
|
||||||
group = kwargs["instance"]
|
group = kwargs["instance"]
|
||||||
|
@ -228,6 +229,7 @@ def synchronise_usergroup(sender, **kwargs):
|
||||||
group_ldap.members = [user.pseudo for user in group.user_set.all()]
|
group_ldap.members = [user.pseudo for user in group.user_set.all()]
|
||||||
group_ldap.save()
|
group_ldap.save()
|
||||||
|
|
||||||
|
|
||||||
@receiver(users.signals.remove, sender=users.models.ListRight)
|
@receiver(users.signals.remove, sender=users.models.ListRight)
|
||||||
def remove_usergroup(sender, **kwargs):
|
def remove_usergroup(sender, **kwargs):
|
||||||
group = kwargs["instance"]
|
group = kwargs["instance"]
|
||||||
|
@ -238,7 +240,6 @@ def remove_usergroup(sender, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LdapServiceUser(ldapdb.models.Model):
|
class LdapServiceUser(ldapdb.models.Model):
|
||||||
"""A class representing a ServiceUser in LDAP, its LDAP conterpart.
|
"""A class representing a ServiceUser in LDAP, its LDAP conterpart.
|
||||||
Synced from ServiceUser, with a copy of its attributes/fields into LDAP,
|
Synced from ServiceUser, with a copy of its attributes/fields into LDAP,
|
||||||
|
@ -296,6 +297,7 @@ def synchronise_serviceuser(sender, **kwargs):
|
||||||
user_ldap.save()
|
user_ldap.save()
|
||||||
synchronise_serviceuser_group(user)
|
synchronise_serviceuser_group(user)
|
||||||
|
|
||||||
|
|
||||||
@receiver(users.signals.remove, sender=users.models.ServiceUser)
|
@receiver(users.signals.remove, sender=users.models.ServiceUser)
|
||||||
def remove_serviceuser(sender, **kwargs):
|
def remove_serviceuser(sender, **kwargs):
|
||||||
user = kwargs["instance"]
|
user = kwargs["instance"]
|
||||||
|
@ -331,4 +333,3 @@ class LdapServiceUserGroup(ldapdb.models.Model):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
from django.conf.urls import url
|
from django.urls import path
|
||||||
from .import views
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
app_name = "ldap_sync"
|
||||||
|
|
||||||
urlpatterns = []
|
urlpatterns = []
|
||||||
|
|
11
logs/apps.py
Normal file
11
logs/apps.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""
|
||||||
|
Configuration of logs app.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class LogsConfig(AppConfig):
|
||||||
|
"""Configuration of logs app."""
|
||||||
|
|
||||||
|
name = "logs"
|
|
@ -21,13 +21,11 @@
|
||||||
|
|
||||||
"""The forms used by the machine search view"""
|
"""The forms used by the machine search view"""
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import Form
|
from django.forms import Form
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from re2o.base import get_input_formats_help_text
|
|
||||||
from re2o.widgets import AutocompleteModelWidget
|
|
||||||
|
|
||||||
import inspect
|
|
||||||
|
|
||||||
# Import all models in which there are classes to be filtered on
|
# Import all models in which there are classes to be filtered on
|
||||||
import cotisations.models
|
import cotisations.models
|
||||||
|
@ -35,7 +33,8 @@ import machines.models
|
||||||
import preferences.models
|
import preferences.models
|
||||||
import topologie.models
|
import topologie.models
|
||||||
import users.models
|
import users.models
|
||||||
|
from re2o.base import get_input_formats_help_text
|
||||||
|
from re2o.widgets import AutocompleteModelWidget
|
||||||
|
|
||||||
CHOICES_ACTION_TYPE = (
|
CHOICES_ACTION_TYPE = (
|
||||||
("users", _("Users")),
|
("users", _("Users")),
|
||||||
|
|
|
@ -21,23 +21,17 @@
|
||||||
"""logs.models
|
"""logs.models
|
||||||
The models definitions for the logs app
|
The models definitions for the logs app
|
||||||
"""
|
"""
|
||||||
from reversion.models import Version, Revision
|
from django.apps import apps
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from django.contrib.auth.models import Group
|
from django.contrib.auth.models import Group
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.apps import apps
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from netaddr import EUI
|
|
||||||
from macaddress.fields import default_dialect
|
from macaddress.fields import default_dialect
|
||||||
|
from netaddr import EUI
|
||||||
|
from reversion.models import Revision, Version
|
||||||
|
|
||||||
from machines.models import IpList
|
from machines.models import Interface, IpList, Machine, MachineType
|
||||||
from machines.models import Interface
|
from topologie.models import Port, Room
|
||||||
from machines.models import Machine
|
from users.models import Adherent, Club, User
|
||||||
from machines.models import MachineType
|
|
||||||
from users.models import User
|
|
||||||
from users.models import Adherent
|
|
||||||
from users.models import Club
|
|
||||||
from topologie.models import Room
|
|
||||||
from topologie.models import Port
|
|
||||||
|
|
||||||
from .forms import classes_for_action_type
|
from .forms import classes_for_action_type
|
||||||
|
|
||||||
|
@ -53,13 +47,12 @@ def make_version_filter(key, value):
|
||||||
# The lookup is done in a json string, so it has to be formated
|
# The lookup is done in a json string, so it has to be formated
|
||||||
# based on the value's type (to add " or not)
|
# based on the value's type (to add " or not)
|
||||||
if type(value) is str:
|
if type(value) is str:
|
||||||
formatted_value = "\"{}\"".format(value)
|
formatted_value = '"{}"'.format(value)
|
||||||
else:
|
else:
|
||||||
formatted_value = str(value)
|
formatted_value = str(value)
|
||||||
|
|
||||||
return (
|
return Q(serialized_data__contains='"{}": {},'.format(key, formatted_value)) | Q(
|
||||||
Q(serialized_data__contains='\"{}\": {},'.format(key, formatted_value))
|
serialized_data__contains='"{}": {}}}'.format(key, formatted_value)
|
||||||
| Q(serialized_data__contains='\"{}\": {}}}'.format(key, formatted_value))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,6 +60,7 @@ def make_version_filter(key, value):
|
||||||
# Machine history search #
|
# Machine history search #
|
||||||
############################
|
############################
|
||||||
|
|
||||||
|
|
||||||
class MachineHistorySearchEvent:
|
class MachineHistorySearchEvent:
|
||||||
def __init__(self, user, machine, interface, start=None, end=None):
|
def __init__(self, user, machine, interface, start=None, end=None):
|
||||||
"""Initialise an instance of MachineHistorySearchEvent.
|
"""Initialise an instance of MachineHistorySearchEvent.
|
||||||
|
@ -113,7 +107,7 @@ class MachineHistorySearchEvent:
|
||||||
self.ipv4,
|
self.ipv4,
|
||||||
self.start_date,
|
self.start_date,
|
||||||
self.end_date,
|
self.end_date,
|
||||||
self.comment or "No comment"
|
self.comment or "No comment",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -300,6 +294,7 @@ class MachineHistorySearch:
|
||||||
# Generic history classes #
|
# Generic history classes #
|
||||||
############################
|
############################
|
||||||
|
|
||||||
|
|
||||||
class RelatedHistory:
|
class RelatedHistory:
|
||||||
def __init__(self, version):
|
def __init__(self, version):
|
||||||
"""Initialise an instance of RelatedHistory.
|
"""Initialise an instance of RelatedHistory.
|
||||||
|
@ -317,10 +312,7 @@ class RelatedHistory:
|
||||||
self.name = "{}: {}".format(self.model_name.title(), self.name)
|
self.name = "{}: {}".format(self.model_name.title(), self.name)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return (
|
return self.model_name == other.model_name and self.object_id == other.object_id
|
||||||
self.model_name == other.model_name
|
|
||||||
and self.object_id == other.object_id
|
|
||||||
)
|
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((self.model_name, self.object_id))
|
return hash((self.model_name, self.object_id))
|
||||||
|
@ -382,15 +374,11 @@ class HistoryEvent:
|
||||||
# Take into account keys that may exist in only one dict
|
# Take into account keys that may exist in only one dict
|
||||||
if field in self.previous_version.field_dict:
|
if field in self.previous_version.field_dict:
|
||||||
old_value = self._repr(
|
old_value = self._repr(
|
||||||
field,
|
field, self.previous_version.field_dict[field]
|
||||||
self.previous_version.field_dict[field]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if field in self.version.field_dict:
|
if field in self.version.field_dict:
|
||||||
new_value = self._repr(
|
new_value = self._repr(field, self.version.field_dict[field])
|
||||||
field,
|
|
||||||
self.version.field_dict[field]
|
|
||||||
)
|
|
||||||
|
|
||||||
edits.append((field, old_value, new_value))
|
edits.append((field, old_value, new_value))
|
||||||
|
|
||||||
|
@ -487,6 +475,7 @@ class History:
|
||||||
# Revision history #
|
# Revision history #
|
||||||
############################
|
############################
|
||||||
|
|
||||||
|
|
||||||
class VersionAction(HistoryEvent):
|
class VersionAction(HistoryEvent):
|
||||||
def __init__(self, version):
|
def __init__(self, version):
|
||||||
self.version = version
|
self.version = version
|
||||||
|
@ -533,15 +522,14 @@ class VersionAction(HistoryEvent):
|
||||||
"""
|
"""
|
||||||
model = self.object_type()
|
model = self.object_type()
|
||||||
try:
|
try:
|
||||||
query = (
|
query = make_version_filter("pk", self.object_id()) & Q(
|
||||||
make_version_filter("pk", self.object_id())
|
revision__date_created__lt=self.version.revision.date_created
|
||||||
& Q(
|
)
|
||||||
revision__date_created__lt=self.version.revision.date_created
|
return (
|
||||||
)
|
Version.objects.get_for_model(model)
|
||||||
|
.filter(query)
|
||||||
|
.order_by("-revision__date_created")[0]
|
||||||
)
|
)
|
||||||
return (Version.objects.get_for_model(model)
|
|
||||||
.filter(query)
|
|
||||||
.order_by("-revision__date_created")[0])
|
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -648,6 +636,7 @@ class ActionsSearch:
|
||||||
# Class-specific history #
|
# Class-specific history #
|
||||||
############################
|
############################
|
||||||
|
|
||||||
|
|
||||||
class UserHistoryEvent(HistoryEvent):
|
class UserHistoryEvent(HistoryEvent):
|
||||||
def _repr(self, name, value):
|
def _repr(self, name, value):
|
||||||
"""Get the appropriate representation of the given field.
|
"""Get the appropriate representation of the given field.
|
||||||
|
@ -733,13 +722,15 @@ class UserHistoryEvent(HistoryEvent):
|
||||||
)
|
)
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash((frozenset(self.edited_fields), self.date, self.performed_by, self.comment))
|
return hash(
|
||||||
|
(frozenset(self.edited_fields), self.date, self.performed_by, self.comment)
|
||||||
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{} edited fields {} ({})".format(
|
return "{} edited fields {} ({})".format(
|
||||||
self.performed_by,
|
self.performed_by,
|
||||||
self.edited_fields or "nothing",
|
self.edited_fields or "nothing",
|
||||||
self.comment or "No comment"
|
self.comment or "No comment",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -762,9 +753,8 @@ class UserHistory(History):
|
||||||
|
|
||||||
# Try to find an Adherent object
|
# Try to find an Adherent object
|
||||||
# If it exists, its id will be the same as the user's
|
# If it exists, its id will be the same as the user's
|
||||||
adherents = (
|
adherents = Version.objects.get_for_model(Adherent).filter(
|
||||||
Version.objects.get_for_model(Adherent)
|
make_version_filter("pk", user_id)
|
||||||
.filter(make_version_filter("pk", user_id))
|
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
obj = adherents[0]
|
obj = adherents[0]
|
||||||
|
@ -774,9 +764,8 @@ class UserHistory(History):
|
||||||
|
|
||||||
# Fallback on a Club
|
# Fallback on a Club
|
||||||
if obj is None:
|
if obj is None:
|
||||||
clubs = (
|
clubs = Version.objects.get_for_model(Club).filter(
|
||||||
Version.objects.get_for_model(Club)
|
make_version_filter("pk", user_id)
|
||||||
.filter(make_version_filter("pk", user_id))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -826,11 +815,7 @@ class UserHistory(History):
|
||||||
|
|
||||||
# Remove duplicates and sort
|
# Remove duplicates and sort
|
||||||
self.events = list(dict.fromkeys(self.events))
|
self.events = list(dict.fromkeys(self.events))
|
||||||
return sorted(
|
return sorted(self.events, key=lambda e: e.date, reverse=True)
|
||||||
self.events,
|
|
||||||
key=lambda e: e.date,
|
|
||||||
reverse=True
|
|
||||||
)
|
|
||||||
|
|
||||||
def _add_revision(self, version):
|
def _add_revision(self, version):
|
||||||
"""Add a new revision to the chronological order.
|
"""Add a new revision to the chronological order.
|
||||||
|
@ -843,7 +828,7 @@ class UserHistory(History):
|
||||||
diff = self._compute_diff(
|
diff = self._compute_diff(
|
||||||
version,
|
version,
|
||||||
self._last_version,
|
self._last_version,
|
||||||
ignoring=["last_login", "pwd_ntlm", "email_change_date"]
|
ignoring=["last_login", "pwd_ntlm", "email_change_date"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Ignore "empty" events like login
|
# Ignore "empty" events like login
|
||||||
|
@ -973,7 +958,7 @@ HISTORY_CLASS_MAPPING = {
|
||||||
User: UserHistory,
|
User: UserHistory,
|
||||||
Machine: MachineHistory,
|
Machine: MachineHistory,
|
||||||
Interface: InterfaceHistory,
|
Interface: InterfaceHistory,
|
||||||
"default": History
|
"default": History,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
30
logs/urls.py
30
logs/urls.py
|
@ -24,26 +24,32 @@ The defined URLs for the logs app. Included in re2o.urls.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
app_name = "logs"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r"^$", views.index, name="index"),
|
path("", views.index, name="index"),
|
||||||
url(r"^stats_logs$", views.stats_logs, name="stats-logs"),
|
path("stats_logs", views.stats_logs, name="stats-logs"),
|
||||||
url(
|
path(
|
||||||
r"^revert_action/(?P<revision_id>[0-9]+)$",
|
"revert_action/<int:revision_id>",
|
||||||
views.revert_action,
|
views.revert_action,
|
||||||
name="revert-action",
|
name="revert-action",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"(?P<application>\w+)/(?P<object_name>\w+)/(?P<object_id>[0-9]+)$",
|
"<str:application>/<str:object_name>/<int:object_id>",
|
||||||
views.history,
|
views.history,
|
||||||
name="history",
|
name="history",
|
||||||
),
|
),
|
||||||
url(r"^stats_general/$", views.stats_general, name="stats-general"),
|
path("stats_general", views.stats_general, name="stats-general"),
|
||||||
url(r"^stats_models/$", views.stats_models, name="stats-models"),
|
path("stats_models", views.stats_models, name="stats-models"),
|
||||||
url(r"^stats_users/$", views.stats_users, name="stats-users"),
|
path("stats_users", views.stats_users, name="stats-users"),
|
||||||
url(r"^stats_actions/$", views.stats_actions, name="stats-actions"),
|
path("stats_actions", views.stats_actions, name="stats-actions"),
|
||||||
url(r"^stats_search_machine/$", views.stats_search_machine_history, name="stats-search-machine"),
|
path(
|
||||||
|
"stats_search_machine",
|
||||||
|
views.stats_search_machine_history,
|
||||||
|
name="stats-search-machine",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -38,84 +38,38 @@ objects for per model, number of actions per user etc.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.urls import reverse
|
from django.apps import apps
|
||||||
from django.shortcuts import render, redirect
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import Http404
|
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.apps import apps
|
from django.http import Http404
|
||||||
|
from django.shortcuts import redirect, render
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
from reversion.models import ContentType, Revision, Version
|
||||||
|
|
||||||
from reversion.models import Revision
|
from cotisations.models import (Article, Banque, Cotisation, Facture, Paiement,
|
||||||
from reversion.models import Version, ContentType
|
Vente)
|
||||||
|
from machines.models import (SOA, Domain, Extension, Interface, IpList, IpType,
|
||||||
from users.models import (
|
Machine, MachineType, Mx, Nas, Ns,
|
||||||
User,
|
OuverturePortList, Service, Vlan)
|
||||||
ServiceUser,
|
|
||||||
School,
|
|
||||||
ListRight,
|
|
||||||
ListShell,
|
|
||||||
Ban,
|
|
||||||
Whitelist,
|
|
||||||
Adherent,
|
|
||||||
Club,
|
|
||||||
)
|
|
||||||
from cotisations.models import Facture, Vente, Article, Banque, Paiement, Cotisation
|
|
||||||
from machines.models import (
|
|
||||||
Machine,
|
|
||||||
MachineType,
|
|
||||||
IpType,
|
|
||||||
Extension,
|
|
||||||
Interface,
|
|
||||||
Domain,
|
|
||||||
IpList,
|
|
||||||
OuverturePortList,
|
|
||||||
Service,
|
|
||||||
Vlan,
|
|
||||||
Nas,
|
|
||||||
SOA,
|
|
||||||
Mx,
|
|
||||||
Ns,
|
|
||||||
)
|
|
||||||
from topologie.models import (
|
|
||||||
Switch,
|
|
||||||
Port,
|
|
||||||
Room,
|
|
||||||
Stack,
|
|
||||||
ModelSwitch,
|
|
||||||
ConstructorSwitch,
|
|
||||||
AccessPoint,
|
|
||||||
)
|
|
||||||
from preferences.models import GeneralOption
|
from preferences.models import GeneralOption
|
||||||
|
from re2o.acl import (acl_error_message, can_edit_history, can_view,
|
||||||
|
can_view_all, can_view_app)
|
||||||
|
from re2o.base import SortTable, re2o_paginator
|
||||||
|
from re2o.utils import (all_active_assigned_interfaces_count,
|
||||||
|
all_active_interfaces_count, all_adherent, all_baned,
|
||||||
|
all_has_access, all_whitelisted)
|
||||||
from re2o.views import form
|
from re2o.views import form
|
||||||
from re2o.utils import (
|
from topologie.models import (AccessPoint, ConstructorSwitch, ModelSwitch,
|
||||||
all_whitelisted,
|
Port, Room, Stack, Switch)
|
||||||
all_baned,
|
from users.models import (Adherent, Ban, Club, ListRight, ListShell, School,
|
||||||
all_has_access,
|
ServiceUser, User, Whitelist)
|
||||||
all_adherent,
|
|
||||||
all_active_assigned_interfaces_count,
|
|
||||||
all_active_interfaces_count,
|
|
||||||
)
|
|
||||||
from re2o.base import re2o_paginator, SortTable
|
|
||||||
from re2o.acl import (
|
|
||||||
can_view_all,
|
|
||||||
can_view_app,
|
|
||||||
can_edit_history,
|
|
||||||
can_view,
|
|
||||||
acl_error_message,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .models import (
|
|
||||||
ActionsSearch,
|
|
||||||
RevisionAction,
|
|
||||||
MachineHistorySearch,
|
|
||||||
get_history_class,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .forms import ActionsSearchForm, MachineHistorySearchForm
|
|
||||||
|
|
||||||
from .acl import can_view as can_view_logs
|
from .acl import can_view as can_view_logs
|
||||||
|
from .forms import ActionsSearchForm, MachineHistorySearchForm
|
||||||
|
from .models import (ActionsSearch, MachineHistorySearch, RevisionAction,
|
||||||
|
get_history_class)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -528,7 +482,11 @@ def stats_search_machine_history(request):
|
||||||
max_result = GeneralOption.get_cached_value("pagination_number")
|
max_result = GeneralOption.get_cached_value("pagination_number")
|
||||||
events = re2o_paginator(request, events, max_result)
|
events = re2o_paginator(request, events, max_result)
|
||||||
|
|
||||||
return render(request, "logs/machine_history.html", {"events": events},)
|
return render(
|
||||||
|
request,
|
||||||
|
"logs/machine_history.html",
|
||||||
|
{"events": events},
|
||||||
|
)
|
||||||
return render(
|
return render(
|
||||||
request, "logs/search_machine_history.html", {"history_form": history_form}
|
request, "logs/search_machine_history.html", {"history_form": history_form}
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,24 +29,10 @@ from __future__ import unicode_literals
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from reversion.admin import VersionAdmin
|
from reversion.admin import VersionAdmin
|
||||||
|
|
||||||
from .models import (
|
from .models import (SOA, DName, Domain, Extension, Interface, IpList, IpType,
|
||||||
Extension,
|
Ipv6List, Machine, MachineType, Mx, Nas, Ns,
|
||||||
SOA,
|
OuverturePort, OuverturePortList, Role, Service, Srv,
|
||||||
Mx,
|
SshFp, Txt, Vlan)
|
||||||
Ns,
|
|
||||||
Vlan,
|
|
||||||
Txt,
|
|
||||||
DName,
|
|
||||||
Srv,
|
|
||||||
SshFp,
|
|
||||||
Nas,
|
|
||||||
Service,
|
|
||||||
Role,
|
|
||||||
OuverturePort,
|
|
||||||
Ipv6List,
|
|
||||||
OuverturePortList,
|
|
||||||
)
|
|
||||||
from .models import IpType, Machine, MachineType, Domain, IpList, Interface
|
|
||||||
|
|
||||||
|
|
||||||
class MachineAdmin(VersionAdmin):
|
class MachineAdmin(VersionAdmin):
|
||||||
|
|
|
@ -22,12 +22,12 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
import machines.models as machines
|
import machines.models as machines
|
||||||
from api.serializers import NamespacedHRField, NamespacedHIField, NamespacedHMSerializer
|
from api.serializers import (NamespacedHIField, NamespacedHMSerializer,
|
||||||
|
NamespacedHRField)
|
||||||
|
|
||||||
|
|
||||||
class MachineSerializer(NamespacedHMSerializer):
|
class MachineSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Machine` objects.
|
"""Serialize `machines.models.Machine` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Machine
|
model = machines.Machine
|
||||||
|
@ -35,8 +35,7 @@ class MachineSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class MachineTypeSerializer(NamespacedHMSerializer):
|
class MachineTypeSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.MachineType` objects.
|
"""Serialize `machines.models.MachineType` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.MachineType
|
model = machines.MachineType
|
||||||
|
@ -44,8 +43,7 @@ class MachineTypeSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class IpTypeSerializer(NamespacedHMSerializer):
|
class IpTypeSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.IpType` objects.
|
"""Serialize `machines.models.IpType` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.IpType
|
model = machines.IpType
|
||||||
|
@ -63,8 +61,7 @@ class IpTypeSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class VlanSerializer(NamespacedHMSerializer):
|
class VlanSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Vlan` objects.
|
"""Serialize `machines.models.Vlan` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Vlan
|
model = machines.Vlan
|
||||||
|
@ -82,8 +79,7 @@ class VlanSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class NasSerializer(NamespacedHMSerializer):
|
class NasSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Nas` objects.
|
"""Serialize `machines.models.Nas` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Nas
|
model = machines.Nas
|
||||||
|
@ -98,8 +94,7 @@ class NasSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SOASerializer(NamespacedHMSerializer):
|
class SOASerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.SOA` objects.
|
"""Serialize `machines.models.SOA` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.SOA
|
model = machines.SOA
|
||||||
|
@ -107,8 +102,7 @@ class SOASerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ExtensionSerializer(NamespacedHMSerializer):
|
class ExtensionSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize machines.models.Extension objects.
|
"""Serialize machines.models.Extension objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Extension
|
model = machines.Extension
|
||||||
|
@ -116,8 +110,7 @@ class ExtensionSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class MxSerializer(NamespacedHMSerializer):
|
class MxSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Mx` objects.
|
"""Serialize `machines.models.Mx` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Mx
|
model = machines.Mx
|
||||||
|
@ -125,8 +118,7 @@ class MxSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class DNameSerializer(NamespacedHMSerializer):
|
class DNameSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.DName` objects.
|
"""Serialize `machines.models.DName` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.DName
|
model = machines.DName
|
||||||
|
@ -134,8 +126,7 @@ class DNameSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class NsSerializer(NamespacedHMSerializer):
|
class NsSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Ns` objects.
|
"""Serialize `machines.models.Ns` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Ns
|
model = machines.Ns
|
||||||
|
@ -143,8 +134,7 @@ class NsSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class TxtSerializer(NamespacedHMSerializer):
|
class TxtSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Txt` objects.
|
"""Serialize `machines.models.Txt` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Txt
|
model = machines.Txt
|
||||||
|
@ -152,8 +142,7 @@ class TxtSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SrvSerializer(NamespacedHMSerializer):
|
class SrvSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Srv` objects.
|
"""Serialize `machines.models.Srv` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Srv
|
model = machines.Srv
|
||||||
|
@ -171,8 +160,7 @@ class SrvSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SshFpSerializer(NamespacedHMSerializer):
|
class SshFpSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.SSHFP` objects.
|
"""Serialize `machines.models.SSHFP` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.SshFp
|
model = machines.SshFp
|
||||||
|
@ -180,8 +168,7 @@ class SshFpSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class InterfaceSerializer(NamespacedHMSerializer):
|
class InterfaceSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Interface` objects.
|
"""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")
|
||||||
|
@ -201,8 +188,7 @@ class InterfaceSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class Ipv6ListSerializer(NamespacedHMSerializer):
|
class Ipv6ListSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Ipv6List` objects.
|
"""Serialize `machines.models.Ipv6List` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Ipv6List
|
model = machines.Ipv6List
|
||||||
|
@ -210,8 +196,7 @@ class Ipv6ListSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class DomainSerializer(NamespacedHMSerializer):
|
class DomainSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Domain` objects.
|
"""Serialize `machines.models.Domain` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Domain
|
model = machines.Domain
|
||||||
|
@ -219,8 +204,7 @@ class DomainSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class IpListSerializer(NamespacedHMSerializer):
|
class IpListSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.IpList` objects.
|
"""Serialize `machines.models.IpList` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.IpList
|
model = machines.IpList
|
||||||
|
@ -228,8 +212,7 @@ class IpListSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ServiceSerializer(NamespacedHMSerializer):
|
class ServiceSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Service` objects.
|
"""Serialize `machines.models.Service` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Service
|
model = machines.Service
|
||||||
|
@ -243,8 +226,7 @@ class ServiceSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ServiceLinkSerializer(NamespacedHMSerializer):
|
class ServiceLinkSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Service_link` objects.
|
"""Serialize `machines.models.Service_link` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Service_link
|
model = machines.Service_link
|
||||||
|
@ -260,8 +242,7 @@ class ServiceLinkSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortListSerializer(NamespacedHMSerializer):
|
class OuverturePortListSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.OuverturePortList` objects.
|
"""Serialize `machines.models.OuverturePortList` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
tcp_ports_in = NamespacedHRField(
|
tcp_ports_in = NamespacedHRField(
|
||||||
view_name="ouvertureport-detail", many=True, read_only=True
|
view_name="ouvertureport-detail", many=True, read_only=True
|
||||||
|
@ -289,8 +270,7 @@ class OuverturePortListSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortSerializer(NamespacedHMSerializer):
|
class OuverturePortSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.OuverturePort` objects.
|
"""Serialize `machines.models.OuverturePort` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.OuverturePort
|
model = machines.OuverturePort
|
||||||
|
@ -298,8 +278,7 @@ class OuverturePortSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class RoleSerializer(NamespacedHMSerializer):
|
class RoleSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.OuverturePort` objects.
|
"""Serialize `machines.models.OuverturePort` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
servers = InterfaceSerializer(read_only=True, many=True)
|
servers = InterfaceSerializer(read_only=True, many=True)
|
||||||
|
|
||||||
|
@ -309,8 +288,7 @@ class RoleSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class ServiceRegenSerializer(NamespacedHMSerializer):
|
class ServiceRegenSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize the data about the services to regen.
|
"""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)
|
||||||
|
@ -517,8 +495,7 @@ class DNAMERecordSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class DNSZonesSerializer(serializers.ModelSerializer):
|
class DNSZonesSerializer(serializers.ModelSerializer):
|
||||||
"""Serialize the data about DNS Zones.
|
"""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")
|
||||||
|
@ -559,8 +536,7 @@ class DNSZonesSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class DNSReverseZonesSerializer(serializers.ModelSerializer):
|
class DNSReverseZonesSerializer(serializers.ModelSerializer):
|
||||||
"""Serialize the data about DNS Zones.
|
"""Serialize the data about DNS Zones."""
|
||||||
"""
|
|
||||||
|
|
||||||
soa = SOARecordSerializer(source="extension.soa")
|
soa = SOARecordSerializer(source="extension.soa")
|
||||||
extension = serializers.CharField(source="extension.name", read_only=True)
|
extension = serializers.CharField(source="extension.name", read_only=True)
|
||||||
|
|
|
@ -45,9 +45,8 @@ urls_viewset = [
|
||||||
(r"machines/ouvertureport", views.OuverturePortViewSet, None),
|
(r"machines/ouvertureport", views.OuverturePortViewSet, None),
|
||||||
(r"machines/role", views.RoleViewSet, None),
|
(r"machines/role", views.RoleViewSet, None),
|
||||||
(r"machines/services-regen", views.ServiceRegenViewSet, "serviceregen"),
|
(r"machines/services-regen", views.ServiceRegenViewSet, "serviceregen"),
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
(r"services/regen", views.ServiceRegenViewSet, "serviceregen")
|
(r"services/regen", views.ServiceRegenViewSet, "serviceregen"),
|
||||||
]
|
]
|
||||||
|
|
||||||
urls_view = [
|
urls_view = [
|
||||||
|
@ -56,7 +55,6 @@ urls_view = [
|
||||||
(r"machines/firewall-interface-ports", views.InterfacePortsOpenView),
|
(r"machines/firewall-interface-ports", views.InterfacePortsOpenView),
|
||||||
(r"machines/dns-zones", views.DNSZonesView),
|
(r"machines/dns-zones", views.DNSZonesView),
|
||||||
(r"machines/dns-reverse-zones", views.DNSReverseZonesView),
|
(r"machines/dns-reverse-zones", views.DNSReverseZonesView),
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
(r"dhcp/hostmacip", views.HostMacIpView),
|
(r"dhcp/hostmacip", views.HostMacIpView),
|
||||||
(r"firewall/subnet-ports", views.SubnetPortsOpenView),
|
(r"firewall/subnet-ports", views.SubnetPortsOpenView),
|
||||||
|
|
|
@ -19,159 +19,142 @@
|
||||||
# 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.
|
||||||
|
|
||||||
from rest_framework import viewsets, generics
|
from rest_framework import generics, viewsets
|
||||||
|
|
||||||
from . import serializers
|
|
||||||
import machines.models as machines
|
import machines.models as machines
|
||||||
from re2o.utils import all_active_interfaces
|
from re2o.utils import all_active_interfaces
|
||||||
|
|
||||||
|
from . import serializers
|
||||||
|
|
||||||
|
|
||||||
class MachineViewSet(viewsets.ReadOnlyModelViewSet):
|
class MachineViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `machines.models.Machine` objects.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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 DNameViewSet(viewsets.ReadOnlyModelViewSet):
|
class DNameViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `machines.models.DName` objects.
|
"""Exposes list and details of `machines.models.DName` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
queryset = machines.DName.objects.all()
|
queryset = machines.DName.objects.all()
|
||||||
serializer_class = serializers.DNameSerializer
|
serializer_class = serializers.DNameSerializer
|
||||||
|
|
||||||
|
|
||||||
class SrvViewSet(viewsets.ReadOnlyModelViewSet):
|
class SrvViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `machines.models.Srv` objects.
|
"""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 SshFpViewSet(viewsets.ReadOnlyModelViewSet):
|
class SshFpViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `machines.models.SshFp` objects.
|
"""Exposes list and details of `machines.models.SshFp` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
queryset = machines.SshFp.objects.all()
|
queryset = machines.SshFp.objects.all()
|
||||||
serializer_class = serializers.SshFpSerializer
|
serializer_class = serializers.SshFpSerializer
|
||||||
|
|
||||||
|
|
||||||
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
|
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `machines.models.Interface` objects.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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.
|
"""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
|
||||||
|
@ -187,24 +170,21 @@ class OuverturePortListViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
|
||||||
|
|
||||||
class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
|
class OuverturePortViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `machines.models.OuverturePort` objects.
|
"""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
|
||||||
|
|
||||||
|
|
||||||
class RoleViewSet(viewsets.ReadOnlyModelViewSet):
|
class RoleViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `machines.models.Machine` objects.
|
"""Exposes list and details of `machines.models.Machine` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
queryset = machines.Role.objects.all()
|
queryset = machines.Role.objects.all()
|
||||||
serializer_class = serializers.RoleSerializer
|
serializer_class = serializers.RoleSerializer
|
||||||
|
|
||||||
|
|
||||||
class ServiceRegenViewSet(viewsets.ModelViewSet):
|
class ServiceRegenViewSet(viewsets.ModelViewSet):
|
||||||
"""Exposes list and details of the services to regen
|
"""Exposes list and details of the services to regen"""
|
||||||
"""
|
|
||||||
|
|
||||||
serializer_class = serializers.ServiceRegenSerializer
|
serializer_class = serializers.ServiceRegenSerializer
|
||||||
|
|
||||||
|
@ -238,6 +218,7 @@ class InterfacePortsOpenView(generics.ListAPIView):
|
||||||
queryset = machines.Interface.objects.filter(port_lists__isnull=False).distinct()
|
queryset = machines.Interface.objects.filter(port_lists__isnull=False).distinct()
|
||||||
serializer_class = serializers.InterfacePortsOpenSerializer
|
serializer_class = serializers.InterfacePortsOpenSerializer
|
||||||
|
|
||||||
|
|
||||||
class DNSZonesView(generics.ListAPIView):
|
class DNSZonesView(generics.ListAPIView):
|
||||||
"""Exposes the detailed information about each extension (hostnames,
|
"""Exposes the detailed information about each extension (hostnames,
|
||||||
IPs, DNS records, etc.) in order to build the DNS zone files.
|
IPs, DNS records, etc.) in order to build the DNS zone files.
|
||||||
|
|
11
machines/apps.py
Normal file
11
machines/apps.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""
|
||||||
|
Configuration of machines app.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class MachinesConfig(AppConfig):
|
||||||
|
"""Configuration of machines app."""
|
||||||
|
|
||||||
|
name = "machines"
|
|
@ -36,37 +36,17 @@ Forms to create, edit and delete:
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import ModelForm, Form
|
from django.forms import Form, ModelForm
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from re2o.field_permissions import FieldPermissionFormMixin
|
from re2o.field_permissions import FieldPermissionFormMixin
|
||||||
from re2o.mixins import FormRevMixin
|
from re2o.mixins import FormRevMixin
|
||||||
from re2o.widgets import (
|
from re2o.widgets import (AutocompleteModelWidget,
|
||||||
AutocompleteModelWidget,
|
AutocompleteMultipleModelWidget)
|
||||||
AutocompleteMultipleModelWidget,
|
|
||||||
)
|
from .models import (SOA, DName, Domain, Extension, Interface, IpList, IpType,
|
||||||
from .models import (
|
Ipv6List, Machine, MachineType, Mx, Nas, Ns,
|
||||||
Domain,
|
OuverturePortList, Role, Service, Srv, SshFp, Txt, Vlan)
|
||||||
Machine,
|
|
||||||
Interface,
|
|
||||||
IpList,
|
|
||||||
MachineType,
|
|
||||||
Extension,
|
|
||||||
SOA,
|
|
||||||
Mx,
|
|
||||||
Txt,
|
|
||||||
DName,
|
|
||||||
Ns,
|
|
||||||
Role,
|
|
||||||
Service,
|
|
||||||
Vlan,
|
|
||||||
Srv,
|
|
||||||
SshFp,
|
|
||||||
Nas,
|
|
||||||
IpType,
|
|
||||||
OuverturePortList,
|
|
||||||
Ipv6List,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class EditMachineForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
|
class EditMachineForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
|
||||||
|
@ -248,7 +228,9 @@ class IpTypeForm(FormRevMixin, ModelForm):
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
widgets = {
|
widgets = {
|
||||||
"vlan": AutocompleteModelWidget(url="/machines/vlan-autocomplete"),
|
"vlan": AutocompleteModelWidget(url="/machines/vlan-autocomplete"),
|
||||||
"extension": AutocompleteModelWidget(url="/machines/extension-autocomplete"),
|
"extension": AutocompleteModelWidget(
|
||||||
|
url="/machines/extension-autocomplete"
|
||||||
|
),
|
||||||
"ouverture_ports": AutocompleteModelWidget(
|
"ouverture_ports": AutocompleteModelWidget(
|
||||||
url="/machines/ouvertureportlist-autocomplete"
|
url="/machines/ouvertureportlist-autocomplete"
|
||||||
),
|
),
|
||||||
|
@ -525,7 +507,9 @@ class SrvForm(FormRevMixin, ModelForm):
|
||||||
model = Srv
|
model = Srv
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
widgets = {
|
widgets = {
|
||||||
"extension": AutocompleteModelWidget(url="/machines/extension-autocomplete"),
|
"extension": AutocompleteModelWidget(
|
||||||
|
url="/machines/extension-autocomplete"
|
||||||
|
),
|
||||||
"target": AutocompleteModelWidget(url="/machines/domain-autocomplete"),
|
"target": AutocompleteModelWidget(url="/machines/domain-autocomplete"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1098,7 +1098,7 @@ class Migration(migrations.Migration):
|
||||||
(
|
(
|
||||||
"cname",
|
"cname",
|
||||||
models.ForeignKey(
|
models.ForeignKey(
|
||||||
"self", null=True, blank=True, related_name="related_domain"
|
"self", null=True, blank=True, related_name="related_domain", on_delete=models.CASCADE
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
108
machines/migrations/0003_auto_20210208_1827.py
Normal file
108
machines/migrations/0003_auto_20210208_1827.py
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
# Generated by Django 2.2.18 on 2021-02-08 17:27
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('machines', '0002_foreign_keys'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='dname',
|
||||||
|
options={'verbose_name': 'DNAME record', 'verbose_name_plural': 'DNAME records'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='domain',
|
||||||
|
options={'permissions': (('change_ttl', 'Can change the TTL of a domain object'),), 'verbose_name': 'domain', 'verbose_name_plural': 'domains'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='extension',
|
||||||
|
options={'permissions': (('use_all_extension', 'Can use all extensions'),), 'verbose_name': 'DNS extension', 'verbose_name_plural': 'DNS extensions'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='interface',
|
||||||
|
options={'permissions': (('change_interface_machine', 'Can change the owner of an interface'),), 'verbose_name': 'interface', 'verbose_name_plural': 'interfaces'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='iplist',
|
||||||
|
options={'verbose_name': 'IPv4 addresses list', 'verbose_name_plural': 'IPv4 addresses lists'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='iptype',
|
||||||
|
options={'permissions': (('use_all_iptype', 'Can use all IP types'),), 'verbose_name': 'IP type', 'verbose_name_plural': 'IP types'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='ipv6list',
|
||||||
|
options={'permissions': (('change_ipv6list_slaac_ip', 'Can change the SLAAC value of an IPv6 addresses list'),), 'verbose_name': 'IPv6 addresses list', 'verbose_name_plural': 'IPv6 addresses lists'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='machine',
|
||||||
|
options={'permissions': (('change_machine_user', 'Can change the user of a machine'),), 'verbose_name': 'machine', 'verbose_name_plural': 'machines'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='machinetype',
|
||||||
|
options={'permissions': (('use_all_machinetype', 'Can use all machine types'),), 'verbose_name': 'machine type', 'verbose_name_plural': 'machine types'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='mx',
|
||||||
|
options={'verbose_name': 'MX record', 'verbose_name_plural': 'MX records'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='nas',
|
||||||
|
options={'verbose_name': 'NAS device', 'verbose_name_plural': 'NAS devices'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='ns',
|
||||||
|
options={'verbose_name': 'NS record', 'verbose_name_plural': 'NS records'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='ouvertureportlist',
|
||||||
|
options={'verbose_name': 'ports opening list', 'verbose_name_plural': 'ports opening lists'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='role',
|
||||||
|
options={'verbose_name': 'server role', 'verbose_name_plural': 'server roles'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='service',
|
||||||
|
options={'verbose_name': 'service to generate (DHCP, DNS, ...)', 'verbose_name_plural': 'services to generate (DHCP, DNS, ...)'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='service_link',
|
||||||
|
options={'verbose_name': 'link between service and server', 'verbose_name_plural': 'links between service and server'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='soa',
|
||||||
|
options={'verbose_name': 'SOA record', 'verbose_name_plural': 'SOA records'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='srv',
|
||||||
|
options={'verbose_name': 'SRV record', 'verbose_name_plural': 'SRV records'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='sshfp',
|
||||||
|
options={'verbose_name': 'SSHFP record', 'verbose_name_plural': 'SSHFP records'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='txt',
|
||||||
|
options={'verbose_name': 'TXT record', 'verbose_name_plural': 'TXT records'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='vlan',
|
||||||
|
options={'verbose_name': 'VLAN', 'verbose_name_plural': 'VLANs'},
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='domain',
|
||||||
|
name='cname',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='related_domain', to='machines.Domain'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='iptype',
|
||||||
|
name='ouverture_ports',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='machines.OuverturePortList'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -34,6 +34,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="interface",
|
model_name="interface",
|
||||||
name="machine",
|
name="machine",
|
||||||
field=models.ForeignKey(to="machines.Machine"),
|
field=models.ForeignKey(to="machines.Machine", on_delete=models.CASCADE),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Migration(migrations.Migration):
|
||||||
unique=True,
|
unique=True,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("interface_parent", models.ForeignKey(to="machines.Interface")),
|
("interface_parent", models.ForeignKey(to="machines.Interface", on_delete=models.CASCADE)),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domain",
|
model_name="domain",
|
||||||
name="interface_parent",
|
name="interface_parent",
|
||||||
field=models.ForeignKey(to="machines.Interface", null=True, blank=True),
|
field=models.ForeignKey(to="machines.Interface", null=True, blank=True, on_delete=models.CASCADE),
|
||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
migrations.AlterUniqueTogether(
|
||||||
name="domain", unique_together=set([("name", "extension")])
|
name="domain", unique_together=set([("name", "extension")])
|
||||||
|
|
|
@ -39,6 +39,7 @@ class Migration(migrations.Migration):
|
||||||
null=True,
|
null=True,
|
||||||
to="machines.Domain",
|
to="machines.Domain",
|
||||||
blank=True,
|
blank=True,
|
||||||
|
on_delete=models.CASCADE
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -39,6 +39,7 @@ class Migration(migrations.Migration):
|
||||||
to="machines.Domain",
|
to="machines.Domain",
|
||||||
related_name="related_domain",
|
related_name="related_domain",
|
||||||
blank=True,
|
blank=True,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -34,6 +34,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="domain",
|
model_name="domain",
|
||||||
name="interface_parent",
|
name="interface_parent",
|
||||||
field=models.OneToOneField(blank=True, null=True, to="machines.Interface"),
|
field=models.OneToOneField(blank=True, null=True, to="machines.Interface", on_delete=models.CASCADE),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -35,26 +35,18 @@ from ipaddress import IPv6Address
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db import models
|
from django.db import models, transaction
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.db.models.signals import post_save, post_delete
|
from django.db.models.signals import post_delete, post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.db import transaction
|
|
||||||
from reversion import revisions as reversion
|
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from macaddress.fields import MACAddressField, default_dialect
|
from macaddress.fields import MACAddressField, default_dialect
|
||||||
from netaddr import (
|
from netaddr import (EUI, IPAddress, IPNetwork, IPRange, IPSet,
|
||||||
mac_bare,
|
NotRegisteredError, mac_bare)
|
||||||
EUI,
|
from reversion import revisions as reversion
|
||||||
NotRegisteredError,
|
|
||||||
IPSet,
|
|
||||||
IPRange,
|
|
||||||
IPNetwork,
|
|
||||||
IPAddress,
|
|
||||||
)
|
|
||||||
|
|
||||||
import preferences.models
|
import preferences.models
|
||||||
import users.models
|
import users.models
|
||||||
|
@ -79,10 +71,7 @@ class Machine(RevMixin, FieldPermissionModelMixin, AclMixin, models.Model):
|
||||||
active = models.BooleanField(default=True)
|
active = models.BooleanField(default=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("change_machine_user", _("Can change the user of a machine")),)
|
||||||
("view_machine", _("Can view a machine object")),
|
|
||||||
("change_machine_user", _("Can change the user of a machine")),
|
|
||||||
)
|
|
||||||
verbose_name = _("machine")
|
verbose_name = _("machine")
|
||||||
verbose_name_plural = _("machines")
|
verbose_name_plural = _("machines")
|
||||||
|
|
||||||
|
@ -343,10 +332,7 @@ class MachineType(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("use_all_machinetype", _("Can use all machine types")),)
|
||||||
("view_machinetype", _("Can view a machine type object")),
|
|
||||||
("use_all_machinetype", _("Can use all machine types")),
|
|
||||||
)
|
|
||||||
verbose_name = _("machine type")
|
verbose_name = _("machine type")
|
||||||
verbose_name_plural = _("machine types")
|
verbose_name_plural = _("machine types")
|
||||||
|
|
||||||
|
@ -358,7 +344,9 @@ class MachineType(RevMixin, AclMixin, models.Model):
|
||||||
"""Update domains extension with the extension of interface_parent. Called after update of an ip_type or a machine_type object. Exceptions are handled in the views.
|
"""Update domains extension with the extension of interface_parent. Called after update of an ip_type or a machine_type object. Exceptions are handled in the views.
|
||||||
(Calling domain.clear() for all domains could take several minutes)
|
(Calling domain.clear() for all domains could take several minutes)
|
||||||
"""
|
"""
|
||||||
Domain.objects.filter(interface_parent__machine_type=self).update(extension=self.ip_type.extension)
|
Domain.objects.filter(interface_parent__machine_type=self).update(
|
||||||
|
extension=self.ip_type.extension
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def can_use_all(user_request, *_args, **_kwargs):
|
def can_use_all(user_request, *_args, **_kwargs):
|
||||||
|
@ -391,20 +379,13 @@ class MachineType(RevMixin, AclMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
can, _message, _group = cls.can_use_all(user_request)
|
can, _message, _group = cls.can_use_all(user_request)
|
||||||
if can:
|
if can:
|
||||||
return (
|
return (True, None, None, cls.objects.all())
|
||||||
True,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
cls.objects.all()
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
True,
|
True,
|
||||||
_("You don't have the right to use all machine types."),
|
_("You don't have the right to use all machine types."),
|
||||||
("machines.use_all_machinetype",),
|
("machines.use_all_machinetype",),
|
||||||
cls.objects.filter(
|
cls.objects.filter(ip_type__in=IpType.objects.filter(need_infra=False)),
|
||||||
ip_type__in=IpType.objects.filter(need_infra=False)
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -457,13 +438,12 @@ class IpType(RevMixin, AclMixin, models.Model):
|
||||||
default=False, help_text=_("Enable reverse DNS for IPv6.")
|
default=False, help_text=_("Enable reverse DNS for IPv6.")
|
||||||
)
|
)
|
||||||
vlan = models.ForeignKey("Vlan", on_delete=models.PROTECT, blank=True, null=True)
|
vlan = models.ForeignKey("Vlan", on_delete=models.PROTECT, blank=True, null=True)
|
||||||
ouverture_ports = models.ForeignKey("OuverturePortList", blank=True, null=True)
|
ouverture_ports = models.ForeignKey(
|
||||||
|
"OuverturePortList", blank=True, null=True, on_delete=models.PROTECT
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("use_all_iptype", _("Can use all IP types")),)
|
||||||
("view_iptype", _("Can view an IP type object")),
|
|
||||||
("use_all_iptype", _("Can use all IP types")),
|
|
||||||
)
|
|
||||||
verbose_name = _("IP type")
|
verbose_name = _("IP type")
|
||||||
verbose_name_plural = _("IP types")
|
verbose_name_plural = _("IP types")
|
||||||
|
|
||||||
|
@ -729,7 +709,6 @@ class Vlan(RevMixin, AclMixin, models.Model):
|
||||||
mld = models.BooleanField(default=False, help_text=_("v6 multicast management."))
|
mld = models.BooleanField(default=False, help_text=_("v6 multicast management."))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_vlan", _("Can view a VLAN object")),)
|
|
||||||
verbose_name = _("VLAN")
|
verbose_name = _("VLAN")
|
||||||
verbose_name_plural = _("VLANs")
|
verbose_name_plural = _("VLANs")
|
||||||
|
|
||||||
|
@ -765,7 +744,6 @@ class Nas(RevMixin, AclMixin, models.Model):
|
||||||
autocapture_mac = models.BooleanField(default=False)
|
autocapture_mac = models.BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_nas", _("Can view a NAS device object")),)
|
|
||||||
verbose_name = _("NAS device")
|
verbose_name = _("NAS device")
|
||||||
verbose_name_plural = _("NAS devices")
|
verbose_name_plural = _("NAS devices")
|
||||||
|
|
||||||
|
@ -819,7 +797,6 @@ class SOA(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_soa", _("Can view an SOA record object")),)
|
|
||||||
verbose_name = _("SOA record")
|
verbose_name = _("SOA record")
|
||||||
verbose_name_plural = _("SOA records")
|
verbose_name_plural = _("SOA records")
|
||||||
|
|
||||||
|
@ -903,10 +880,7 @@ class Extension(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (("use_all_extension", _("Can use all extensions")),)
|
||||||
("view_extension", _("Can view an extension object")),
|
|
||||||
("use_all_extension", _("Can use all extensions")),
|
|
||||||
)
|
|
||||||
verbose_name = _("DNS extension")
|
verbose_name = _("DNS extension")
|
||||||
verbose_name_plural = _("DNS extensions")
|
verbose_name_plural = _("DNS extensions")
|
||||||
|
|
||||||
|
@ -994,12 +968,7 @@ class Extension(RevMixin, AclMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
can, _message, _group = cls.can_use_all(user_request)
|
can, _message, _group = cls.can_use_all(user_request)
|
||||||
if can:
|
if can:
|
||||||
return (
|
return (True, None, None, cls.objects.all())
|
||||||
True,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
cls.objects.all()
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
True,
|
True,
|
||||||
|
@ -1037,14 +1006,12 @@ class Mx(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_mx", _("Can view an MX record object")),)
|
|
||||||
verbose_name = _("MX record")
|
verbose_name = _("MX record")
|
||||||
verbose_name_plural = _("MX records")
|
verbose_name_plural = _("MX records")
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
"""Get the complete DNS entry of the MX record, to put in zone files.
|
"""Get the complete DNS entry of the MX record, to put in zone files."""
|
||||||
"""
|
|
||||||
return "@ IN MX {prior} {name}".format(
|
return "@ IN MX {prior} {name}".format(
|
||||||
prior=str(self.priority).ljust(3), name=str(self.name)
|
prior=str(self.priority).ljust(3), name=str(self.name)
|
||||||
)
|
)
|
||||||
|
@ -1069,14 +1036,12 @@ class Ns(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_ns", _("Can view an NS record object")),)
|
|
||||||
verbose_name = _("NS record")
|
verbose_name = _("NS record")
|
||||||
verbose_name_plural = _("NS records")
|
verbose_name_plural = _("NS records")
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
"""Get the complete DNS entry of the NS record, to put in zone files.
|
"""Get the complete DNS entry of the NS record, to put in zone files."""
|
||||||
"""
|
|
||||||
return "@ IN NS " + str(self.ns)
|
return "@ IN NS " + str(self.ns)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -1101,7 +1066,6 @@ class Txt(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_txt", _("Can view a TXT record object")),)
|
|
||||||
verbose_name = _("TXT record")
|
verbose_name = _("TXT record")
|
||||||
verbose_name_plural = _("TXT records")
|
verbose_name_plural = _("TXT records")
|
||||||
|
|
||||||
|
@ -1110,8 +1074,7 @@ class Txt(RevMixin, AclMixin, models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
"""Get the complete DNS entry of the TXT record, to put in zone files.
|
"""Get the complete DNS entry of the TXT record, to put in zone files."""
|
||||||
"""
|
|
||||||
return str(self.field1).ljust(15) + " IN TXT " + str(self.field2)
|
return str(self.field1).ljust(15) + " IN TXT " + str(self.field2)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1131,7 +1094,6 @@ class DName(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_dname", _("Can view a DNAME record object")),)
|
|
||||||
verbose_name = _("DNAME record")
|
verbose_name = _("DNAME record")
|
||||||
verbose_name_plural = _("DNAME records")
|
verbose_name_plural = _("DNAME records")
|
||||||
|
|
||||||
|
@ -1140,8 +1102,7 @@ class DName(RevMixin, AclMixin, models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
"""Get the complete DNS entry of the TXT record, to put in zone files.
|
"""Get the complete DNS entry of the TXT record, to put in zone files."""
|
||||||
"""
|
|
||||||
return str(self.alias).ljust(15) + " IN DNAME " + str(self.zone)
|
return str(self.alias).ljust(15) + " IN DNAME " + str(self.zone)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1195,7 +1156,6 @@ class Srv(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_srv", _("Can view an SRV record object")),)
|
|
||||||
verbose_name = _("SRV record")
|
verbose_name = _("SRV record")
|
||||||
verbose_name_plural = _("SRV records")
|
verbose_name_plural = _("SRV records")
|
||||||
|
|
||||||
|
@ -1216,8 +1176,7 @@ class Srv(RevMixin, AclMixin, models.Model):
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def dns_entry(self):
|
def dns_entry(self):
|
||||||
"""Get the complete DNS entry of the SRV record, to put in zone files.
|
"""Get the complete DNS entry of the SRV record, to put in zone files."""
|
||||||
"""
|
|
||||||
return (
|
return (
|
||||||
str(self.service)
|
str(self.service)
|
||||||
+ "._"
|
+ "._"
|
||||||
|
@ -1285,7 +1244,6 @@ class SshFp(RevMixin, AclMixin, models.Model):
|
||||||
}
|
}
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_sshfp", _("Can view an SSHFP record object")),)
|
|
||||||
verbose_name = _("SSHFP record")
|
verbose_name = _("SSHFP record")
|
||||||
verbose_name_plural = _("SSHFP records")
|
verbose_name_plural = _("SSHFP records")
|
||||||
|
|
||||||
|
@ -1350,7 +1308,6 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_interface", _("Can view an interface object")),
|
|
||||||
("change_interface_machine", _("Can change the owner of an interface")),
|
("change_interface_machine", _("Can change the owner of an interface")),
|
||||||
)
|
)
|
||||||
verbose_name = _("interface")
|
verbose_name = _("interface")
|
||||||
|
@ -1401,8 +1358,7 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
return vendor
|
return vendor
|
||||||
|
|
||||||
def sync_ipv6_dhcpv6(self):
|
def sync_ipv6_dhcpv6(self):
|
||||||
"""Assign an IPv6 address by DHCPv6, computed from the interface's ID.
|
"""Assign an IPv6 address by DHCPv6, computed from the interface's ID."""
|
||||||
"""
|
|
||||||
ipv6_dhcpv6 = self.gen_ipv6_dhcpv6
|
ipv6_dhcpv6 = self.gen_ipv6_dhcpv6
|
||||||
if not ipv6_dhcpv6:
|
if not ipv6_dhcpv6:
|
||||||
return
|
return
|
||||||
|
@ -1428,8 +1384,7 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
ipv6_object.save()
|
ipv6_object.save()
|
||||||
|
|
||||||
def sync_ipv6(self):
|
def sync_ipv6(self):
|
||||||
"""Create and update the IPv6 addresses according to the IPv6 mode set.
|
"""Create and update the IPv6 addresses according to the IPv6 mode set."""
|
||||||
"""
|
|
||||||
if preferences.models.OptionalMachine.get_cached_value("ipv6_mode") == "SLAAC":
|
if preferences.models.OptionalMachine.get_cached_value("ipv6_mode") == "SLAAC":
|
||||||
self.sync_ipv6_slaac()
|
self.sync_ipv6_slaac()
|
||||||
elif (
|
elif (
|
||||||
|
@ -1595,8 +1550,10 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
_("You don't have the right to add a machine."),
|
_("You don't have the right to add a machine."),
|
||||||
("machines.add_interface",),
|
("machines.add_interface",),
|
||||||
)
|
)
|
||||||
max_lambdauser_interfaces = preferences.models.OptionalMachine.get_cached_value(
|
max_lambdauser_interfaces = (
|
||||||
"max_lambdauser_interfaces"
|
preferences.models.OptionalMachine.get_cached_value(
|
||||||
|
"max_lambdauser_interfaces"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if machine.user != user_request:
|
if machine.user != user_request:
|
||||||
return (
|
return (
|
||||||
|
@ -1735,13 +1692,11 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
)
|
)
|
||||||
slaac_ip = models.BooleanField(default=False)
|
slaac_ip = models.BooleanField(default=False)
|
||||||
active = models.BooleanField(
|
active = models.BooleanField(
|
||||||
default=True,
|
default=True, help_text=_("If false,the DNS will not provide this ip.")
|
||||||
help_text=_("If false,the DNS will not provide this ip.")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
permissions = (
|
||||||
("view_ipv6list", _("Can view an IPv6 addresses list object")),
|
|
||||||
(
|
(
|
||||||
"change_ipv6list_slaac_ip",
|
"change_ipv6list_slaac_ip",
|
||||||
_("Can change the SLAAC value of an IPv6 addresses list"),
|
_("Can change the SLAAC value of an IPv6 addresses list"),
|
||||||
|
@ -1871,8 +1826,9 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
|
|
||||||
def check_and_replace_prefix(self, prefix=None):
|
def check_and_replace_prefix(self, prefix=None):
|
||||||
"""Check if the IPv6 prefix is correct and update it if not."""
|
"""Check if the IPv6 prefix is correct and update it if not."""
|
||||||
prefix_v6 = prefix or self.interface.machine_type.ip_type.prefix_v6.encode().decode(
|
prefix_v6 = (
|
||||||
"utf-8"
|
prefix
|
||||||
|
or self.interface.machine_type.ip_type.prefix_v6.encode().decode("utf-8")
|
||||||
)
|
)
|
||||||
if not prefix_v6:
|
if not prefix_v6:
|
||||||
return
|
return
|
||||||
|
@ -1945,7 +1901,11 @@ class Domain(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
)
|
)
|
||||||
extension = models.ForeignKey("Extension", on_delete=models.PROTECT)
|
extension = models.ForeignKey("Extension", on_delete=models.PROTECT)
|
||||||
cname = models.ForeignKey(
|
cname = models.ForeignKey(
|
||||||
"self", null=True, blank=True, related_name="related_domain"
|
"self",
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="related_domain",
|
||||||
|
on_delete=models.PROTECT,
|
||||||
)
|
)
|
||||||
ttl = models.PositiveIntegerField(
|
ttl = models.PositiveIntegerField(
|
||||||
verbose_name=_("Time To Live (TTL)"),
|
verbose_name=_("Time To Live (TTL)"),
|
||||||
|
@ -1955,10 +1915,7 @@ class Domain(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (("name", "extension"),)
|
unique_together = (("name", "extension"),)
|
||||||
permissions = (
|
permissions = (("change_ttl", _("Can change the TTL of a domain object")),)
|
||||||
("view_domain", _("Can view a domain object")),
|
|
||||||
("change_ttl", _("Can change the TTL of a domain object")),
|
|
||||||
)
|
|
||||||
verbose_name = _("domain")
|
verbose_name = _("domain")
|
||||||
verbose_name_plural = _("domains")
|
verbose_name_plural = _("domains")
|
||||||
|
|
||||||
|
@ -2053,8 +2010,10 @@ class Domain(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
except Interface.DoesNotExist:
|
except Interface.DoesNotExist:
|
||||||
return False, _("Nonexistent interface."), None
|
return False, _("Nonexistent interface."), None
|
||||||
if not user_request.has_perm("machines.add_domain"):
|
if not user_request.has_perm("machines.add_domain"):
|
||||||
max_lambdauser_aliases = preferences.models.OptionalMachine.get_cached_value(
|
max_lambdauser_aliases = (
|
||||||
"max_lambdauser_aliases"
|
preferences.models.OptionalMachine.get_cached_value(
|
||||||
|
"max_lambdauser_aliases"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if interface.machine.user != user_request:
|
if interface.machine.user != user_request:
|
||||||
return (
|
return (
|
||||||
|
@ -2184,14 +2143,12 @@ class IpList(RevMixin, AclMixin, models.Model):
|
||||||
ip_type = models.ForeignKey("IpType", on_delete=models.CASCADE)
|
ip_type = models.ForeignKey("IpType", on_delete=models.CASCADE)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_iplist", _("Can view an IPv4 addresses list object")),)
|
|
||||||
verbose_name = _("IPv4 addresses list")
|
verbose_name = _("IPv4 addresses list")
|
||||||
verbose_name_plural = _("IPv4 addresses lists")
|
verbose_name_plural = _("IPv4 addresses lists")
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def need_infra(self):
|
def need_infra(self):
|
||||||
"""Check if the 'infra' right is required to assign this IP address.
|
"""Check if the 'infra' right is required to assign this IP address."""
|
||||||
"""
|
|
||||||
return self.ip_type.need_infra
|
return self.ip_type.need_infra
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
@ -2223,20 +2180,13 @@ class IpList(RevMixin, AclMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
can, _message, _group = IpType.can_use_all(user_request)
|
can, _message, _group = IpType.can_use_all(user_request)
|
||||||
if can:
|
if can:
|
||||||
return (
|
return (True, None, None, cls.objects.all())
|
||||||
True,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
cls.objects.all()
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return (
|
return (
|
||||||
True,
|
True,
|
||||||
_("You don't have the right to use all machine types."),
|
_("You don't have the right to use all machine types."),
|
||||||
("machines.use_all_machinetype",),
|
("machines.use_all_machinetype",),
|
||||||
cls.objects.filter(
|
cls.objects.filter(ip_type__in=IpType.objects.filter(need_infra=False)),
|
||||||
ip_type__in=IpType.objects.filter(need_infra=False)
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -2275,7 +2225,6 @@ class Role(RevMixin, AclMixin, models.Model):
|
||||||
specific_role = models.CharField(choices=ROLE, null=True, blank=True, max_length=32)
|
specific_role = models.CharField(choices=ROLE, null=True, blank=True, max_length=32)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_role", _("Can view a role object")),)
|
|
||||||
verbose_name = _("server role")
|
verbose_name = _("server role")
|
||||||
verbose_name_plural = _("server roles")
|
verbose_name_plural = _("server roles")
|
||||||
|
|
||||||
|
@ -2325,7 +2274,6 @@ class Service(RevMixin, AclMixin, models.Model):
|
||||||
servers = models.ManyToManyField("Interface", through="Service_link")
|
servers = models.ManyToManyField("Interface", through="Service_link")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_service", _("Can view a service object")),)
|
|
||||||
verbose_name = _("service to generate (DHCP, DNS, ...)")
|
verbose_name = _("service to generate (DHCP, DNS, ...)")
|
||||||
verbose_name_plural = _("services to generate (DHCP, DNS, ...)")
|
verbose_name_plural = _("services to generate (DHCP, DNS, ...)")
|
||||||
|
|
||||||
|
@ -2383,9 +2331,6 @@ class Service_link(RevMixin, AclMixin, models.Model):
|
||||||
asked_regen = models.BooleanField(default=False)
|
asked_regen = models.BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
|
||||||
("view_service_link", _("Can view a service server link object")),
|
|
||||||
)
|
|
||||||
verbose_name = _("link between service and server")
|
verbose_name = _("link between service and server")
|
||||||
verbose_name_plural = _("links between service and server")
|
verbose_name_plural = _("links between service and server")
|
||||||
|
|
||||||
|
@ -2438,9 +2383,6 @@ class OuverturePortList(RevMixin, AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
|
||||||
("view_ouvertureportlist", _("Can view a ports opening list" " object")),
|
|
||||||
)
|
|
||||||
verbose_name = _("ports opening list")
|
verbose_name = _("ports opening list")
|
||||||
verbose_name_plural = _("ports opening lists")
|
verbose_name_plural = _("ports opening lists")
|
||||||
|
|
||||||
|
@ -2542,7 +2484,13 @@ class OuverturePort(RevMixin, AclMixin, models.Model):
|
||||||
def machine_post_save(**kwargs):
|
def machine_post_save(**kwargs):
|
||||||
"""Synchronise LDAP and regen firewall/DHCP after a machine is edited."""
|
"""Synchronise LDAP and regen firewall/DHCP after a machine is edited."""
|
||||||
user = kwargs["instance"].user
|
user = kwargs["instance"].user
|
||||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=False, access_refresh=False, mac_refresh=True)
|
users.signals.synchronise.send(
|
||||||
|
sender=users.models.User,
|
||||||
|
instance=user,
|
||||||
|
base=False,
|
||||||
|
access_refresh=False,
|
||||||
|
mac_refresh=True,
|
||||||
|
)
|
||||||
regen("dhcp")
|
regen("dhcp")
|
||||||
regen("mac_ip_list")
|
regen("mac_ip_list")
|
||||||
|
|
||||||
|
@ -2552,7 +2500,13 @@ def machine_post_delete(**kwargs):
|
||||||
"""Synchronise LDAP and regen firewall/DHCP after a machine is deleted."""
|
"""Synchronise LDAP and regen firewall/DHCP after a machine is deleted."""
|
||||||
machine = kwargs["instance"]
|
machine = kwargs["instance"]
|
||||||
user = machine.user
|
user = machine.user
|
||||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=False, access_refresh=False, mac_refresh=True)
|
users.signals.synchronise.send(
|
||||||
|
sender=users.models.User,
|
||||||
|
instance=user,
|
||||||
|
base=False,
|
||||||
|
access_refresh=False,
|
||||||
|
mac_refresh=True,
|
||||||
|
)
|
||||||
regen("dhcp")
|
regen("dhcp")
|
||||||
regen("mac_ip_list")
|
regen("mac_ip_list")
|
||||||
|
|
||||||
|
@ -2565,7 +2519,13 @@ def interface_post_save(**kwargs):
|
||||||
interface = kwargs["instance"]
|
interface = kwargs["instance"]
|
||||||
interface.sync_ipv6()
|
interface.sync_ipv6()
|
||||||
user = interface.machine.user
|
user = interface.machine.user
|
||||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=False, access_refresh=False, mac_refresh=True)
|
users.signals.synchronise.send(
|
||||||
|
sender=users.models.User,
|
||||||
|
instance=user,
|
||||||
|
base=False,
|
||||||
|
access_refresh=False,
|
||||||
|
mac_refresh=True,
|
||||||
|
)
|
||||||
# Regen services
|
# Regen services
|
||||||
regen("dhcp")
|
regen("dhcp")
|
||||||
regen("mac_ip_list")
|
regen("mac_ip_list")
|
||||||
|
@ -2577,11 +2537,16 @@ def interface_post_save(**kwargs):
|
||||||
|
|
||||||
@receiver(post_delete, sender=Interface)
|
@receiver(post_delete, sender=Interface)
|
||||||
def interface_post_delete(**kwargs):
|
def interface_post_delete(**kwargs):
|
||||||
"""Synchronise LDAP and regen firewall/DHCP after an interface is deleted.
|
"""Synchronise LDAP and regen firewall/DHCP after an interface is deleted."""
|
||||||
"""
|
|
||||||
interface = kwargs["instance"]
|
interface = kwargs["instance"]
|
||||||
user = interface.machine.user
|
user = interface.machine.user
|
||||||
users.signals.synchronise.send(sender=users.models.User, instance=user, base=False, access_refresh=False, mac_refresh=True)
|
users.signals.synchronise.send(
|
||||||
|
sender=users.models.User,
|
||||||
|
instance=user,
|
||||||
|
base=False,
|
||||||
|
access_refresh=False,
|
||||||
|
mac_refresh=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=IpType)
|
@receiver(post_save, sender=IpType)
|
||||||
|
|
229
machines/urls.py
229
machines/urls.py
|
@ -26,142 +26,175 @@ The defined URLs for the Machines app
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views, views_autocomplete
|
||||||
from . import views_autocomplete
|
|
||||||
|
app_name = "machines"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r"^new_machine/(?P<userid>[0-9]+)$", views.new_machine, name="new-machine"),
|
path("new_machine/<int:userid>", views.new_machine, name="new-machine"),
|
||||||
url(
|
path(
|
||||||
r"^edit_interface/(?P<interfaceid>[0-9]+)$",
|
"edit_interface/<int:interfaceid>",
|
||||||
views.edit_interface,
|
views.edit_interface,
|
||||||
name="edit-interface",
|
name="edit-interface",
|
||||||
),
|
),
|
||||||
url(r"^del_machine/(?P<machineid>[0-9]+)$", views.del_machine, name="del-machine"),
|
path("del_machine/<int:machineid>", views.del_machine, name="del-machine"),
|
||||||
url(
|
path(
|
||||||
r"^new_interface/(?P<machineid>[0-9]+)$",
|
"new_interface/<int:machineid>",
|
||||||
views.new_interface,
|
views.new_interface,
|
||||||
name="new-interface",
|
name="new-interface",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_interface/(?P<interfaceid>[0-9]+)$",
|
"del_interface/<int:interfaceid>",
|
||||||
views.del_interface,
|
views.del_interface,
|
||||||
name="del-interface",
|
name="del-interface",
|
||||||
),
|
),
|
||||||
url(r"^add_machinetype/$", views.add_machinetype, name="add-machinetype"),
|
path("add_machinetype", views.add_machinetype, name="add-machinetype"),
|
||||||
url(
|
path(
|
||||||
r"^edit_machinetype/(?P<machinetypeid>[0-9]+)$",
|
"edit_machinetype/<int:machinetypeid>",
|
||||||
views.edit_machinetype,
|
views.edit_machinetype,
|
||||||
name="edit-machinetype",
|
name="edit-machinetype",
|
||||||
),
|
),
|
||||||
url(r"^del_machinetype/$", views.del_machinetype, name="del-machinetype"),
|
path("del_machinetype", views.del_machinetype, name="del-machinetype"),
|
||||||
url(r"^index_machinetype/$", views.index_machinetype, name="index-machinetype"),
|
path("index_machinetype", views.index_machinetype, name="index-machinetype"),
|
||||||
url(r"^add_iptype/$", views.add_iptype, name="add-iptype"),
|
path("add_iptype", views.add_iptype, name="add-iptype"),
|
||||||
url(r"^edit_iptype/(?P<iptypeid>[0-9]+)$", views.edit_iptype, name="edit-iptype"),
|
path("edit_iptype/<int:iptypeid>", views.edit_iptype, name="edit-iptype"),
|
||||||
url(r"^del_iptype/$", views.del_iptype, name="del-iptype"),
|
path("del_iptype", views.del_iptype, name="del-iptype"),
|
||||||
url(r"^index_iptype/$", views.index_iptype, name="index-iptype"),
|
path("index_iptype", views.index_iptype, name="index-iptype"),
|
||||||
url(r"^add_extension/$", views.add_extension, name="add-extension"),
|
path("add_extension", views.add_extension, name="add-extension"),
|
||||||
url(
|
path(
|
||||||
r"^edit_extension/(?P<extensionid>[0-9]+)$",
|
"edit_extension/<int:extensionid>",
|
||||||
views.edit_extension,
|
views.edit_extension,
|
||||||
name="edit-extension",
|
name="edit-extension",
|
||||||
),
|
),
|
||||||
url(r"^del_extension/$", views.del_extension, name="del-extension"),
|
path("del_extension", views.del_extension, name="del-extension"),
|
||||||
url(r"^add_soa/$", views.add_soa, name="add-soa"),
|
path("add_soa", views.add_soa, name="add-soa"),
|
||||||
url(r"^edit_soa/(?P<soaid>[0-9]+)$", views.edit_soa, name="edit-soa"),
|
path("edit_soa/<int:soaid>", views.edit_soa, name="edit-soa"),
|
||||||
url(r"^del_soa/$", views.del_soa, name="del-soa"),
|
path("del_soa", views.del_soa, name="del-soa"),
|
||||||
url(r"^add_mx/$", views.add_mx, name="add-mx"),
|
path("add_mx", views.add_mx, name="add-mx"),
|
||||||
url(r"^edit_mx/(?P<mxid>[0-9]+)$", views.edit_mx, name="edit-mx"),
|
path("edit_mx/<int:mxid>", views.edit_mx, name="edit-mx"),
|
||||||
url(r"^del_mx/$", views.del_mx, name="del-mx"),
|
path("del_mx", views.del_mx, name="del-mx"),
|
||||||
url(r"^add_txt/$", views.add_txt, name="add-txt"),
|
path("add_txt", views.add_txt, name="add-txt"),
|
||||||
url(r"^edit_txt/(?P<txtid>[0-9]+)$", views.edit_txt, name="edit-txt"),
|
path("edit_txt/<int:txtid>", views.edit_txt, name="edit-txt"),
|
||||||
url(r"^del_txt/$", views.del_txt, name="del-txt"),
|
path("del_txt", views.del_txt, name="del-txt"),
|
||||||
url(r"^add_dname/$", views.add_dname, name="add-dname"),
|
path("add_dname", views.add_dname, name="add-dname"),
|
||||||
url(r"^edit_dname/(?P<dnameid>[0-9]+)$", views.edit_dname, name="edit-dname"),
|
path("edit_dname/<int:dnameid>", views.edit_dname, name="edit-dname"),
|
||||||
url(r"^del_dname/$", views.del_dname, name="del-dname"),
|
path("del_dname", views.del_dname, name="del-dname"),
|
||||||
url(r"^add_ns/$", views.add_ns, name="add-ns"),
|
path("add_ns", views.add_ns, name="add-ns"),
|
||||||
url(r"^edit_ns/(?P<nsid>[0-9]+)$", views.edit_ns, name="edit-ns"),
|
path("edit_ns/<int:nsid>", views.edit_ns, name="edit-ns"),
|
||||||
url(r"^del_ns/$", views.del_ns, name="del-ns"),
|
path("del_ns", views.del_ns, name="del-ns"),
|
||||||
url(r"^add_srv/$", views.add_srv, name="add-srv"),
|
path("add_srv", views.add_srv, name="add-srv"),
|
||||||
url(r"^edit_srv/(?P<srvid>[0-9]+)$", views.edit_srv, name="edit-srv"),
|
path("edit_srv/<int:srvid>", views.edit_srv, name="edit-srv"),
|
||||||
url(r"^del_srv/$", views.del_srv, name="del-srv"),
|
path("del_srv", views.del_srv, name="del-srv"),
|
||||||
url(r"^new_sshfp/(?P<machineid>[0-9]+)$", views.new_sshfp, name="new-sshfp"),
|
path("new_sshfp/<int:machineid>", views.new_sshfp, name="new-sshfp"),
|
||||||
url(r"^edit_sshfp/(?P<sshfpid>[0-9]+)$", views.edit_sshfp, name="edit-sshfp"),
|
path("edit_sshfp/<int:sshfpid>", views.edit_sshfp, name="edit-sshfp"),
|
||||||
url(r"^del_sshfp/(?P<sshfpid>[0-9]+)$", views.del_sshfp, name="del-sshfp"),
|
path("del_sshfp/<int:sshfpid>", views.del_sshfp, name="del-sshfp"),
|
||||||
url(r"^index_sshfp/(?P<machineid>[0-9]+)$", views.index_sshfp, name="index-sshfp"),
|
path("index_sshfp/<int:machineid>", views.index_sshfp, name="index-sshfp"),
|
||||||
url(r"^index_extension/$", views.index_extension, name="index-extension"),
|
path("index_extension", views.index_extension, name="index-extension"),
|
||||||
url(r"^add_alias/(?P<interfaceid>[0-9]+)$", views.add_alias, name="add-alias"),
|
path("add_alias/<int:interfaceid>", views.add_alias, name="add-alias"),
|
||||||
url(r"^edit_alias/(?P<domainid>[0-9]+)$", views.edit_alias, name="edit-alias"),
|
path("edit_alias/<int:domainid>", views.edit_alias, name="edit-alias"),
|
||||||
url(r"^del_alias/(?P<interfaceid>[0-9]+)$", views.del_alias, name="del-alias"),
|
path("del_alias/<int:interfaceid>", views.del_alias, name="del-alias"),
|
||||||
url(
|
path("index_alias/<int:interfaceid>", views.index_alias, name="index-alias"),
|
||||||
r"^index_alias/(?P<interfaceid>[0-9]+)$", views.index_alias, name="index-alias"
|
path(
|
||||||
),
|
"new_ipv6list/<int:interfaceid>",
|
||||||
url(
|
|
||||||
r"^new_ipv6list/(?P<interfaceid>[0-9]+)$",
|
|
||||||
views.new_ipv6list,
|
views.new_ipv6list,
|
||||||
name="new-ipv6list",
|
name="new-ipv6list",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^edit_ipv6list/(?P<ipv6listid>[0-9]+)$",
|
"edit_ipv6list/<int:ipv6listid>",
|
||||||
views.edit_ipv6list,
|
views.edit_ipv6list,
|
||||||
name="edit-ipv6list",
|
name="edit-ipv6list",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_ipv6list/(?P<ipv6listid>[0-9]+)$",
|
"del_ipv6list/<int:ipv6listid>",
|
||||||
views.del_ipv6list,
|
views.del_ipv6list,
|
||||||
name="del-ipv6list",
|
name="del-ipv6list",
|
||||||
),
|
),
|
||||||
url(r"^index_ipv6/(?P<interfaceid>[0-9]+)$", views.index_ipv6, name="index-ipv6"),
|
path("index_ipv6/<int:interfaceid>", views.index_ipv6, name="index-ipv6"),
|
||||||
url(r"^add_service/$", views.add_service, name="add-service"),
|
path("add_service", views.add_service, name="add-service"),
|
||||||
url(
|
path("edit_service/<int:serviceid>", views.edit_service, name="edit-service"),
|
||||||
r"^edit_service/(?P<serviceid>[0-9]+)$", views.edit_service, name="edit-service"
|
path("del_service", views.del_service, name="del-service"),
|
||||||
),
|
path(
|
||||||
url(r"^del_service/$", views.del_service, name="del-service"),
|
"regen_service/<int:serviceid>",
|
||||||
url(
|
|
||||||
r"^regen_service/(?P<serviceid>[0-9]+)$",
|
|
||||||
views.regen_service,
|
views.regen_service,
|
||||||
name="regen-service",
|
name="regen-service",
|
||||||
),
|
),
|
||||||
url(r"^index_service/$", views.index_service, name="index-service"),
|
path("index_service", views.index_service, name="index-service"),
|
||||||
url(r"^add_role/$", views.add_role, name="add-role"),
|
path("add_role", views.add_role, name="add-role"),
|
||||||
url(r"^edit_role/(?P<roleid>[0-9]+)$", views.edit_role, name="edit-role"),
|
path("edit_role/<int:roleid>", views.edit_role, name="edit-role"),
|
||||||
url(r"^del_role/$", views.del_role, name="del-role"),
|
path("del_role", views.del_role, name="del-role"),
|
||||||
url(r"^index_role/$", views.index_role, name="index-role"),
|
path("index_role", views.index_role, name="index-role"),
|
||||||
url(r"^add_vlan/$", views.add_vlan, name="add-vlan"),
|
path("add_vlan", views.add_vlan, name="add-vlan"),
|
||||||
url(r"^edit_vlan/(?P<vlanid>[0-9]+)$", views.edit_vlan, name="edit-vlan"),
|
path("edit_vlan/<int:vlanid>", views.edit_vlan, name="edit-vlan"),
|
||||||
url(r"^del_vlan/$", views.del_vlan, name="del-vlan"),
|
path("del_vlan", views.del_vlan, name="del-vlan"),
|
||||||
url(r"^index_vlan/$", views.index_vlan, name="index-vlan"),
|
path("index_vlan", views.index_vlan, name="index-vlan"),
|
||||||
url(r"^add_nas/$", views.add_nas, name="add-nas"),
|
path("add_nas", views.add_nas, name="add-nas"),
|
||||||
url(r"^edit_nas/(?P<nasid>[0-9]+)$", views.edit_nas, name="edit-nas"),
|
path("edit_nas/<int:nasid>", views.edit_nas, name="edit-nas"),
|
||||||
url(r"^del_nas/$", views.del_nas, name="del-nas"),
|
path("del_nas", views.del_nas, name="del-nas"),
|
||||||
url(r"^index_nas/$", views.index_nas, name="index-nas"),
|
path("index_nas", views.index_nas, name="index-nas"),
|
||||||
url(r"^$", views.index, name="index"),
|
path("", views.index, name="index"),
|
||||||
url(r"index_portlist/$", views.index_portlist, name="index-portlist"),
|
path("index_portlist", views.index_portlist, name="index-portlist"),
|
||||||
url(
|
path(
|
||||||
r"^edit_portlist/(?P<ouvertureportlistid>[0-9]+)$",
|
"edit_portlist/<int:ouvertureportlistid>",
|
||||||
views.edit_portlist,
|
views.edit_portlist,
|
||||||
name="edit-portlist",
|
name="edit-portlist",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_portlist/(?P<ouvertureportlistid>[0-9]+)$",
|
"del_portlist/<int:ouvertureportlistid>",
|
||||||
views.del_portlist,
|
views.del_portlist,
|
||||||
name="del-portlist",
|
name="del-portlist",
|
||||||
),
|
),
|
||||||
url(r"^add_portlist/$", views.add_portlist, name="add-portlist"),
|
path("add_portlist", views.add_portlist, name="add-portlist"),
|
||||||
url(
|
path(
|
||||||
r"^port_config/(?P<interfaceid>[0-9]+)$",
|
"port_config/<int:interfaceid>",
|
||||||
views.configure_ports,
|
views.configure_ports,
|
||||||
name="port-config",
|
name="port-config",
|
||||||
),
|
),
|
||||||
### Autocomplete Views
|
### Autocomplete Views
|
||||||
url(r'^vlan-autocomplete/$', views_autocomplete.VlanAutocomplete.as_view(), name='vlan-autocomplete',),
|
path(
|
||||||
url(r'^interface-autocomplete/$', views_autocomplete.InterfaceAutocomplete.as_view(), name='interface-autocomplete',),
|
"vlan-autocomplete",
|
||||||
url(r'^machine-autocomplete/$', views_autocomplete.MachineAutocomplete.as_view(), name='machine-autocomplete',),
|
views_autocomplete.VlanAutocomplete.as_view(),
|
||||||
url(r'^machinetype-autocomplete/$', views_autocomplete.MachineTypeAutocomplete.as_view(), name='machinetype-autocomplete',),
|
name="vlan-autocomplete",
|
||||||
url(r'^iptype-autocomplete/$', views_autocomplete.IpTypeAutocomplete.as_view(), name='iptype-autocomplete',),
|
),
|
||||||
url(r'^extension-autocomplete/$', views_autocomplete.ExtensionAutocomplete.as_view(), name='extension-autocomplete',),
|
path(
|
||||||
url(r'^domain-autocomplete/$', views_autocomplete.DomainAutocomplete.as_view(), name='domain-autocomplete',),
|
"interface-autocomplete",
|
||||||
url(r'^ouvertureportlist-autocomplete/$', views_autocomplete.OuverturePortListAutocomplete.as_view(), name='ouvertureportlist-autocomplete',),
|
views_autocomplete.InterfaceAutocomplete.as_view(),
|
||||||
url(r'^iplist-autocomplete/$', views_autocomplete.IpListAutocomplete.as_view(), name='iplist-autocomplete',),
|
name="interface-autocomplete",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"machine-autocomplete",
|
||||||
|
views_autocomplete.MachineAutocomplete.as_view(),
|
||||||
|
name="machine-autocomplete",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"machinetype-autocomplete",
|
||||||
|
views_autocomplete.MachineTypeAutocomplete.as_view(),
|
||||||
|
name="machinetype-autocomplete",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"iptype-autocomplete",
|
||||||
|
views_autocomplete.IpTypeAutocomplete.as_view(),
|
||||||
|
name="iptype-autocomplete",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"extension-autocomplete",
|
||||||
|
views_autocomplete.ExtensionAutocomplete.as_view(),
|
||||||
|
name="extension-autocomplete",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"domain-autocomplete",
|
||||||
|
views_autocomplete.DomainAutocomplete.as_view(),
|
||||||
|
name="domain-autocomplete",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"ouvertureportlist-autocomplete",
|
||||||
|
views_autocomplete.OuverturePortListAutocomplete.as_view(),
|
||||||
|
name="ouvertureportlist-autocomplete",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"iplist-autocomplete",
|
||||||
|
views_autocomplete.IpListAutocomplete.as_view(),
|
||||||
|
name="iplist-autocomplete",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -34,11 +34,11 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required, permission_required
|
from django.contrib.auth.decorators import login_required, permission_required
|
||||||
from django.db.models import ProtectedError, F
|
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
|
from django.db.models import F, ProtectedError
|
||||||
from django.forms import modelformset_factory
|
from django.forms import modelformset_factory
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import redirect, render
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
@ -46,82 +46,28 @@ from django.views.decorators.csrf import csrf_exempt
|
||||||
from rest_framework.renderers import JSONRenderer
|
from rest_framework.renderers import JSONRenderer
|
||||||
|
|
||||||
from preferences.models import GeneralOption
|
from preferences.models import GeneralOption
|
||||||
from re2o.acl import (
|
from re2o.acl import (can_create, can_delete, can_delete_set, can_edit,
|
||||||
can_create,
|
can_view, can_view_all)
|
||||||
can_edit,
|
|
||||||
can_view,
|
|
||||||
can_delete,
|
|
||||||
can_view_all,
|
|
||||||
can_delete_set,
|
|
||||||
)
|
|
||||||
from re2o.utils import all_active_assigned_interfaces, filter_active_interfaces
|
|
||||||
from re2o.base import SortTable, re2o_paginator
|
from re2o.base import SortTable, re2o_paginator
|
||||||
|
from re2o.utils import all_active_assigned_interfaces, filter_active_interfaces
|
||||||
from re2o.views import form
|
from re2o.views import form
|
||||||
from users.models import User
|
from users.models import User
|
||||||
from .forms import (
|
|
||||||
NewMachineForm,
|
from .forms import (AddInterfaceForm, AliasForm, DelAliasForm, DelDNameForm,
|
||||||
EditMachineForm,
|
DelExtensionForm, DelIpTypeForm, DelMachineTypeForm,
|
||||||
EditInterfaceForm,
|
DelMxForm, DelNasForm, DelNsForm, DelRoleForm,
|
||||||
AddInterfaceForm,
|
DelServiceForm, DelSOAForm, DelSrvForm, DelTxtForm,
|
||||||
MachineTypeForm,
|
DelVlanForm, DNameForm, DomainForm, EditInterfaceForm,
|
||||||
DelMachineTypeForm,
|
EditIpTypeForm, EditMachineForm,
|
||||||
ExtensionForm,
|
EditOuverturePortConfigForm, EditOuverturePortListForm,
|
||||||
DelExtensionForm,
|
ExtensionForm, IpTypeForm, Ipv6ListForm, MachineTypeForm,
|
||||||
EditIpTypeForm,
|
MxForm, NasForm, NewMachineForm, NsForm, RoleForm,
|
||||||
IpTypeForm,
|
ServiceForm, SOAForm, SrvForm, SshFpForm, TxtForm,
|
||||||
DelIpTypeForm,
|
VlanForm)
|
||||||
DomainForm,
|
from .models import (SOA, DName, Domain, Extension, Interface, IpType,
|
||||||
AliasForm,
|
Ipv6List, Machine, MachineType, Mx, Nas, Ns,
|
||||||
DelAliasForm,
|
OuverturePort, OuverturePortList, Role, Service,
|
||||||
SOAForm,
|
Service_link, Srv, SshFp, Txt, Vlan, regen)
|
||||||
DelSOAForm,
|
|
||||||
NsForm,
|
|
||||||
DelNsForm,
|
|
||||||
TxtForm,
|
|
||||||
DelTxtForm,
|
|
||||||
DNameForm,
|
|
||||||
DelDNameForm,
|
|
||||||
MxForm,
|
|
||||||
DelMxForm,
|
|
||||||
VlanForm,
|
|
||||||
DelVlanForm,
|
|
||||||
RoleForm,
|
|
||||||
DelRoleForm,
|
|
||||||
ServiceForm,
|
|
||||||
DelServiceForm,
|
|
||||||
SshFpForm,
|
|
||||||
NasForm,
|
|
||||||
DelNasForm,
|
|
||||||
SrvForm,
|
|
||||||
DelSrvForm,
|
|
||||||
Ipv6ListForm,
|
|
||||||
EditOuverturePortListForm,
|
|
||||||
EditOuverturePortConfigForm,
|
|
||||||
)
|
|
||||||
from .models import (
|
|
||||||
IpType,
|
|
||||||
Machine,
|
|
||||||
Interface,
|
|
||||||
MachineType,
|
|
||||||
Extension,
|
|
||||||
SOA,
|
|
||||||
Mx,
|
|
||||||
Ns,
|
|
||||||
Domain,
|
|
||||||
Role,
|
|
||||||
Service,
|
|
||||||
Service_link,
|
|
||||||
regen,
|
|
||||||
Vlan,
|
|
||||||
Nas,
|
|
||||||
Txt,
|
|
||||||
DName,
|
|
||||||
Srv,
|
|
||||||
SshFp,
|
|
||||||
OuverturePortList,
|
|
||||||
OuverturePort,
|
|
||||||
Ipv6List,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -135,7 +81,9 @@ def new_machine(request, user, **_kwargs):
|
||||||
"""
|
"""
|
||||||
machine = NewMachineForm(request.POST or None, user=request.user)
|
machine = NewMachineForm(request.POST or None, user=request.user)
|
||||||
interface = AddInterfaceForm(request.POST or None, user=request.user)
|
interface = AddInterfaceForm(request.POST or None, user=request.user)
|
||||||
domain = DomainForm(request.POST or None, user=user, initial={'name': user.get_next_domain_name()})
|
domain = DomainForm(
|
||||||
|
request.POST or None, user=user, initial={"name": user.get_next_domain_name()}
|
||||||
|
)
|
||||||
if machine.is_valid() and interface.is_valid():
|
if machine.is_valid() and interface.is_valid():
|
||||||
new_machine_obj = machine.save(commit=False)
|
new_machine_obj = machine.save(commit=False)
|
||||||
new_machine_obj.user = user
|
new_machine_obj.user = user
|
||||||
|
@ -229,7 +177,11 @@ def new_interface(request, machine, **_kwargs):
|
||||||
machine.
|
machine.
|
||||||
"""
|
"""
|
||||||
interface_form = AddInterfaceForm(request.POST or None, user=request.user)
|
interface_form = AddInterfaceForm(request.POST or None, user=request.user)
|
||||||
domain_form = DomainForm(request.POST or None, user=request.user, initial={'name': machine.user.get_next_domain_name()})
|
domain_form = DomainForm(
|
||||||
|
request.POST or None,
|
||||||
|
user=request.user,
|
||||||
|
initial={"name": machine.user.get_next_domain_name()},
|
||||||
|
)
|
||||||
if interface_form.is_valid():
|
if interface_form.is_valid():
|
||||||
new_interface_obj = interface_form.save(commit=False)
|
new_interface_obj = interface_form.save(commit=False)
|
||||||
domain_form.instance.interface_parent = new_interface_obj
|
domain_form.instance.interface_parent = new_interface_obj
|
||||||
|
@ -268,7 +220,9 @@ def del_interface(request, interface, **_kwargs):
|
||||||
reverse("users:profil", kwargs={"userid": str(request.user.id)})
|
reverse("users:profil", kwargs={"userid": str(request.user.id)})
|
||||||
)
|
)
|
||||||
return form(
|
return form(
|
||||||
{"objet": interface, "objet_name": _("interface")}, "machines/delete.html", request
|
{"objet": interface, "objet_name": _("interface")},
|
||||||
|
"machines/delete.html",
|
||||||
|
request,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -328,7 +282,9 @@ def del_ipv6list(request, ipv6list, **_kwargs):
|
||||||
reverse("machines:index-ipv6", kwargs={"interfaceid": str(interfaceid)})
|
reverse("machines:index-ipv6", kwargs={"interfaceid": str(interfaceid)})
|
||||||
)
|
)
|
||||||
return form(
|
return form(
|
||||||
{"objet": ipv6list, "objet_name": _("IPv6 addresses list")}, "machines/delete.html", request
|
{"objet": ipv6list, "objet_name": _("IPv6 addresses list")},
|
||||||
|
"machines/delete.html",
|
||||||
|
request,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,7 +340,9 @@ def del_sshfp(request, sshfp, **_kwargs):
|
||||||
reverse("machines:index-sshfp", kwargs={"machineid": str(machineid)})
|
reverse("machines:index-sshfp", kwargs={"machineid": str(machineid)})
|
||||||
)
|
)
|
||||||
return form(
|
return form(
|
||||||
{"objet": sshfp, "objet_name": _("SSHFP record")}, "machines/delete.html", request
|
{"objet": sshfp, "objet_name": _("SSHFP record")},
|
||||||
|
"machines/delete.html",
|
||||||
|
request,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -421,7 +379,9 @@ def edit_iptype(request, iptype_instance, **_kwargs):
|
||||||
iptype.save()
|
iptype.save()
|
||||||
messages.success(request, _("The IP type was edited."))
|
messages.success(request, _("The IP type was edited."))
|
||||||
except IntegrityError as e:
|
except IntegrityError as e:
|
||||||
messages.success(request, _("This IP type change would create duplicated domains"))
|
messages.success(
|
||||||
|
request, _("This IP type change would create duplicated domains")
|
||||||
|
)
|
||||||
return redirect(reverse("machines:index-iptype"))
|
return redirect(reverse("machines:index-iptype"))
|
||||||
return form(
|
return form(
|
||||||
{"iptypeform": iptype, "action_name": _("Edit")},
|
{"iptypeform": iptype, "action_name": _("Edit")},
|
||||||
|
@ -490,7 +450,10 @@ def edit_machinetype(request, machinetype_instance, **_kwargs):
|
||||||
machinetype.save()
|
machinetype.save()
|
||||||
messages.success(request, _("The machine type was edited."))
|
messages.success(request, _("The machine type was edited."))
|
||||||
except IntegrityError as e:
|
except IntegrityError as e:
|
||||||
messages.error(request, _("This machine type change would create duplicated domains"))
|
messages.error(
|
||||||
|
request,
|
||||||
|
_("This machine type change would create duplicated domains"),
|
||||||
|
)
|
||||||
return redirect(reverse("machines:index-machinetype"))
|
return redirect(reverse("machines:index-machinetype"))
|
||||||
return form(
|
return form(
|
||||||
{"machinetypeform": machinetype, "action_name": _("Edit")},
|
{"machinetypeform": machinetype, "action_name": _("Edit")},
|
||||||
|
@ -580,10 +543,16 @@ def del_extension(request, instances):
|
||||||
_(
|
_(
|
||||||
"The extension %s is assigned to following %s : %s"
|
"The extension %s is assigned to following %s : %s"
|
||||||
", you can't delete it."
|
", you can't delete it."
|
||||||
) % (
|
)
|
||||||
|
% (
|
||||||
extension_del,
|
extension_del,
|
||||||
str(e.protected_objects.model._meta.verbose_name_plural),
|
str(e.protected_objects.model._meta.verbose_name_plural),
|
||||||
",".join(map(lambda x: str(x['name']), e.protected_objects.values('name').iterator()))
|
",".join(
|
||||||
|
map(
|
||||||
|
lambda x: str(x["name"]),
|
||||||
|
e.protected_objects.values("name").iterator(),
|
||||||
|
)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -1221,11 +1190,12 @@ def index(request):
|
||||||
machines_list = re2o_paginator(request, machines_list, pagination_large_number)
|
machines_list = re2o_paginator(request, machines_list, pagination_large_number)
|
||||||
return render(request, "machines/index.html", {"machines_list": machines_list})
|
return render(request, "machines/index.html", {"machines_list": machines_list})
|
||||||
|
|
||||||
|
|
||||||
# Canonic view for displaying machines in users's profil
|
# Canonic view for displaying machines in users's profil
|
||||||
def aff_profil(request, user):
|
def aff_profil(request, user):
|
||||||
"""View used to display the machines on a user's profile."""
|
"""View used to display the machines on a user's profile."""
|
||||||
machines = (
|
machines = (
|
||||||
Machine.objects.filter(user=user)
|
Machine.objects.filter(user=user)
|
||||||
.select_related("user")
|
.select_related("user")
|
||||||
.prefetch_related("interface_set__domain__extension")
|
.prefetch_related("interface_set__domain__extension")
|
||||||
.prefetch_related("interface_set__ipv4__ip_type__extension")
|
.prefetch_related("interface_set__ipv4__ip_type__extension")
|
||||||
|
@ -1243,19 +1213,16 @@ def aff_profil(request, user):
|
||||||
machines = re2o_paginator(request, machines, pagination_large_number)
|
machines = re2o_paginator(request, machines, pagination_large_number)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"users":user,
|
"users": user,
|
||||||
"machines_list": machines,
|
"machines_list": machines,
|
||||||
"nb_machines":nb_machines,
|
"nb_machines": nb_machines,
|
||||||
}
|
}
|
||||||
|
|
||||||
return render_to_string(
|
return render_to_string(
|
||||||
"machines/aff_profil.html",context=context,request=request,using=None
|
"machines/aff_profil.html", context=context, request=request, using=None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@can_view_all(IpType)
|
@can_view_all(IpType)
|
||||||
def index_iptype(request):
|
def index_iptype(request):
|
||||||
|
@ -1531,4 +1498,3 @@ def configure_ports(request, interface_instance, **_kwargs):
|
||||||
"machines/machine.html",
|
"machines/machine.html",
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -31,23 +31,14 @@ Here are defined the autocomplete class based view.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db.models import Q, Value, CharField
|
from django.db.models import CharField, Q, Value
|
||||||
from django.db.models.functions import Concat
|
from django.db.models.functions import Concat
|
||||||
|
|
||||||
from .models import (
|
|
||||||
Interface,
|
|
||||||
Machine,
|
|
||||||
Vlan,
|
|
||||||
MachineType,
|
|
||||||
IpType,
|
|
||||||
Extension,
|
|
||||||
Domain,
|
|
||||||
OuverturePortList,
|
|
||||||
IpList,
|
|
||||||
)
|
|
||||||
|
|
||||||
from re2o.views import AutocompleteViewMixin
|
from re2o.views import AutocompleteViewMixin
|
||||||
|
|
||||||
|
from .models import (Domain, Extension, Interface, IpList, IpType, Machine,
|
||||||
|
MachineType, OuverturePortList, Vlan)
|
||||||
|
|
||||||
|
|
||||||
class VlanAutocomplete(AutocompleteViewMixin):
|
class VlanAutocomplete(AutocompleteViewMixin):
|
||||||
obj_type = Vlan
|
obj_type = Vlan
|
||||||
|
|
|
@ -27,11 +27,11 @@ Select a dorm
|
||||||
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import ModelForm, Form
|
from django.forms import Form, ModelForm
|
||||||
from re2o.field_permissions import FieldPermissionFormMixin
|
|
||||||
from re2o.mixins import FormRevMixin
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from re2o.field_permissions import FieldPermissionFormMixin
|
||||||
|
from re2o.mixins import FormRevMixin
|
||||||
from topologie.models import Dormitory
|
from topologie.models import Dormitory
|
||||||
|
|
||||||
from .preferences.models import MultiopOption
|
from .preferences.models import MultiopOption
|
||||||
|
@ -49,4 +49,6 @@ class DormitoryForm(FormRevMixin, Form):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(DormitoryForm, self).__init__(*args, **kwargs)
|
super(DormitoryForm, self).__init__(*args, **kwargs)
|
||||||
self.fields["dormitory"].queryset = MultiopOption.get_cached_value("enabled_dorm").all()
|
self.fields["dormitory"].queryset = MultiopOption.get_cached_value(
|
||||||
|
"enabled_dorm"
|
||||||
|
).all()
|
||||||
|
|
|
@ -25,21 +25,18 @@ Multi_op model
|
||||||
|
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
from django.core.mail import EmailMessage
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
|
||||||
from django.template import loader
|
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
|
from django.template import loader
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from reversion.models import Version
|
from reversion.models import Version
|
||||||
|
|
||||||
from re2o.mixins import AclMixin
|
|
||||||
from re2o.mail_utils import send_mail_object
|
|
||||||
from django.core.mail import EmailMessage
|
|
||||||
|
|
||||||
from preferences.models import GeneralOption
|
|
||||||
|
|
||||||
import users.models
|
import users.models
|
||||||
|
from preferences.models import GeneralOption
|
||||||
|
from re2o.mail_utils import send_mail_object
|
||||||
|
from re2o.mixins import AclMixin
|
||||||
|
|
||||||
from .preferences.models import MultiopOption
|
from .preferences.models import MultiopOption
|
||||||
|
|
|
@ -27,8 +27,9 @@ each.
|
||||||
|
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import ModelForm, Form
|
from django.forms import Form, ModelForm
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from re2o.widgets import AutocompleteMultipleModelWidget
|
from re2o.widgets import AutocompleteMultipleModelWidget
|
||||||
|
|
||||||
from .models import MultiopOption
|
from .models import MultiopOption
|
||||||
|
|
|
@ -27,8 +27,8 @@ with multiple operators.
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from re2o.mixins import AclMixin, RevMixin
|
|
||||||
from preferences.models import PreferencesModel
|
from preferences.models import PreferencesModel
|
||||||
|
from re2o.mixins import AclMixin, RevMixin
|
||||||
|
|
||||||
|
|
||||||
class MultiopOption(AclMixin, PreferencesModel):
|
class MultiopOption(AclMixin, PreferencesModel):
|
||||||
|
|
|
@ -26,20 +26,16 @@
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import redirect, render
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
from re2o.base import re2o_paginator
|
|
||||||
|
|
||||||
from re2o.acl import can_view, can_view_all, can_edit, can_create
|
|
||||||
|
|
||||||
from preferences.views import edit_options_template_function
|
from preferences.views import edit_options_template_function
|
||||||
|
from re2o.acl import can_create, can_edit, can_view, can_view_all
|
||||||
|
from re2o.base import re2o_paginator
|
||||||
|
|
||||||
from . import forms
|
from . import forms, models
|
||||||
from . import models
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def aff_preferences(request):
|
def aff_preferences(request):
|
||||||
|
|
|
@ -25,35 +25,37 @@ For further details on each of those models, see the documentation details for
|
||||||
each.
|
each.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.urls import path, re_path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
from .preferences.views import edit_options
|
from .preferences.views import edit_options
|
||||||
|
|
||||||
|
app_name = "multi_op"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r"^$", views.aff_state_global, name="aff-state-global"),
|
path("", views.aff_state_global, name="aff-state-global"),
|
||||||
url(
|
path(
|
||||||
r"^(?P<dormitoryid>[0-9]+)$",
|
"<int:dormitoryid>",
|
||||||
views.aff_state_dormitory,
|
views.aff_state_dormitory,
|
||||||
name="aff-state-dormitory",
|
name="aff-state-dormitory",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>MultiopOption)$",
|
r"^edit_options/(?P<section>MultiopOption)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^pending-connection$",
|
"pending-connection",
|
||||||
views.aff_pending_connection,
|
views.aff_pending_connection,
|
||||||
name="aff-pending-connection",
|
name="aff-pending-connection",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^pending-disconnection$",
|
"pending-disconnection",
|
||||||
views.aff_pending_disconnection,
|
views.aff_pending_disconnection,
|
||||||
name="aff-pending-disconnection",
|
name="aff-pending-disconnection",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^disconnect-room/(?P<roomid>[0-9]+)$",
|
"disconnect-room/<int:roomid>",
|
||||||
views.disconnect_room,
|
views.disconnect_room,
|
||||||
name="disconnect-room",
|
name="disconnect-room",
|
||||||
),
|
),
|
||||||
|
|
|
@ -27,28 +27,24 @@
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.shortcuts import render, redirect
|
|
||||||
from django.template.loader import render_to_string
|
|
||||||
from django.views.decorators.cache import cache_page
|
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from django.urls import reverse
|
|
||||||
from django.forms import modelformset_factory
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
from django.forms import modelformset_factory
|
||||||
|
from django.shortcuts import redirect, render
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from django.views.decorators.cache import cache_page
|
||||||
|
|
||||||
|
from preferences.models import AssoOption, GeneralOption
|
||||||
|
from re2o.acl import can_create, can_edit, can_view, can_view_all
|
||||||
|
from re2o.base import SortTable, re2o_paginator
|
||||||
|
from re2o.utils import all_adherent, all_has_access
|
||||||
from re2o.views import form
|
from re2o.views import form
|
||||||
from re2o.utils import all_has_access, all_adherent
|
from topologie.models import Dormitory, Room
|
||||||
|
|
||||||
from re2o.base import re2o_paginator, SortTable
|
|
||||||
|
|
||||||
from re2o.acl import can_view, can_view_all, can_edit, can_create
|
|
||||||
|
|
||||||
from preferences.models import GeneralOption, AssoOption
|
|
||||||
|
|
||||||
from .forms import DormitoryForm
|
from .forms import DormitoryForm
|
||||||
|
|
||||||
from .preferences.models import MultiopOption
|
from .preferences.models import MultiopOption
|
||||||
|
|
||||||
from topologie.models import Room, Dormitory
|
|
||||||
|
|
||||||
|
|
||||||
def display_rooms_connection(request, dormitory=None):
|
def display_rooms_connection(request, dormitory=None):
|
||||||
"""View used to display an overview of the rooms' connection state.
|
"""View used to display an overview of the rooms' connection state.
|
||||||
|
@ -58,9 +54,13 @@ def display_rooms_connection(request, dormitory=None):
|
||||||
dormitory: Dormitory, the dormitory used to filter rooms. If no
|
dormitory: Dormitory, the dormitory used to filter rooms. If no
|
||||||
dormitory is given, all rooms are displayed (default: None).
|
dormitory is given, all rooms are displayed (default: None).
|
||||||
"""
|
"""
|
||||||
room_list = Room.objects.select_related("building__dormitory").filter(
|
room_list = (
|
||||||
building__dormitory__in=MultiopOption.get_cached_value("enabled_dorm").all()
|
Room.objects.select_related("building__dormitory")
|
||||||
).order_by("building_dormitory", "port")
|
.filter(
|
||||||
|
building__dormitory__in=MultiopOption.get_cached_value("enabled_dorm").all()
|
||||||
|
)
|
||||||
|
.order_by("building_dormitory", "port")
|
||||||
|
)
|
||||||
if dormitory:
|
if dormitory:
|
||||||
room_list = room_list.filter(building__dormitory=dormitory)
|
room_list = room_list.filter(building__dormitory=dormitory)
|
||||||
room_list = SortTable.sort(
|
room_list = SortTable.sort(
|
||||||
|
@ -113,7 +113,9 @@ def aff_pending_connection(request):
|
||||||
Room.objects.select_related("building__dormitory")
|
Room.objects.select_related("building__dormitory")
|
||||||
.filter(port__isnull=True)
|
.filter(port__isnull=True)
|
||||||
.filter(adherent__in=all_has_access())
|
.filter(adherent__in=all_has_access())
|
||||||
.filter(building__dormitory__in=MultiopOption.get_cached_value("enabled_dorm").all())
|
.filter(
|
||||||
|
building__dormitory__in=MultiopOption.get_cached_value("enabled_dorm").all()
|
||||||
|
)
|
||||||
.order_by("building_dormitory", "port")
|
.order_by("building_dormitory", "port")
|
||||||
)
|
)
|
||||||
dormitory_form = DormitoryForm(request.POST or None)
|
dormitory_form = DormitoryForm(request.POST or None)
|
||||||
|
@ -151,7 +153,9 @@ def aff_pending_disconnection(request):
|
||||||
Room.objects.select_related("building__dormitory")
|
Room.objects.select_related("building__dormitory")
|
||||||
.filter(port__isnull=False)
|
.filter(port__isnull=False)
|
||||||
.exclude(Q(adherent__in=all_has_access()) | Q(adherent__in=all_adherent()))
|
.exclude(Q(adherent__in=all_has_access()) | Q(adherent__in=all_adherent()))
|
||||||
.filter(building__dormitory__in=MultiopOption.get_cached_value("enabled_dorm").all())
|
.filter(
|
||||||
|
building__dormitory__in=MultiopOption.get_cached_value("enabled_dorm").all()
|
||||||
|
)
|
||||||
.order_by("building_dormitory", "port")
|
.order_by("building_dormitory", "port")
|
||||||
)
|
)
|
||||||
dormitory_form = DormitoryForm(request.POST or None)
|
dormitory_form = DormitoryForm(request.POST or None)
|
||||||
|
|
142
mysql-requirements.txt
Normal file
142
mysql-requirements.txt
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
django-autocomplete-light==3.8.1 \
|
||||||
|
--hash=sha256:4e84a6d95d272b0d7221614332e2bd54ffff15ec06e78947279398f6507ce225
|
||||||
|
django-bootstrap3==14.2.0; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:1fc3db37f29bcd159c0b00e1f15fd2d6dedf7551ce8bcca09072e33663c110de \
|
||||||
|
--hash=sha256:c7e6912b5127bea913bc8504399613758760954140162e048184624765e61904
|
||||||
|
django-ldapdb==1.5.1; python_version >= "3.6" \
|
||||||
|
--hash=sha256:5ea333c3130abbb86f8629766370a7f490878706469fce4e5008e41fb566392a \
|
||||||
|
--hash=sha256:2daee828a7eb1ce6ad0634ce5311339d77c08128829e575ff14d62a46771b86a
|
||||||
|
django-macaddress==1.7.0 \
|
||||||
|
--hash=sha256:342aa3421ee19acc3661d1705dad2ae674eaa7d06a02799f7a5dc394d6233275 \
|
||||||
|
--hash=sha256:db8beedcbd708aba3a6c9e83de6527efa2f9cc7dbe698406cebdfdbaf98c896d
|
||||||
|
django-rest-framework==0.1.0 \
|
||||||
|
--hash=sha256:47a8f496fa69e3b6bd79f68dd7a1527d907d6b77f009e9db7cf9bb21cc565e4a
|
||||||
|
django-reversion==3.0.9; python_version >= "3.6" \
|
||||||
|
--hash=sha256:a5af55f086a3f9c38be2f049c251e06005b9ed48ba7a109473736b1fc95a066f \
|
||||||
|
--hash=sha256:1b57127a136b969f4b843a915c72af271febe7f336469db6c27121f8adcad35c
|
||||||
|
django==2.2.18; python_version >= "3.5" \
|
||||||
|
--hash=sha256:0eaca08f236bf502a9773e53623f766cc3ceee6453cc41e6de1c8b80f07d2364 \
|
||||||
|
--hash=sha256:c9c994f5e0a032cbd45089798b52e4080f4dea7241c58e3e0636c54146480bb4
|
||||||
|
djangorestframework==3.12.2; python_version >= "3.5" \
|
||||||
|
--hash=sha256:0209bafcb7b5010fdfec784034f059d512256424de2a0f084cb82b096d6dd6a7 \
|
||||||
|
--hash=sha256:0898182b4737a7b584a2c73735d89816343369f259fea932d90dc78e35d8ac33
|
||||||
|
gitdb==4.0.5; python_version >= "3.4" \
|
||||||
|
--hash=sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac \
|
||||||
|
--hash=sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9
|
||||||
|
gitpython==3.1.13; python_version >= "3.4" \
|
||||||
|
--hash=sha256:c5347c81d232d9b8e7f47b68a83e5dc92e7952127133c5f2df9133f2c75a1b29 \
|
||||||
|
--hash=sha256:8621a7e777e276a5ec838b59280ba5272dd144a18169c36c903d8b38b99f750a
|
||||||
|
importlib-metadata==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_version >= "3.6" and python_version < "3.8" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070 \
|
||||||
|
--hash=sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83
|
||||||
|
importlib-resources==5.1.0; python_version >= "3.6" and python_version < "3.7" \
|
||||||
|
--hash=sha256:885b8eae589179f661c909d699a546cf10d83692553e34dca1bf5eb06f7f6217 \
|
||||||
|
--hash=sha256:bfdad047bce441405a49cf8eb48ddce5e56c696e185f59147a8b79e75e9e6380
|
||||||
|
mysqlclient==2.0.3; python_version >= "3.5" \
|
||||||
|
--hash=sha256:3381ca1a4f37ff1155fcfde20836b46416d66531add8843f6aa6d968982731c3 \
|
||||||
|
--hash=sha256:0ac0dd759c4ca02c35a9fedc24bc982cf75171651e8187c2495ec957a87dfff7 \
|
||||||
|
--hash=sha256:71c4b330cf2313bbda0307fc858cc9055e64493ba9bf28454d25cf8b3ee8d7f5 \
|
||||||
|
--hash=sha256:fc575093cf81b6605bed84653e48b277318b880dc9becf42dd47fa11ffd3e2b6 \
|
||||||
|
--hash=sha256:f6ebea7c008f155baeefe16c56cd3ee6239f7a5a9ae42396c2f1860f08a7c432
|
||||||
|
netaddr==0.8.0 \
|
||||||
|
--hash=sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac \
|
||||||
|
--hash=sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243
|
||||||
|
pillow==8.1.0; python_version >= "3.6" \
|
||||||
|
--hash=sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a \
|
||||||
|
--hash=sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2 \
|
||||||
|
--hash=sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174 \
|
||||||
|
--hash=sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded \
|
||||||
|
--hash=sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d \
|
||||||
|
--hash=sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d \
|
||||||
|
--hash=sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234 \
|
||||||
|
--hash=sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8 \
|
||||||
|
--hash=sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17 \
|
||||||
|
--hash=sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7 \
|
||||||
|
--hash=sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e \
|
||||||
|
--hash=sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b \
|
||||||
|
--hash=sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0 \
|
||||||
|
--hash=sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a \
|
||||||
|
--hash=sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d \
|
||||||
|
--hash=sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae \
|
||||||
|
--hash=sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59 \
|
||||||
|
--hash=sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c \
|
||||||
|
--hash=sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6 \
|
||||||
|
--hash=sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378 \
|
||||||
|
--hash=sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7 \
|
||||||
|
--hash=sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0 \
|
||||||
|
--hash=sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b \
|
||||||
|
--hash=sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865 \
|
||||||
|
--hash=sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9 \
|
||||||
|
--hash=sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913 \
|
||||||
|
--hash=sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206 \
|
||||||
|
--hash=sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9 \
|
||||||
|
--hash=sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032 \
|
||||||
|
--hash=sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820 \
|
||||||
|
--hash=sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5 \
|
||||||
|
--hash=sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba
|
||||||
|
psycopg2==2.8.6; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \
|
||||||
|
--hash=sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725 \
|
||||||
|
--hash=sha256:d160744652e81c80627a909a0e808f3c6653a40af435744de037e3172cf277f5 \
|
||||||
|
--hash=sha256:b8cae8b2f022efa1f011cc753adb9cbadfa5a184431d09b273fb49b4167561ad \
|
||||||
|
--hash=sha256:f22ea9b67aea4f4a1718300908a2fb62b3e4276cf00bd829a97ab5894af42ea3 \
|
||||||
|
--hash=sha256:26e7fd115a6db75267b325de0fba089b911a4a12ebd3d0b5e7acb7028bc46821 \
|
||||||
|
--hash=sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301 \
|
||||||
|
--hash=sha256:a49833abfdede8985ba3f3ec641f771cca215479f41523e99dace96d5b8cce2a \
|
||||||
|
--hash=sha256:f974c96fca34ae9e4f49839ba6b78addf0346777b46c4da27a7bf54f48d3057d \
|
||||||
|
--hash=sha256:6a3d9efb6f36f1fe6aa8dbb5af55e067db802502c55a9defa47c5a1dad41df84 \
|
||||||
|
--hash=sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5 \
|
||||||
|
--hash=sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e \
|
||||||
|
--hash=sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051 \
|
||||||
|
--hash=sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3 \
|
||||||
|
--hash=sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7 \
|
||||||
|
--hash=sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543
|
||||||
|
pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
|
||||||
|
--hash=sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199 \
|
||||||
|
--hash=sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405 \
|
||||||
|
--hash=sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb \
|
||||||
|
--hash=sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8 \
|
||||||
|
--hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74 \
|
||||||
|
--hash=sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d \
|
||||||
|
--hash=sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45 \
|
||||||
|
--hash=sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4 \
|
||||||
|
--hash=sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811 \
|
||||||
|
--hash=sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed \
|
||||||
|
--hash=sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0 \
|
||||||
|
--hash=sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd
|
||||||
|
pyasn1==0.4.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3 \
|
||||||
|
--hash=sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf \
|
||||||
|
--hash=sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00 \
|
||||||
|
--hash=sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8 \
|
||||||
|
--hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
|
||||||
|
--hash=sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86 \
|
||||||
|
--hash=sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7 \
|
||||||
|
--hash=sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576 \
|
||||||
|
--hash=sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12 \
|
||||||
|
--hash=sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2 \
|
||||||
|
--hash=sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359 \
|
||||||
|
--hash=sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776 \
|
||||||
|
--hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
|
||||||
|
pycrypto==2.6.1 \
|
||||||
|
--hash=sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c
|
||||||
|
python-dateutil==2.8.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0") \
|
||||||
|
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
|
||||||
|
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a
|
||||||
|
python-ldap==3.3.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:4711cacf013e298754abd70058ccc995758177fb425f1c2d30e71adfc1d00aa5
|
||||||
|
pytz==2021.1; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798 \
|
||||||
|
--hash=sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da
|
||||||
|
six==1.15.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" \
|
||||||
|
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced \
|
||||||
|
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259
|
||||||
|
smmap==3.0.5; python_version >= "3.4" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.4" \
|
||||||
|
--hash=sha256:7bfcf367828031dc893530a29cb35eb8c8f2d7c8f2d0989354d75d24c8573714 \
|
||||||
|
--hash=sha256:84c2751ef3072d4f6b2785ec7ee40244c6f45eb934d9e543e2c51f1bd3d54c50
|
||||||
|
sqlparse==0.4.1; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0 \
|
||||||
|
--hash=sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8
|
||||||
|
zipp==3.4.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108 \
|
||||||
|
--hash=sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb
|
1213
poetry.lock
generated
Normal file
1213
poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
142
postgresql-requirements.txt
Normal file
142
postgresql-requirements.txt
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
django-autocomplete-light==3.8.1 \
|
||||||
|
--hash=sha256:4e84a6d95d272b0d7221614332e2bd54ffff15ec06e78947279398f6507ce225
|
||||||
|
django-bootstrap3==14.2.0; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:1fc3db37f29bcd159c0b00e1f15fd2d6dedf7551ce8bcca09072e33663c110de \
|
||||||
|
--hash=sha256:c7e6912b5127bea913bc8504399613758760954140162e048184624765e61904
|
||||||
|
django-ldapdb==1.5.1; python_version >= "3.6" \
|
||||||
|
--hash=sha256:5ea333c3130abbb86f8629766370a7f490878706469fce4e5008e41fb566392a \
|
||||||
|
--hash=sha256:2daee828a7eb1ce6ad0634ce5311339d77c08128829e575ff14d62a46771b86a
|
||||||
|
django-macaddress==1.7.0 \
|
||||||
|
--hash=sha256:342aa3421ee19acc3661d1705dad2ae674eaa7d06a02799f7a5dc394d6233275 \
|
||||||
|
--hash=sha256:db8beedcbd708aba3a6c9e83de6527efa2f9cc7dbe698406cebdfdbaf98c896d
|
||||||
|
django-rest-framework==0.1.0 \
|
||||||
|
--hash=sha256:47a8f496fa69e3b6bd79f68dd7a1527d907d6b77f009e9db7cf9bb21cc565e4a
|
||||||
|
django-reversion==3.0.9; python_version >= "3.6" \
|
||||||
|
--hash=sha256:a5af55f086a3f9c38be2f049c251e06005b9ed48ba7a109473736b1fc95a066f \
|
||||||
|
--hash=sha256:1b57127a136b969f4b843a915c72af271febe7f336469db6c27121f8adcad35c
|
||||||
|
django==2.2.18; python_version >= "3.5" \
|
||||||
|
--hash=sha256:0eaca08f236bf502a9773e53623f766cc3ceee6453cc41e6de1c8b80f07d2364 \
|
||||||
|
--hash=sha256:c9c994f5e0a032cbd45089798b52e4080f4dea7241c58e3e0636c54146480bb4
|
||||||
|
djangorestframework==3.12.2; python_version >= "3.5" \
|
||||||
|
--hash=sha256:0209bafcb7b5010fdfec784034f059d512256424de2a0f084cb82b096d6dd6a7 \
|
||||||
|
--hash=sha256:0898182b4737a7b584a2c73735d89816343369f259fea932d90dc78e35d8ac33
|
||||||
|
gitdb==4.0.5; python_version >= "3.4" \
|
||||||
|
--hash=sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac \
|
||||||
|
--hash=sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9
|
||||||
|
gitpython==3.1.13; python_version >= "3.4" \
|
||||||
|
--hash=sha256:c5347c81d232d9b8e7f47b68a83e5dc92e7952127133c5f2df9133f2c75a1b29 \
|
||||||
|
--hash=sha256:8621a7e777e276a5ec838b59280ba5272dd144a18169c36c903d8b38b99f750a
|
||||||
|
importlib-metadata==1.7.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.8" or python_version >= "3.6" and python_version < "3.8" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070 \
|
||||||
|
--hash=sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83
|
||||||
|
importlib-resources==5.1.0; python_version >= "3.6" and python_version < "3.7" \
|
||||||
|
--hash=sha256:885b8eae589179f661c909d699a546cf10d83692553e34dca1bf5eb06f7f6217 \
|
||||||
|
--hash=sha256:bfdad047bce441405a49cf8eb48ddce5e56c696e185f59147a8b79e75e9e6380
|
||||||
|
mysqlclient==2.0.3; python_version >= "3.5" \
|
||||||
|
--hash=sha256:3381ca1a4f37ff1155fcfde20836b46416d66531add8843f6aa6d968982731c3 \
|
||||||
|
--hash=sha256:0ac0dd759c4ca02c35a9fedc24bc982cf75171651e8187c2495ec957a87dfff7 \
|
||||||
|
--hash=sha256:71c4b330cf2313bbda0307fc858cc9055e64493ba9bf28454d25cf8b3ee8d7f5 \
|
||||||
|
--hash=sha256:fc575093cf81b6605bed84653e48b277318b880dc9becf42dd47fa11ffd3e2b6 \
|
||||||
|
--hash=sha256:f6ebea7c008f155baeefe16c56cd3ee6239f7a5a9ae42396c2f1860f08a7c432
|
||||||
|
netaddr==0.8.0 \
|
||||||
|
--hash=sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac \
|
||||||
|
--hash=sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243
|
||||||
|
pillow==8.1.0; python_version >= "3.6" \
|
||||||
|
--hash=sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a \
|
||||||
|
--hash=sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2 \
|
||||||
|
--hash=sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174 \
|
||||||
|
--hash=sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded \
|
||||||
|
--hash=sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d \
|
||||||
|
--hash=sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d \
|
||||||
|
--hash=sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234 \
|
||||||
|
--hash=sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8 \
|
||||||
|
--hash=sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17 \
|
||||||
|
--hash=sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7 \
|
||||||
|
--hash=sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e \
|
||||||
|
--hash=sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b \
|
||||||
|
--hash=sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0 \
|
||||||
|
--hash=sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a \
|
||||||
|
--hash=sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d \
|
||||||
|
--hash=sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae \
|
||||||
|
--hash=sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59 \
|
||||||
|
--hash=sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c \
|
||||||
|
--hash=sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6 \
|
||||||
|
--hash=sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378 \
|
||||||
|
--hash=sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7 \
|
||||||
|
--hash=sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0 \
|
||||||
|
--hash=sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b \
|
||||||
|
--hash=sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865 \
|
||||||
|
--hash=sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9 \
|
||||||
|
--hash=sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913 \
|
||||||
|
--hash=sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206 \
|
||||||
|
--hash=sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9 \
|
||||||
|
--hash=sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032 \
|
||||||
|
--hash=sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820 \
|
||||||
|
--hash=sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5 \
|
||||||
|
--hash=sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba
|
||||||
|
psycopg2==2.8.6; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") \
|
||||||
|
--hash=sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725 \
|
||||||
|
--hash=sha256:d160744652e81c80627a909a0e808f3c6653a40af435744de037e3172cf277f5 \
|
||||||
|
--hash=sha256:b8cae8b2f022efa1f011cc753adb9cbadfa5a184431d09b273fb49b4167561ad \
|
||||||
|
--hash=sha256:f22ea9b67aea4f4a1718300908a2fb62b3e4276cf00bd829a97ab5894af42ea3 \
|
||||||
|
--hash=sha256:26e7fd115a6db75267b325de0fba089b911a4a12ebd3d0b5e7acb7028bc46821 \
|
||||||
|
--hash=sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301 \
|
||||||
|
--hash=sha256:a49833abfdede8985ba3f3ec641f771cca215479f41523e99dace96d5b8cce2a \
|
||||||
|
--hash=sha256:f974c96fca34ae9e4f49839ba6b78addf0346777b46c4da27a7bf54f48d3057d \
|
||||||
|
--hash=sha256:6a3d9efb6f36f1fe6aa8dbb5af55e067db802502c55a9defa47c5a1dad41df84 \
|
||||||
|
--hash=sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5 \
|
||||||
|
--hash=sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e \
|
||||||
|
--hash=sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051 \
|
||||||
|
--hash=sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3 \
|
||||||
|
--hash=sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7 \
|
||||||
|
--hash=sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543
|
||||||
|
pyasn1-modules==0.2.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e \
|
||||||
|
--hash=sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199 \
|
||||||
|
--hash=sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405 \
|
||||||
|
--hash=sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb \
|
||||||
|
--hash=sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8 \
|
||||||
|
--hash=sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74 \
|
||||||
|
--hash=sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d \
|
||||||
|
--hash=sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45 \
|
||||||
|
--hash=sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4 \
|
||||||
|
--hash=sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811 \
|
||||||
|
--hash=sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed \
|
||||||
|
--hash=sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0 \
|
||||||
|
--hash=sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd
|
||||||
|
pyasn1==0.4.8; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3 \
|
||||||
|
--hash=sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf \
|
||||||
|
--hash=sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00 \
|
||||||
|
--hash=sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8 \
|
||||||
|
--hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \
|
||||||
|
--hash=sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86 \
|
||||||
|
--hash=sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7 \
|
||||||
|
--hash=sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576 \
|
||||||
|
--hash=sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12 \
|
||||||
|
--hash=sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2 \
|
||||||
|
--hash=sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359 \
|
||||||
|
--hash=sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776 \
|
||||||
|
--hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba
|
||||||
|
pycrypto==2.6.1 \
|
||||||
|
--hash=sha256:f2ce1e989b272cfcb677616763e0a2e7ec659effa67a88aa92b3a65528f60a3c
|
||||||
|
python-dateutil==2.8.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.3.0") \
|
||||||
|
--hash=sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c \
|
||||||
|
--hash=sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a
|
||||||
|
python-ldap==3.3.1; python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.6" \
|
||||||
|
--hash=sha256:4711cacf013e298754abd70058ccc995758177fb425f1c2d30e71adfc1d00aa5
|
||||||
|
pytz==2021.1; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798 \
|
||||||
|
--hash=sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da
|
||||||
|
six==1.15.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" \
|
||||||
|
--hash=sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced \
|
||||||
|
--hash=sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259
|
||||||
|
smmap==3.0.5; python_version >= "3.4" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.4" \
|
||||||
|
--hash=sha256:7bfcf367828031dc893530a29cb35eb8c8f2d7c8f2d0989354d75d24c8573714 \
|
||||||
|
--hash=sha256:84c2751ef3072d4f6b2785ec7ee40244c6f45eb934d9e543e2c51f1bd3d54c50
|
||||||
|
sqlparse==0.4.1; python_version >= "3.6" and python_version < "4.0" \
|
||||||
|
--hash=sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0 \
|
||||||
|
--hash=sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8
|
||||||
|
zipp==3.4.0; python_version >= "3.6" and python_full_version < "3.0.0" and python_version < "3.7" or python_version >= "3.6" and python_version < "3.7" and python_full_version >= "3.5.0" \
|
||||||
|
--hash=sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108 \
|
||||||
|
--hash=sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb
|
|
@ -28,21 +28,10 @@ from __future__ import unicode_literals
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from reversion.admin import VersionAdmin
|
from reversion.admin import VersionAdmin
|
||||||
|
|
||||||
from .models import (
|
from .models import (AssoOption, DocumentTemplate, GeneralOption, HomeOption,
|
||||||
OptionalUser,
|
MailContact, MailMessageOption, OptionalMachine,
|
||||||
OptionalMachine,
|
OptionalTopologie, OptionalUser, RadiusKey, Reminder,
|
||||||
OptionalTopologie,
|
Service, SwitchManagementCred)
|
||||||
GeneralOption,
|
|
||||||
Service,
|
|
||||||
MailContact,
|
|
||||||
AssoOption,
|
|
||||||
MailMessageOption,
|
|
||||||
HomeOption,
|
|
||||||
RadiusKey,
|
|
||||||
SwitchManagementCred,
|
|
||||||
Reminder,
|
|
||||||
DocumentTemplate,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class OptionalUserAdmin(VersionAdmin):
|
class OptionalUserAdmin(VersionAdmin):
|
||||||
|
|
|
@ -22,11 +22,12 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
import preferences.models as preferences
|
import preferences.models as preferences
|
||||||
from api.serializers import NamespacedHRField, NamespacedHIField, NamespacedHMSerializer
|
from api.serializers import (NamespacedHIField, NamespacedHMSerializer,
|
||||||
|
NamespacedHRField)
|
||||||
|
|
||||||
|
|
||||||
class OptionalUserSerializer(NamespacedHMSerializer):
|
class OptionalUserSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.OptionalUser` objects.
|
"""Serialize `preferences.models.OptionalUser` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
tel_mandatory = serializers.BooleanField(source="is_tel_mandatory")
|
tel_mandatory = serializers.BooleanField(source="is_tel_mandatory")
|
||||||
shell_default = serializers.StringRelatedField()
|
shell_default = serializers.StringRelatedField()
|
||||||
|
@ -47,8 +48,7 @@ class OptionalUserSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class OptionalMachineSerializer(NamespacedHMSerializer):
|
class OptionalMachineSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.OptionalMachine` objects.
|
"""Serialize `preferences.models.OptionalMachine` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.OptionalMachine
|
model = preferences.OptionalMachine
|
||||||
|
@ -59,13 +59,12 @@ class OptionalMachineSerializer(NamespacedHMSerializer):
|
||||||
"ipv6_mode",
|
"ipv6_mode",
|
||||||
"create_machine",
|
"create_machine",
|
||||||
"ipv6",
|
"ipv6",
|
||||||
"default_dns_ttl"
|
"default_dns_ttl",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class OptionalTopologieSerializer(NamespacedHMSerializer):
|
class OptionalTopologieSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.OptionalTopologie` objects.
|
"""Serialize `preferences.models.OptionalTopologie` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
switchs_management_interface_ip = serializers.CharField()
|
switchs_management_interface_ip = serializers.CharField()
|
||||||
|
|
||||||
|
@ -85,8 +84,7 @@ class OptionalTopologieSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class RadiusOptionSerializer(NamespacedHMSerializer):
|
class RadiusOptionSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.RadiusOption` objects
|
"""Serialize `preferences.models.RadiusOption` objects"""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.RadiusOption
|
model = preferences.RadiusOption
|
||||||
|
@ -107,8 +105,7 @@ class RadiusOptionSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class GeneralOptionSerializer(NamespacedHMSerializer):
|
class GeneralOptionSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.GeneralOption` objects.
|
"""Serialize `preferences.models.GeneralOption` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.GeneralOption
|
model = preferences.GeneralOption
|
||||||
|
@ -128,8 +125,7 @@ class GeneralOptionSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class HomeServiceSerializer(NamespacedHMSerializer):
|
class HomeServiceSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.Service` objects.
|
"""Serialize `preferences.models.Service` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.Service
|
model = preferences.Service
|
||||||
|
@ -138,8 +134,7 @@ class HomeServiceSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssoOptionSerializer(NamespacedHMSerializer):
|
class AssoOptionSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.AssoOption` objects.
|
"""Serialize `preferences.models.AssoOption` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.AssoOption
|
model = preferences.AssoOption
|
||||||
|
@ -157,8 +152,7 @@ class AssoOptionSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class HomeOptionSerializer(NamespacedHMSerializer):
|
class HomeOptionSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.HomeOption` objects.
|
"""Serialize `preferences.models.HomeOption` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.HomeOption
|
model = preferences.HomeOption
|
||||||
|
@ -166,8 +160,7 @@ class HomeOptionSerializer(NamespacedHMSerializer):
|
||||||
|
|
||||||
|
|
||||||
class MailMessageOptionSerializer(NamespacedHMSerializer):
|
class MailMessageOptionSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `preferences.models.MailMessageOption` objects.
|
"""Serialize `preferences.models.MailMessageOption` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = preferences.MailMessageOption
|
model = preferences.MailMessageOption
|
||||||
|
|
|
@ -21,9 +21,7 @@
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urls_viewset = [
|
urls_viewset = [(r"preferences/service", views.HomeServiceViewSet, "homeservice")]
|
||||||
(r"preferences/service", views.HomeServiceViewSet, "homeservice")
|
|
||||||
]
|
|
||||||
|
|
||||||
urls_view = [
|
urls_view = [
|
||||||
(r"preferences/optionaluser", views.OptionalUserView),
|
(r"preferences/optionaluser", views.OptionalUserView),
|
||||||
|
@ -33,5 +31,5 @@ urls_view = [
|
||||||
(r"preferences/generaloption", views.GeneralOptionView),
|
(r"preferences/generaloption", views.GeneralOptionView),
|
||||||
(r"preferences/assooption", views.AssoOptionView),
|
(r"preferences/assooption", views.AssoOptionView),
|
||||||
(r"preferences/homeoption", views.HomeOptionView),
|
(r"preferences/homeoption", views.HomeOptionView),
|
||||||
(r"preferences/mailmessageoption", views.MailMessageOptionView)
|
(r"preferences/mailmessageoption", views.MailMessageOptionView),
|
||||||
]
|
]
|
|
@ -19,16 +19,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.
|
||||||
|
|
||||||
from rest_framework import viewsets, generics
|
from rest_framework import generics, viewsets
|
||||||
|
|
||||||
from . import serializers
|
|
||||||
import preferences.models as preferences
|
import preferences.models as preferences
|
||||||
from api.permissions import ACLPermission
|
from api.permissions import ACLPermission
|
||||||
|
|
||||||
|
from . import serializers
|
||||||
|
|
||||||
|
|
||||||
class OptionalUserView(generics.RetrieveAPIView):
|
class OptionalUserView(generics.RetrieveAPIView):
|
||||||
"""Exposes details of `preferences.models.` settings.
|
"""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]}
|
||||||
|
@ -39,8 +39,7 @@ class OptionalUserView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class OptionalMachineView(generics.RetrieveAPIView):
|
class OptionalMachineView(generics.RetrieveAPIView):
|
||||||
"""Exposes details of `preferences.models.OptionalMachine` settings.
|
"""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]}
|
||||||
|
@ -51,8 +50,7 @@ class OptionalMachineView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class OptionalTopologieView(generics.RetrieveAPIView):
|
class OptionalTopologieView(generics.RetrieveAPIView):
|
||||||
"""Exposes details of `preferences.models.OptionalTopologie` settings.
|
"""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]}
|
||||||
|
@ -63,8 +61,7 @@ class OptionalTopologieView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class RadiusOptionView(generics.RetrieveAPIView):
|
class RadiusOptionView(generics.RetrieveAPIView):
|
||||||
"""Exposes details of `preferences.models.OptionalTopologie` settings.
|
"""Exposes details of `preferences.models.OptionalTopologie` settings."""
|
||||||
"""
|
|
||||||
|
|
||||||
permission_classes = (ACLPermission,)
|
permission_classes = (ACLPermission,)
|
||||||
perms_map = {"GET": [preferences.RadiusOption.can_view_all]}
|
perms_map = {"GET": [preferences.RadiusOption.can_view_all]}
|
||||||
|
@ -75,8 +72,7 @@ class RadiusOptionView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class GeneralOptionView(generics.RetrieveAPIView):
|
class GeneralOptionView(generics.RetrieveAPIView):
|
||||||
"""Exposes details of `preferences.models.GeneralOption` settings.
|
"""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]}
|
||||||
|
@ -87,16 +83,14 @@ class GeneralOptionView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class HomeServiceViewSet(viewsets.ReadOnlyModelViewSet):
|
class HomeServiceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `preferences.models.Service` objects.
|
"""Exposes list and details of `preferences.models.Service` objects."""
|
||||||
"""
|
|
||||||
|
|
||||||
queryset = preferences.Service.objects.all()
|
queryset = preferences.Service.objects.all()
|
||||||
serializer_class = serializers.HomeServiceSerializer
|
serializer_class = serializers.HomeServiceSerializer
|
||||||
|
|
||||||
|
|
||||||
class AssoOptionView(generics.RetrieveAPIView):
|
class AssoOptionView(generics.RetrieveAPIView):
|
||||||
"""Exposes details of `preferences.models.AssoOption` settings.
|
"""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]}
|
||||||
|
@ -107,8 +101,7 @@ class AssoOptionView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class HomeOptionView(generics.RetrieveAPIView):
|
class HomeOptionView(generics.RetrieveAPIView):
|
||||||
"""Exposes details of `preferences.models.HomeOption` settings.
|
"""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]}
|
||||||
|
@ -119,8 +112,7 @@ class HomeOptionView(generics.RetrieveAPIView):
|
||||||
|
|
||||||
|
|
||||||
class MailMessageOptionView(generics.RetrieveAPIView):
|
class MailMessageOptionView(generics.RetrieveAPIView):
|
||||||
"""Exposes details of `preferences.models.MailMessageOption` settings.
|
"""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]}
|
||||||
|
|
11
preferences/apps.py
Normal file
11
preferences/apps.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""
|
||||||
|
Configuration of preferences app.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class PreferencesConfig(AppConfig):
|
||||||
|
"""Configuration of preferences app."""
|
||||||
|
|
||||||
|
name = "preferences"
|
|
@ -25,36 +25,22 @@ Forms to edit preferences: users, machines, topology, organisation etc.
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.forms import ModelForm, Form
|
|
||||||
from django.db.models import Q
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.db.models import Q
|
||||||
|
from django.forms import Form, ModelForm
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from re2o.mixins import FormRevMixin
|
from re2o.mixins import FormRevMixin
|
||||||
from re2o.widgets import (
|
from re2o.widgets import (AutocompleteModelWidget,
|
||||||
AutocompleteModelWidget,
|
AutocompleteMultipleModelWidget)
|
||||||
AutocompleteMultipleModelWidget
|
|
||||||
)
|
|
||||||
from .models import (
|
|
||||||
OptionalUser,
|
|
||||||
OptionalMachine,
|
|
||||||
OptionalTopologie,
|
|
||||||
GeneralOption,
|
|
||||||
AssoOption,
|
|
||||||
MailMessageOption,
|
|
||||||
HomeOption,
|
|
||||||
Service,
|
|
||||||
MailContact,
|
|
||||||
Reminder,
|
|
||||||
RadiusKey,
|
|
||||||
SwitchManagementCred,
|
|
||||||
RadiusOption,
|
|
||||||
CotisationsOption,
|
|
||||||
DocumentTemplate,
|
|
||||||
RadiusAttribute,
|
|
||||||
Mandate,
|
|
||||||
)
|
|
||||||
from topologie.models import Switch
|
from topologie.models import Switch
|
||||||
|
|
||||||
|
from .models import (AssoOption, CotisationsOption, DocumentTemplate,
|
||||||
|
GeneralOption, HomeOption, MailContact, MailMessageOption,
|
||||||
|
Mandate, OptionalMachine, OptionalTopologie, OptionalUser,
|
||||||
|
RadiusAttribute, RadiusKey, RadiusOption, Reminder,
|
||||||
|
Service, SwitchManagementCred)
|
||||||
|
|
||||||
|
|
||||||
class EditOptionalUserForm(ModelForm):
|
class EditOptionalUserForm(ModelForm):
|
||||||
"""Form used to edit user preferences."""
|
"""Form used to edit user preferences."""
|
||||||
|
@ -74,14 +60,22 @@ class EditOptionalUserForm(ModelForm):
|
||||||
self.fields["self_change_shell"].label = _("Self change shell")
|
self.fields["self_change_shell"].label = _("Self change shell")
|
||||||
self.fields["self_change_pseudo"].label = _("Self change pseudo")
|
self.fields["self_change_pseudo"].label = _("Self change pseudo")
|
||||||
self.fields["self_room_policy"].label = _("Self room policy")
|
self.fields["self_room_policy"].label = _("Self room policy")
|
||||||
self.fields["local_email_accounts_enabled"].label = _("Local email accounts enabled")
|
self.fields["local_email_accounts_enabled"].label = _(
|
||||||
|
"Local email accounts enabled"
|
||||||
|
)
|
||||||
self.fields["local_email_domain"].label = _("Local email domain")
|
self.fields["local_email_domain"].label = _("Local email domain")
|
||||||
self.fields["max_email_address"].label = _("Max local email address")
|
self.fields["max_email_address"].label = _("Max local email address")
|
||||||
self.fields["delete_notyetactive"].label = _("Delete not yet active users")
|
self.fields["delete_notyetactive"].label = _("Delete not yet active users")
|
||||||
self.fields["disable_emailnotyetconfirmed"].label = _("Disabled email not yet confirmed")
|
self.fields["disable_emailnotyetconfirmed"].label = _(
|
||||||
|
"Disabled email not yet confirmed"
|
||||||
|
)
|
||||||
self.fields["self_adhesion"].label = _("Self registration")
|
self.fields["self_adhesion"].label = _("Self registration")
|
||||||
self.fields["all_users_active"].label = _("All users are state active by default")
|
self.fields["all_users_active"].label = _(
|
||||||
self.fields["allow_set_password_during_user_creation"].label = _("Allow set password during user creation")
|
"All users are state active by default"
|
||||||
|
)
|
||||||
|
self.fields["allow_set_password_during_user_creation"].label = _(
|
||||||
|
"Allow set password during user creation"
|
||||||
|
)
|
||||||
self.fields["allow_archived_connexion"].label = _("Allow archived connexion")
|
self.fields["allow_archived_connexion"].label = _("Allow archived connexion")
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,9 +205,7 @@ class EditMailMessageOptionForm(ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
|
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
|
||||||
super(EditMailMessageOptionForm, self).__init__(*args, prefix=prefix, **kwargs)
|
super(EditMailMessageOptionForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||||
self.fields["welcome_mail_fr"].label = _(
|
self.fields["welcome_mail_fr"].label = _("Message for the French welcome email")
|
||||||
"Message for the French welcome email"
|
|
||||||
)
|
|
||||||
self.fields["welcome_mail_en"].label = _(
|
self.fields["welcome_mail_en"].label = _(
|
||||||
"Message for the English welcome email"
|
"Message for the English welcome email"
|
||||||
)
|
)
|
||||||
|
@ -355,8 +347,7 @@ class ServiceForm(ModelForm):
|
||||||
|
|
||||||
|
|
||||||
class DelServiceForm(Form):
|
class DelServiceForm(Form):
|
||||||
"""Form used to delete one or several services displayed on the home page.
|
"""Form used to delete one or several services displayed on the home page."""
|
||||||
"""
|
|
||||||
|
|
||||||
services = forms.ModelMultipleChoiceField(
|
services = forms.ModelMultipleChoiceField(
|
||||||
queryset=Service.objects.none(),
|
queryset=Service.objects.none(),
|
||||||
|
|
65
preferences/migrations/0003_auto_20210208_1827.py
Normal file
65
preferences/migrations/0003_auto_20210208_1827.py
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# Generated by Django 2.2.18 on 2021-02-08 17:27
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('preferences', '0002_foreign_keys'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='assooption',
|
||||||
|
options={'verbose_name': 'organisation preferences'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='generaloption',
|
||||||
|
options={'verbose_name': 'general preferences'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='homeoption',
|
||||||
|
options={'verbose_name': 'homepage preferences'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='mailcontact',
|
||||||
|
options={'verbose_name': 'contact email address', 'verbose_name_plural': 'contact email addresses'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='mailmessageoption',
|
||||||
|
options={'verbose_name': 'email message preferences'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='mandate',
|
||||||
|
options={'verbose_name': 'mandate', 'verbose_name_plural': 'mandates'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='optionalmachine',
|
||||||
|
options={'verbose_name': 'machine preferences'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='optionaltopologie',
|
||||||
|
options={'verbose_name': 'topology preferences'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='optionaluser',
|
||||||
|
options={'verbose_name': 'user preferences'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='radiuskey',
|
||||||
|
options={'verbose_name': 'RADIUS key', 'verbose_name_plural': 'RADIUS keys'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='reminder',
|
||||||
|
options={'verbose_name': 'reminder', 'verbose_name_plural': 'reminders'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='service',
|
||||||
|
options={'verbose_name': 'service', 'verbose_name_plural': 'services'},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='switchmanagementcred',
|
||||||
|
options={'verbose_name': 'switch management credentials'},
|
||||||
|
),
|
||||||
|
]
|
|
@ -25,23 +25,22 @@ Models defining the preferences for users, machines, emails, general settings
|
||||||
etc.
|
etc.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import os
|
|
||||||
|
|
||||||
from django.utils.functional import cached_property
|
import os
|
||||||
from django.utils import timezone
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from django.core.cache import cache
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.core.cache import cache
|
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import machines.models
|
import machines.models
|
||||||
|
|
||||||
from re2o.mixins import AclMixin, RevMixin
|
|
||||||
from re2o.aes_field import AESEncryptedField
|
from re2o.aes_field import AESEncryptedField
|
||||||
|
from re2o.mixins import AclMixin, RevMixin
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
|
|
||||||
class PreferencesModel(models.Model):
|
class PreferencesModel(models.Model):
|
||||||
|
@ -185,7 +184,6 @@ class OptionalUser(AclMixin, PreferencesModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_optionaluser", _("Can view the user preferences")),)
|
|
||||||
verbose_name = _("user preferences")
|
verbose_name = _("user preferences")
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
@ -241,7 +239,6 @@ class OptionalMachine(AclMixin, PreferencesModel):
|
||||||
return not self.get_cached_value("ipv6_mode") == "DISABLED"
|
return not self.get_cached_value("ipv6_mode") == "DISABLED"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_optionalmachine", _("Can view the machine preferences")),)
|
|
||||||
verbose_name = _("machine preferences")
|
verbose_name = _("machine preferences")
|
||||||
|
|
||||||
|
|
||||||
|
@ -330,7 +327,7 @@ class OptionalTopologie(AclMixin, PreferencesModel):
|
||||||
configuration.
|
configuration.
|
||||||
"""
|
"""
|
||||||
if self.switchs_ip_type:
|
if self.switchs_ip_type:
|
||||||
from machines.models import Role, Interface
|
from machines.models import Interface, Role
|
||||||
|
|
||||||
return (
|
return (
|
||||||
Interface.objects.filter(
|
Interface.objects.filter(
|
||||||
|
@ -366,14 +363,14 @@ class OptionalTopologie(AclMixin, PreferencesModel):
|
||||||
"""Get the dictionary of IP addresses for the configuration of
|
"""Get the dictionary of IP addresses for the configuration of
|
||||||
switches.
|
switches.
|
||||||
"""
|
"""
|
||||||
from machines.models import Role, Ipv6List, Interface
|
from machines.models import Interface, Ipv6List, Role
|
||||||
|
|
||||||
def return_ips_dict(interfaces):
|
def return_ips_dict(interfaces):
|
||||||
return {
|
return {
|
||||||
"ipv4": [str(interface.ipv4) for interface in interfaces],
|
"ipv4": [str(interface.ipv4) for interface in interfaces],
|
||||||
"ipv6": Ipv6List.objects.filter(interface__in=interfaces).filter(active=True).values_list(
|
"ipv6": Ipv6List.objects.filter(interface__in=interfaces)
|
||||||
"ipv6", flat=True
|
.filter(active=True)
|
||||||
),
|
.values_list("ipv6", flat=True),
|
||||||
}
|
}
|
||||||
|
|
||||||
ntp_servers = Role.all_interfaces_for_roletype("ntp-server").filter(
|
ntp_servers = Role.all_interfaces_for_roletype("ntp-server").filter(
|
||||||
|
@ -421,9 +418,6 @@ class OptionalTopologie(AclMixin, PreferencesModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
|
||||||
("view_optionaltopologie", _("Can view the topology preferences")),
|
|
||||||
)
|
|
||||||
verbose_name = _("topology preferences")
|
verbose_name = _("topology preferences")
|
||||||
|
|
||||||
|
|
||||||
|
@ -453,7 +447,6 @@ class RadiusKey(AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_radiuskey", _("Can view a RADIUS key object")),)
|
|
||||||
verbose_name = _("RADIUS key")
|
verbose_name = _("RADIUS key")
|
||||||
verbose_name_plural = _("RADIUS keys")
|
verbose_name_plural = _("RADIUS keys")
|
||||||
|
|
||||||
|
@ -483,12 +476,6 @@ class SwitchManagementCred(AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
|
||||||
(
|
|
||||||
"view_switchmanagementcred",
|
|
||||||
_("Can view a switch management credentials object"),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
verbose_name = _("switch management credentials")
|
verbose_name = _("switch management credentials")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -518,7 +505,6 @@ class Reminder(AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_reminder", _("Can view a reminder object")),)
|
|
||||||
verbose_name = _("reminder")
|
verbose_name = _("reminder")
|
||||||
verbose_name_plural = _("reminders")
|
verbose_name_plural = _("reminders")
|
||||||
|
|
||||||
|
@ -582,7 +568,6 @@ class GeneralOption(AclMixin, PreferencesModel):
|
||||||
GTU = models.FileField(upload_to="", default="", null=True, blank=True)
|
GTU = models.FileField(upload_to="", default="", null=True, blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_generaloption", _("Can view the general preferences")),)
|
|
||||||
verbose_name = _("general preferences")
|
verbose_name = _("general preferences")
|
||||||
|
|
||||||
|
|
||||||
|
@ -609,7 +594,6 @@ class Service(AclMixin, models.Model):
|
||||||
image = models.ImageField(upload_to="logo", blank=True)
|
image = models.ImageField(upload_to="logo", blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_service", _("Can view the service preferences")),)
|
|
||||||
verbose_name = _("service")
|
verbose_name = _("service")
|
||||||
verbose_name_plural = _("services")
|
verbose_name_plural = _("services")
|
||||||
|
|
||||||
|
@ -641,9 +625,6 @@ class MailContact(AclMixin, models.Model):
|
||||||
return self.address.split("@")[0]
|
return self.address.split("@")[0]
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
|
||||||
("view_mailcontact", _("Can view a contact email address object")),
|
|
||||||
)
|
|
||||||
verbose_name = _("contact email address")
|
verbose_name = _("contact email address")
|
||||||
verbose_name_plural = _("contact email addresses")
|
verbose_name_plural = _("contact email addresses")
|
||||||
|
|
||||||
|
@ -664,7 +645,6 @@ class Mandate(RevMixin, AclMixin, models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("mandate")
|
verbose_name = _("mandate")
|
||||||
verbose_name_plural = _("mandates")
|
verbose_name_plural = _("mandates")
|
||||||
permissions = (("view_mandate", _("Can view a mandate object")),)
|
|
||||||
|
|
||||||
president = models.ForeignKey(
|
president = models.ForeignKey(
|
||||||
"users.User",
|
"users.User",
|
||||||
|
@ -679,7 +659,7 @@ class Mandate(RevMixin, AclMixin, models.Model):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_mandate(cls, date=timezone.now):
|
def get_mandate(cls, date=timezone.now):
|
||||||
""""Get the mandate taking place at the given date.
|
""" "Get the mandate taking place at the given date.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
date: the date used to find the mandate (default: timezone.now).
|
date: the date used to find the mandate (default: timezone.now).
|
||||||
|
@ -740,7 +720,6 @@ class AssoOption(AclMixin, PreferencesModel):
|
||||||
description = models.TextField(null=True, blank=True)
|
description = models.TextField(null=True, blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_assooption", _("Can view the organisation preferences")),)
|
|
||||||
verbose_name = _("organisation preferences")
|
verbose_name = _("organisation preferences")
|
||||||
|
|
||||||
|
|
||||||
|
@ -766,7 +745,6 @@ class HomeOption(AclMixin, PreferencesModel):
|
||||||
twitter_account_name = models.CharField(max_length=32, null=True, blank=True)
|
twitter_account_name = models.CharField(max_length=32, null=True, blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (("view_homeoption", _("Can view the homepage preferences")),)
|
|
||||||
verbose_name = _("homepage preferences")
|
verbose_name = _("homepage preferences")
|
||||||
|
|
||||||
|
|
||||||
|
@ -793,9 +771,6 @@ class MailMessageOption(AclMixin, models.Model):
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
permissions = (
|
|
||||||
("view_mailmessageoption", _("Can view the email message preferences")),
|
|
||||||
)
|
|
||||||
verbose_name = _("email message preferences")
|
verbose_name = _("email message preferences")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,139 +25,134 @@ Urls de l'application preferences, pointant vers les fonctions de views
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.urls import path, re_path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
from .views import edit_options
|
from .views import edit_options
|
||||||
|
|
||||||
|
app_name = "preferences"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>OptionalUser)$",
|
r"^edit_options/(?P<section>OptionalUser)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>OptionalMachine)$",
|
r"^edit_options/(?P<section>OptionalMachine)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>OptionalTopologie)$",
|
r"^edit_options/(?P<section>OptionalTopologie)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>GeneralOption)$",
|
r"^edit_options/(?P<section>GeneralOption)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>AssoOption)$",
|
r"^edit_options/(?P<section>AssoOption)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>HomeOption)$",
|
r"^edit_options/(?P<section>HomeOption)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>MailMessageOption)$",
|
r"^edit_options/(?P<section>MailMessageOption)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>RadiusOption)$",
|
r"^edit_options/(?P<section>RadiusOption)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(
|
re_path(
|
||||||
r"^edit_options/(?P<section>CotisationsOption)$",
|
r"^edit_options/(?P<section>CotisationsOption)$",
|
||||||
edit_options,
|
edit_options,
|
||||||
name="edit-options",
|
name="edit-options",
|
||||||
),
|
),
|
||||||
url(r"^add_service/$", views.add_service, name="add-service"),
|
path("add_service", views.add_service, name="add-service"),
|
||||||
url(
|
path("edit_service/<int:serviceid>", views.edit_service, name="edit-service"),
|
||||||
r"^edit_service/(?P<serviceid>[0-9]+)$", views.edit_service, name="edit-service"
|
path("del_service/<int:serviceid>", views.del_service, name="del-service"),
|
||||||
),
|
path("add_mailcontact", views.add_mailcontact, name="add-mailcontact"),
|
||||||
url(r"^del_service/(?P<serviceid>[0-9]+)$", views.del_service, name="del-service"),
|
path(
|
||||||
url(r"^add_mailcontact/$", views.add_mailcontact, name="add-mailcontact"),
|
"edit_mailcontact/<int:mailcontactid>",
|
||||||
url(
|
|
||||||
r"^edit_mailcontact/(?P<mailcontactid>[0-9]+)$",
|
|
||||||
views.edit_mailcontact,
|
views.edit_mailcontact,
|
||||||
name="edit-mailcontact",
|
name="edit-mailcontact",
|
||||||
),
|
),
|
||||||
url(r"^del_mailcontact/$", views.del_mailcontact, name="del-mailcontact"),
|
path("del_mailcontact", views.del_mailcontact, name="del-mailcontact"),
|
||||||
url(r"^add_reminder/$", views.add_reminder, name="add-reminder"),
|
path("add_reminder", views.add_reminder, name="add-reminder"),
|
||||||
url(
|
path(
|
||||||
r"^edit_reminder/(?P<reminderid>[0-9]+)$",
|
"edit_reminder/<int:reminderid>",
|
||||||
views.edit_reminder,
|
views.edit_reminder,
|
||||||
name="edit-reminder",
|
name="edit-reminder",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_reminder/(?P<reminderid>[0-9]+)$",
|
"del_reminder/<int:reminderid>",
|
||||||
views.del_reminder,
|
views.del_reminder,
|
||||||
name="del-reminder",
|
name="del-reminder",
|
||||||
),
|
),
|
||||||
url(r"^add_radiuskey/$", views.add_radiuskey, name="add-radiuskey"),
|
path("add_radiuskey", views.add_radiuskey, name="add-radiuskey"),
|
||||||
url(
|
path(
|
||||||
r"^edit_radiuskey/(?P<radiuskeyid>[0-9]+)$",
|
"edit_radiuskey/<int:radiuskeyid>",
|
||||||
views.edit_radiuskey,
|
views.edit_radiuskey,
|
||||||
name="edit-radiuskey",
|
name="edit-radiuskey",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_radiuskey/(?P<radiuskeyid>[0-9]+)$",
|
"del_radiuskey/<int:radiuskeyid>",
|
||||||
views.del_radiuskey,
|
views.del_radiuskey,
|
||||||
name="del-radiuskey",
|
name="del-radiuskey",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^add_switchmanagementcred/$",
|
"add_switchmanagementcred",
|
||||||
views.add_switchmanagementcred,
|
views.add_switchmanagementcred,
|
||||||
name="add-switchmanagementcred",
|
name="add-switchmanagementcred",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^edit_switchmanagementcred/(?P<switchmanagementcredid>[0-9]+)$",
|
"edit_switchmanagementcred/<int:switchmanagementcredid>",
|
||||||
views.edit_switchmanagementcred,
|
views.edit_switchmanagementcred,
|
||||||
name="edit-switchmanagementcred",
|
name="edit-switchmanagementcred",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_switchmanagementcred/(?P<switchmanagementcredid>[0-9]+)$",
|
"del_switchmanagementcred/<int:switchmanagementcredid>",
|
||||||
views.del_switchmanagementcred,
|
views.del_switchmanagementcred,
|
||||||
name="del-switchmanagementcred",
|
name="del-switchmanagementcred",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^add_document_template/$",
|
"add_document_template",
|
||||||
views.add_document_template,
|
views.add_document_template,
|
||||||
name="add-document-template",
|
name="add-document-template",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^edit_document_template/(?P<documenttemplateid>[0-9]+)$",
|
"edit_document_template/<int:documenttemplateid>",
|
||||||
views.edit_document_template,
|
views.edit_document_template,
|
||||||
name="edit-document-template",
|
name="edit-document-template",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_document_template/$",
|
"del_document_template",
|
||||||
views.del_document_template,
|
views.del_document_template,
|
||||||
name="del-document-template",
|
name="del-document-template",
|
||||||
),
|
),
|
||||||
url(r"^add_mandate/$", views.add_mandate, name="add-mandate"),
|
path("add_mandate", views.add_mandate, name="add-mandate"),
|
||||||
url(
|
path("edit_mandate/<int:mandateid>", views.edit_mandate, name="edit-mandate"),
|
||||||
r"^edit_mandate/(?P<mandateid>[0-9]+)$", views.edit_mandate, name="edit-mandate"
|
path("del_mandate/<int:mandateid>", views.del_mandate, name="del-mandate"),
|
||||||
),
|
path("add_radiusattribute", views.add_radiusattribute, name="add-radiusattribute"),
|
||||||
url(r"^del_mandate/(?P<mandateid>[0-9]+)$", views.del_mandate, name="del-mandate"),
|
path(
|
||||||
url(
|
"edit_radiusattribute/<int:radiusattributeid>",
|
||||||
r"^add_radiusattribute/$", views.add_radiusattribute, name="add-radiusattribute"
|
|
||||||
),
|
|
||||||
url(
|
|
||||||
r"^edit_radiusattribute/(?P<radiusattributeid>[0-9]+)$",
|
|
||||||
views.edit_radiusattribute,
|
views.edit_radiusattribute,
|
||||||
name="edit-radiusattribute",
|
name="edit-radiusattribute",
|
||||||
),
|
),
|
||||||
url(
|
path(
|
||||||
r"^del_radiusattribute/(?P<radiusattributeid>[0-9]+)$",
|
"del_radiusattribute/<int:radiusattributeid>",
|
||||||
views.del_radiusattribute,
|
views.del_radiusattribute,
|
||||||
name="del-radiusattribute",
|
name="del-radiusattribute",
|
||||||
),
|
),
|
||||||
url(r"^$", views.display_options, name="display-options"),
|
path("", views.display_options, name="display-options"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -30,61 +30,33 @@ services etc.)
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.urls import reverse
|
from importlib import import_module
|
||||||
from django.shortcuts import redirect
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.db.models import ProtectedError
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from django.db.models import ProtectedError
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from reversion import revisions as reversion
|
from reversion import revisions as reversion
|
||||||
|
|
||||||
from importlib import import_module
|
from re2o.acl import (acl_error_message, can_create, can_delete,
|
||||||
|
can_delete_set, can_edit, can_view_all)
|
||||||
from re2o.settings_local import OPTIONNAL_APPS_RE2O
|
from re2o.settings_local import OPTIONNAL_APPS_RE2O
|
||||||
from re2o.views import form
|
from re2o.views import form
|
||||||
from re2o.acl import (
|
|
||||||
can_create,
|
|
||||||
can_edit,
|
|
||||||
can_delete_set,
|
|
||||||
can_view_all,
|
|
||||||
can_delete,
|
|
||||||
acl_error_message,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .forms import MailContactForm, DelMailContactForm
|
from . import forms, models
|
||||||
from .forms import (
|
from .forms import (DelDocumentTemplateForm, DelMailContactForm,
|
||||||
ServiceForm,
|
DelRadiusAttributeForm, DocumentTemplateForm,
|
||||||
ReminderForm,
|
MailContactForm, MandateForm, RadiusAttributeForm,
|
||||||
RadiusKeyForm,
|
RadiusKeyForm, ReminderForm, ServiceForm,
|
||||||
SwitchManagementCredForm,
|
SwitchManagementCredForm)
|
||||||
DocumentTemplateForm,
|
from .models import (AssoOption, CotisationsOption, DocumentTemplate,
|
||||||
DelDocumentTemplateForm,
|
GeneralOption, HomeOption, MailContact, MailMessageOption,
|
||||||
RadiusAttributeForm,
|
Mandate, OptionalMachine, OptionalTopologie, OptionalUser,
|
||||||
DelRadiusAttributeForm,
|
RadiusAttribute, RadiusKey, RadiusOption, Reminder,
|
||||||
MandateForm,
|
Service, SwitchManagementCred)
|
||||||
)
|
|
||||||
from .models import (
|
|
||||||
Service,
|
|
||||||
MailContact,
|
|
||||||
OptionalUser,
|
|
||||||
OptionalMachine,
|
|
||||||
AssoOption,
|
|
||||||
MailMessageOption,
|
|
||||||
GeneralOption,
|
|
||||||
OptionalTopologie,
|
|
||||||
HomeOption,
|
|
||||||
Reminder,
|
|
||||||
RadiusKey,
|
|
||||||
SwitchManagementCred,
|
|
||||||
RadiusOption,
|
|
||||||
CotisationsOption,
|
|
||||||
DocumentTemplate,
|
|
||||||
RadiusAttribute,
|
|
||||||
Mandate,
|
|
||||||
)
|
|
||||||
from . import models
|
|
||||||
from . import forms
|
|
||||||
|
|
||||||
|
|
||||||
def edit_options_template_function(request, section, forms, models):
|
def edit_options_template_function(request, section, forms, models):
|
||||||
|
|
73
pyproject.toml
Normal file
73
pyproject.toml
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
[tool.poetry]
|
||||||
|
name = "re2o"
|
||||||
|
version = "2.9.0"
|
||||||
|
description = "Re2o is a management software initially developed at Rézo Metz. It is now in use in several student organizations. It aims to remain agnostic of the organization that uses it and be easy to setup."
|
||||||
|
authors = [
|
||||||
|
"Gabriel Detraz",
|
||||||
|
"Hugo Levy-falk",
|
||||||
|
"Maël Kervella",
|
||||||
|
"Jean-romain Garnier",
|
||||||
|
"Arthur Grisel-davy",
|
||||||
|
"Laouen Fernet",
|
||||||
|
"Augustin Lemesle",
|
||||||
|
"Lara Kermarec",
|
||||||
|
"Alexandre Iooss",
|
||||||
|
"Yoann Piétri",
|
||||||
|
"Charlie Jacomme",
|
||||||
|
"Corentin Canebier",
|
||||||
|
"Bombar Maxime",
|
||||||
|
"Guillaume Goessel",
|
||||||
|
"Matthieu Michelet",
|
||||||
|
"Edpibu",
|
||||||
|
"Fardale",
|
||||||
|
"Jean-marie Mineau",
|
||||||
|
"David Sinquin",
|
||||||
|
"Gabriel Le Bouder",
|
||||||
|
"Simon Brélivet",
|
||||||
|
"Benjamin Graillot",
|
||||||
|
"Leïla Bekaddour",
|
||||||
|
"Éloi Alain",
|
||||||
|
"Pierre Cadart",
|
||||||
|
"Antoine Vintache",
|
||||||
|
"Thibault De Boutray",
|
||||||
|
"Delphine Salvy",
|
||||||
|
"Joanne Steiner",
|
||||||
|
"Krokmou",
|
||||||
|
"B",
|
||||||
|
"Daniel Stan",
|
||||||
|
"Gwenael Le Hir",
|
||||||
|
"Hugo Hervieux",
|
||||||
|
"Mikachu",
|
||||||
|
"Nymous",
|
||||||
|
"Pierre-antoine Comby",
|
||||||
|
"Vincent Le Gallic",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = ">=3.6,<4.0"
|
||||||
|
Django = "2.2.18"
|
||||||
|
django-autocomplete-light = "^3.8.1"
|
||||||
|
django-bootstrap3 = "^14.2.0"
|
||||||
|
django-rest-framework = "^0.1.0"
|
||||||
|
django-reversion = "^3.0.9"
|
||||||
|
Pillow = "^8.1.0"
|
||||||
|
python-dateutil = "^2.8.1"
|
||||||
|
django-macaddress = "^1.7.0"
|
||||||
|
pycrypto = "^2.6.1"
|
||||||
|
GitPython = "^3.1.13"
|
||||||
|
mysqlclient = {version = "^2.0.3", optional=true}
|
||||||
|
psycopg2 = {version = "^2.8.6", optional=true}
|
||||||
|
django-ldapdb = {version = "^1.5.1", optional=true}
|
||||||
|
|
||||||
|
[tool.poetry.extras]
|
||||||
|
mysql = ["mysqlclient"]
|
||||||
|
postgresql = ["psycopg2"]
|
||||||
|
ldap = ["django-ldapdb"]
|
||||||
|
|
||||||
|
[tool.poetry.dev-dependencies]
|
||||||
|
Sphinx = "^3.4.3"
|
||||||
|
sphinx-rtd-theme = "^0.5.1"
|
||||||
|
black = "^20.8b1"
|
||||||
|
rope = "^0.18.0"
|
||||||
|
coverage = "^5.4"
|
||||||
|
docstr-coverage = "^2.0.0"
|
|
@ -30,8 +30,8 @@ from __future__ import unicode_literals
|
||||||
import sys
|
import sys
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from django.db.models import Model
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
from django.db.models import Model
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
|
@ -28,22 +28,22 @@ Module defining a AESEncryptedField object that can be used in forms
|
||||||
to handle the use of properly encrypting and decrypting AES keys
|
to handle the use of properly encrypting and decrypting AES keys
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import string
|
|
||||||
import binascii
|
import binascii
|
||||||
|
import string
|
||||||
from random import choice
|
from random import choice
|
||||||
from Crypto.Cipher import AES
|
|
||||||
|
|
||||||
from django.db import models
|
from Crypto.Cipher import AES
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
EOD_asbyte = b"`%EofD%`" # This should be something that will not occur in strings
|
EOD_asbyte = b"`%EofD%`" # This should be something that will not occur in strings
|
||||||
EOD = EOD_asbyte.decode("utf-8")
|
EOD = EOD_asbyte.decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
def genstring(length=16, chars=string.printable):
|
def genstring(length=16, chars=string.printable):
|
||||||
""" Generate a random string of length `length` and composed of
|
"""Generate a random string of length `length` and composed of
|
||||||
the characters in `chars` """
|
the characters in `chars`"""
|
||||||
return "".join([choice(chars) for i in range(length)])
|
return "".join([choice(chars) for i in range(length)])
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,8 +71,8 @@ class AESEncryptedFormField(forms.CharField):
|
||||||
|
|
||||||
|
|
||||||
class AESEncryptedField(models.CharField):
|
class AESEncryptedField(models.CharField):
|
||||||
""" A Field that can be used in forms for adding the support
|
"""A Field that can be used in forms for adding the support
|
||||||
of AES ecnrypted fields """
|
of AES ecnrypted fields"""
|
||||||
|
|
||||||
def save_form_data(self, instance, data):
|
def save_form_data(self, instance, data):
|
||||||
setattr(
|
setattr(
|
||||||
|
|
11
re2o/apps.py
Normal file
11
re2o/apps.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
"""
|
||||||
|
Configuration of re2o app.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class Re2oConfig(AppConfig):
|
||||||
|
"""Configuration of re2o app."""
|
||||||
|
|
||||||
|
name = "re2o"
|
13
re2o/base.py
13
re2o/base.py
|
@ -26,12 +26,11 @@ Global independant usefull functions
|
||||||
|
|
||||||
import smtplib
|
import smtplib
|
||||||
|
|
||||||
|
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
|
||||||
|
|
||||||
from re2o.settings import EMAIL_HOST
|
from re2o.settings import EMAIL_HOST
|
||||||
|
|
||||||
|
|
||||||
# Mapping of srtftime format for better understanding
|
# Mapping of srtftime format for better understanding
|
||||||
# https://docs.python.org/3.6/library/datetime.html#strftime-strptime-behavior
|
# https://docs.python.org/3.6/library/datetime.html#strftime-strptime-behavior
|
||||||
datetime_mapping = {
|
datetime_mapping = {
|
||||||
|
@ -64,7 +63,7 @@ datetime_mapping = {
|
||||||
|
|
||||||
def smtp_check(local_part):
|
def smtp_check(local_part):
|
||||||
"""Return True if the local_part is already taken
|
"""Return True if the local_part is already taken
|
||||||
False if available"""
|
False if available"""
|
||||||
try:
|
try:
|
||||||
srv = smtplib.SMTP(EMAIL_HOST)
|
srv = smtplib.SMTP(EMAIL_HOST)
|
||||||
srv.putcmd("vrfy", local_part)
|
srv.putcmd("vrfy", local_part)
|
||||||
|
@ -108,9 +107,9 @@ def get_input_formats_help_text(input_formats):
|
||||||
|
|
||||||
|
|
||||||
class SortTable:
|
class SortTable:
|
||||||
""" Class gathering uselful stuff to sort the colums of a table, according
|
"""Class gathering uselful stuff to sort the colums of a table, according
|
||||||
to the column and order requested. It's used with a dict of possible
|
to the column and order requested. It's used with a dict of possible
|
||||||
values and associated model_fields """
|
values and associated model_fields"""
|
||||||
|
|
||||||
# All the possible possible values
|
# All the possible possible values
|
||||||
# The naming convention is based on the URL or the views function
|
# The naming convention is based on the URL or the views function
|
||||||
|
@ -228,8 +227,8 @@ class SortTable:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sort(request, col, order, values):
|
def sort(request, col, order, values):
|
||||||
""" Check if the given values are possible and add .order_by() and
|
"""Check if the given values are possible and add .order_by() and
|
||||||
a .reverse() as specified according to those values """
|
a .reverse() as specified according to those values"""
|
||||||
fields = values.get(col, None)
|
fields = values.get(col, None)
|
||||||
if not fields:
|
if not fields:
|
||||||
fields = values.get("default", [])
|
fields = values.get("default", [])
|
||||||
|
|
|
@ -24,21 +24,22 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
from importlib import import_module
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.messages import get_messages
|
from django.contrib.messages import get_messages
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from preferences.models import GeneralOption, OptionalMachine
|
|
||||||
from django.utils.translation import get_language
|
from django.utils.translation import get_language
|
||||||
from importlib import import_module
|
|
||||||
|
from preferences.models import GeneralOption, OptionalMachine
|
||||||
from re2o.settings_local import OPTIONNAL_APPS_RE2O
|
from re2o.settings_local import OPTIONNAL_APPS_RE2O
|
||||||
|
|
||||||
|
|
||||||
def context_user(request):
|
def context_user(request):
|
||||||
"""Global Context function
|
"""Global Context function
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict:Containing user's interfaces and himself if logged, else None
|
dict:Containing user's interfaces and himself if logged, else None
|
||||||
|
|
||||||
"""
|
"""
|
||||||
user = request.user
|
user = request.user
|
||||||
|
@ -51,9 +52,11 @@ def context_user(request):
|
||||||
if global_message not in [msg.message for msg in get_messages(request)]:
|
if global_message not in [msg.message for msg in get_messages(request)]:
|
||||||
messages.warning(request, global_message)
|
messages.warning(request, global_message)
|
||||||
else:
|
else:
|
||||||
if global_message not in [msg.message for msg in get_messages(request._request)]:
|
if global_message not in [
|
||||||
|
msg.message for msg in get_messages(request._request)
|
||||||
|
]:
|
||||||
messages.warning(request._request, global_message)
|
messages.warning(request._request, global_message)
|
||||||
if user.is_authenticated():
|
if user.is_authenticated:
|
||||||
interfaces = user.user_interfaces()
|
interfaces = user.user_interfaces()
|
||||||
else:
|
else:
|
||||||
interfaces = None
|
interfaces = None
|
||||||
|
@ -70,9 +73,9 @@ def context_user(request):
|
||||||
def context_optionnal_apps(request):
|
def context_optionnal_apps(request):
|
||||||
"""Context functions. Called to add optionnal apps buttons in navbari
|
"""Context functions. Called to add optionnal apps buttons in navbari
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict:Containing optionnal template list of functions for navbar found
|
dict:Containing optionnal template list of functions for navbar found
|
||||||
in optional apps
|
in optional apps
|
||||||
|
|
||||||
"""
|
"""
|
||||||
optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS_RE2O]
|
optionnal_apps = [import_module(app) for app in OPTIONNAL_APPS_RE2O]
|
||||||
|
|
|
@ -4,44 +4,44 @@ A list of the proud contributors to Re2o
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CONTRIBUTORS = [
|
CONTRIBUTORS = [
|
||||||
'Gabriel Detraz',
|
"Gabriel Detraz",
|
||||||
'Hugo Levy-falk',
|
"Hugo Levy-falk",
|
||||||
'Maël Kervella',
|
"Maël Kervella",
|
||||||
'Jean-romain Garnier',
|
"Jean-romain Garnier",
|
||||||
'Arthur Grisel-davy',
|
"Arthur Grisel-davy",
|
||||||
'Laouen Fernet',
|
"Laouen Fernet",
|
||||||
'Augustin Lemesle',
|
"Augustin Lemesle",
|
||||||
'Lara Kermarec',
|
"Lara Kermarec",
|
||||||
'Root `root` Root',
|
"Root `root` Root",
|
||||||
'Alexandre Iooss',
|
"Alexandre Iooss",
|
||||||
'Yoann Piétri',
|
"Yoann Piétri",
|
||||||
'Charlie Jacomme',
|
"Charlie Jacomme",
|
||||||
'Corentin Canebier',
|
"Corentin Canebier",
|
||||||
'Bombar Maxime',
|
"Bombar Maxime",
|
||||||
'Guillaume Goessel',
|
"Guillaume Goessel",
|
||||||
'Matthieu Michelet',
|
"Matthieu Michelet",
|
||||||
'Edpibu',
|
"Edpibu",
|
||||||
'Fardale',
|
"Fardale",
|
||||||
'Jean-marie Mineau',
|
"Jean-marie Mineau",
|
||||||
'David Sinquin',
|
"David Sinquin",
|
||||||
'Gabriel Le Bouder',
|
"Gabriel Le Bouder",
|
||||||
'Simon Brélivet',
|
"Simon Brélivet",
|
||||||
'~anonymised~',
|
"~anonymised~",
|
||||||
'Benjamin Graillot',
|
"Benjamin Graillot",
|
||||||
'Leïla Bekaddour',
|
"Leïla Bekaddour",
|
||||||
'Éloi Alain',
|
"Éloi Alain",
|
||||||
'Pierre Cadart',
|
"Pierre Cadart",
|
||||||
'Antoine Vintache',
|
"Antoine Vintache",
|
||||||
'Thibault De Boutray',
|
"Thibault De Boutray",
|
||||||
'Delphine Salvy',
|
"Delphine Salvy",
|
||||||
'Joanne Steiner',
|
"Joanne Steiner",
|
||||||
'Krokmou',
|
"Krokmou",
|
||||||
'B',
|
"B",
|
||||||
'Daniel Stan',
|
"Daniel Stan",
|
||||||
'Gwenael Le Hir',
|
"Gwenael Le Hir",
|
||||||
'Hugo Hervieux',
|
"Hugo Hervieux",
|
||||||
'Mikachu',
|
"Mikachu",
|
||||||
'Nymous',
|
"Nymous",
|
||||||
'Pierre-antoine Comby',
|
"Pierre-antoine Comby",
|
||||||
'Vincent Le Gallic',
|
"Vincent Le Gallic",
|
||||||
]
|
]
|
|
@ -40,8 +40,8 @@ class FieldPermissionModelMixin:
|
||||||
FIELD_PERMISSION_MISSING_DEFAULT = True
|
FIELD_PERMISSION_MISSING_DEFAULT = True
|
||||||
|
|
||||||
def has_field_perm(self, user, field):
|
def has_field_perm(self, user, field):
|
||||||
""" Checks if a `user` has the right to edit the `field`
|
"""Checks if a `user` has the right to edit the `field`
|
||||||
of this model """
|
of this model"""
|
||||||
if field in self.field_permissions:
|
if field in self.field_permissions:
|
||||||
checks = self.field_permissions[field]
|
checks = self.field_permissions[field]
|
||||||
if not isinstance(checks, (list, tuple)):
|
if not isinstance(checks, (list, tuple)):
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue