Commit 39a1c4eb authored by guimoz's avatar guimoz

Merge branch 'profil_frontend' into 'master'

Profil frontend

See merge request federez/re2o!111
parents 22143e8a 2fffa98d
......@@ -45,9 +45,9 @@ from preferences.models import OptionalUser
from users.models import User
from re2o.field_permissions import FieldPermissionFormMixin
from re2o.mixins import FormRevMixin
class NewFactureForm(ModelForm):
class NewFactureForm(FormRevMixin, ModelForm):
"""Creation d'une facture, moyen de paiement, banque et numero
de cheque"""
def __init__(self, *args, **kwargs):
......@@ -96,7 +96,7 @@ class CreditSoldeForm(NewFactureForm):
montant = forms.DecimalField(max_digits=5, decimal_places=2, required=True)
class SelectUserArticleForm(Form):
class SelectUserArticleForm(FormRevMixin, Form):
"""Selection d'un article lors de la creation d'une facture"""
article = forms.ModelChoiceField(
queryset=Article.objects.filter(Q(type_user='All') | Q(type_user='Adherent')),
......@@ -158,7 +158,7 @@ class EditFactureForm(FieldPermissionFormMixin, NewFactureForm):
self.fields['valid'].label = 'Validité de la facture'
class ArticleForm(ModelForm):
class ArticleForm(FormRevMixin, ModelForm):
"""Creation d'un article. Champs : nom, cotisation, durée"""
class Meta:
model = Article
......@@ -170,7 +170,7 @@ class ArticleForm(ModelForm):
self.fields['name'].label = "Désignation de l'article"
class DelArticleForm(Form):
class DelArticleForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs articles en vente. Choix
parmis les modèles"""
articles = forms.ModelMultipleChoiceField(
......@@ -188,7 +188,7 @@ class DelArticleForm(Form):
self.fields['articles'].queryset = Article.objects.all()
class PaiementForm(ModelForm):
class PaiementForm(FormRevMixin, ModelForm):
"""Creation d'un moyen de paiement, champ text moyen et type
permettant d'indiquer si il s'agit d'un chèque ou non pour le form"""
class Meta:
......@@ -202,7 +202,7 @@ class PaiementForm(ModelForm):
self.fields['type_paiement'].label = 'Type de paiement à ajouter'
class DelPaiementForm(Form):
class DelPaiementForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs moyens de paiements, selection
parmis les models"""
paiements = forms.ModelMultipleChoiceField(
......@@ -220,7 +220,7 @@ class DelPaiementForm(Form):
self.fields['paiements'].queryset = Paiement.objects.all()
class BanqueForm(ModelForm):
class BanqueForm(FormRevMixin, ModelForm):
"""Creation d'une banque, field name"""
class Meta:
model = Banque
......@@ -232,7 +232,7 @@ class BanqueForm(ModelForm):
self.fields['name'].label = 'Banque à ajouter'
class DelBanqueForm(Form):
class DelBanqueForm(FormRevMixin, Form):
"""Selection d'une ou plusieurs banques, pour suppression"""
banques = forms.ModelMultipleChoiceField(
queryset=Banque.objects.none(),
......@@ -283,7 +283,7 @@ class NewFactureSoldeForm(NewFactureForm):
return cleaned_data
class RechargeForm(Form):
class RechargeForm(FormRevMixin, Form):
value = forms.FloatField(
label='Valeur',
min_value=0.01,
......
......@@ -57,9 +57,10 @@ from django.utils import timezone
from machines.models import regen
from re2o.field_permissions import FieldPermissionModelMixin
from re2o.mixins import AclMixin
from re2o.mixins import AclMixin, RevMixin
class Facture(AclMixin, FieldPermissionModelMixin, models.Model):
class Facture(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
""" Définition du modèle des factures. Une facture regroupe une ou
plusieurs ventes, rattachée à un user, et reliée à un moyen de paiement
et si il y a lieu un numero pour les chèques. Possède les valeurs
......@@ -87,6 +88,11 @@ class Facture(AclMixin, FieldPermissionModelMixin, models.Model):
("change_all_facture", "Superdroit, peut modifier toutes les factures"),
)
def linked_objects(self):
"""Return linked objects : machine and domain.
Usefull in history display"""
return self.vente_set.all()
def prix(self):
"""Renvoie le prix brut sans les quantités. Méthode
dépréciée"""
......@@ -180,7 +186,7 @@ def facture_post_delete(sender, **kwargs):
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
class Vente(AclMixin, models.Model):
class Vente(RevMixin, AclMixin, models.Model):
"""Objet vente, contient une quantité, une facture parente, un nom,
un prix. Peut-être relié à un objet cotisation, via le boolean
iscotisation"""
......@@ -325,7 +331,7 @@ def vente_post_delete(sender, **kwargs):
user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
class Article(AclMixin, models.Model):
class Article(RevMixin, AclMixin, models.Model):
"""Liste des articles en vente : prix, nom, et attribut iscotisation
et duree si c'est une cotisation"""
PRETTY_NAME = "Articles en vente"
......@@ -381,7 +387,7 @@ class Article(AclMixin, models.Model):
return self.name
class Banque(AclMixin, models.Model):
class Banque(RevMixin, AclMixin, models.Model):
"""Liste des banques"""
PRETTY_NAME = "Banques enregistrées"
......@@ -396,7 +402,7 @@ class Banque(AclMixin, models.Model):
return self.name
class Paiement(AclMixin, models.Model):
class Paiement(RevMixin, AclMixin, models.Model):
"""Moyens de paiement"""
PRETTY_NAME = "Moyens de paiement"
PAYMENT_TYPES = (
......@@ -426,7 +432,7 @@ class Paiement(AclMixin, models.Model):
super(Paiement, self).save(*args, **kwargs)
class Cotisation(AclMixin, models.Model):
class Cotisation(RevMixin, AclMixin, models.Model):
"""Objet cotisation, debut et fin, relié en onetoone à une vente"""
PRETTY_NAME = "Cotisations"
......
This diff is collapsed.
......@@ -39,7 +39,6 @@ from __future__ import unicode_literals
from django.urls import reverse
from django.shortcuts import render, redirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Count, Max
......@@ -100,6 +99,7 @@ from re2o.utils import (
all_baned,
all_has_access,
all_adherent,
re2o_paginator,
)
from re2o.acl import (
can_view_all,
......@@ -139,17 +139,7 @@ def index(request):
request.GET.get('order'),
SortTable.LOGS_INDEX
)
paginator = Paginator(versions, pagination_number)
page = request.GET.get('page')
try:
versions = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
versions = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
versions = paginator.page(paginator.num_pages)
versions = re2o_paginator(request, versions, pagination_number)
# Force to have a list instead of QuerySet
versions.count(0)
# Items to remove later because invalid
......@@ -191,16 +181,7 @@ def stats_logs(request):
request.GET.get('order'),
SortTable.LOGS_STATS_LOGS
)
paginator = Paginator(revisions, pagination_number)
page = request.GET.get('page')
try:
revisions = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
revisions = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
revisions = paginator.page(paginator.num_pages)
revisions = re2o_paginator(request, revisions, pagination_number)
return render(request, 'logs/stats_logs.html', {
'revisions_list': revisions
})
......
......@@ -39,6 +39,7 @@ from django.forms import ModelForm, Form
from django import forms
from re2o.field_permissions import FieldPermissionFormMixin
from re2o.mixins import FormRevMixin
from .models import (
Domain,
......@@ -61,7 +62,7 @@ from .models import (
)
class EditMachineForm(FieldPermissionFormMixin, ModelForm):
class EditMachineForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
"""Formulaire d'édition d'une machine"""
class Meta:
model = Machine
......@@ -79,7 +80,7 @@ class NewMachineForm(EditMachineForm):
fields = ['name']
class EditInterfaceForm(FieldPermissionFormMixin, ModelForm):
class EditInterfaceForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
"""Edition d'une interface. Edition complète"""
class Meta:
model = Interface
......@@ -125,7 +126,7 @@ class AddInterfaceForm(EditInterfaceForm):
fields = ['type', 'ipv4', 'mac_address', 'details']
class AliasForm(ModelForm):
class AliasForm(FormRevMixin, ModelForm):
"""Ajout d'un alias (et edition), CNAME, contenant nom et extension"""
class Meta:
model = Domain
......@@ -142,7 +143,7 @@ class AliasForm(ModelForm):
)
class DomainForm(ModelForm):
class DomainForm(FormRevMixin, ModelForm):
"""Ajout et edition d'un enregistrement de nom, relié à interface"""
class Meta:
model = Domain
......@@ -158,7 +159,7 @@ class DomainForm(ModelForm):
super(DomainForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelAliasForm(Form):
class DelAliasForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs objets alias"""
alias = forms.ModelMultipleChoiceField(
queryset=Domain.objects.all(),
......@@ -174,7 +175,7 @@ class DelAliasForm(Form):
)
class MachineTypeForm(ModelForm):
class MachineTypeForm(FormRevMixin, ModelForm):
"""Ajout et edition d'un machinetype, relié à un iptype"""
class Meta:
model = MachineType
......@@ -187,7 +188,7 @@ class MachineTypeForm(ModelForm):
self.fields['ip_type'].label = "Type d'ip relié"
class DelMachineTypeForm(Form):
class DelMachineTypeForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs machinetype"""
machinetypes = forms.ModelMultipleChoiceField(
queryset=MachineType.objects.none(),
......@@ -204,7 +205,7 @@ class DelMachineTypeForm(Form):
self.fields['machinetypes'].queryset = MachineType.objects.all()
class IpTypeForm(ModelForm):
class IpTypeForm(FormRevMixin, ModelForm):
"""Formulaire d'ajout d'un iptype. Pas d'edition de l'ip de start et de
stop après creation"""
class Meta:
......@@ -226,7 +227,7 @@ class EditIpTypeForm(IpTypeForm):
'ouverture_ports']
class DelIpTypeForm(Form):
class DelIpTypeForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs iptype"""
iptypes = forms.ModelMultipleChoiceField(
queryset=IpType.objects.none(),
......@@ -243,7 +244,7 @@ class DelIpTypeForm(Form):
self.fields['iptypes'].queryset = IpType.objects.all()
class ExtensionForm(ModelForm):
class ExtensionForm(FormRevMixin, ModelForm):
"""Formulaire d'ajout et edition d'une extension"""
class Meta:
model = Extension
......@@ -258,7 +259,7 @@ class ExtensionForm(ModelForm):
self.fields['soa'].label = 'En-tête SOA à utiliser'
class DelExtensionForm(Form):
class DelExtensionForm(FormRevMixin, Form):
"""Suppression d'une ou plusieurs extensions"""
extensions = forms.ModelMultipleChoiceField(
queryset=Extension.objects.none(),
......@@ -275,7 +276,7 @@ class DelExtensionForm(Form):
self.fields['extensions'].queryset = Extension.objects.all()
class Ipv6ListForm(FieldPermissionFormMixin, ModelForm):
class Ipv6ListForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
"""Gestion des ipv6 d'une machine"""
class Meta:
model = Ipv6List
......@@ -286,7 +287,7 @@ class Ipv6ListForm(FieldPermissionFormMixin, ModelForm):
super(Ipv6ListForm, self).__init__(*args, prefix=prefix, **kwargs)
class SOAForm(ModelForm):
class SOAForm(FormRevMixin, ModelForm):
"""Ajout et edition d'un SOA"""
class Meta:
model = SOA
......@@ -297,7 +298,7 @@ class SOAForm(ModelForm):
super(SOAForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelSOAForm(Form):
class DelSOAForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs SOA"""
soa = forms.ModelMultipleChoiceField(
queryset=SOA.objects.none(),
......@@ -314,7 +315,7 @@ class DelSOAForm(Form):
self.fields['soa'].queryset = SOA.objects.all()
class MxForm(ModelForm):
class MxForm(FormRevMixin, ModelForm):
"""Ajout et edition d'un MX"""
class Meta:
model = Mx
......@@ -327,7 +328,7 @@ class MxForm(ModelForm):
interface_parent=None
).select_related('extension')
class DelMxForm(Form):
class DelMxForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs MX"""
mx = forms.ModelMultipleChoiceField(
queryset=Mx.objects.none(),
......@@ -344,7 +345,7 @@ class DelMxForm(Form):
self.fields['mx'].queryset = Mx.objects.all()
class NsForm(ModelForm):
class NsForm(FormRevMixin, ModelForm):
"""Ajout d'un NS pour une zone
On exclue les CNAME dans les objets domain (interdit par la rfc)
donc on prend uniquemet """
......@@ -360,7 +361,7 @@ class NsForm(ModelForm):
).select_related('extension')
class DelNsForm(Form):
class DelNsForm(FormRevMixin, Form):
"""Suppresion d'un ou plusieurs NS"""
ns = forms.ModelMultipleChoiceField(
queryset=Ns.objects.none(),
......@@ -377,7 +378,7 @@ class DelNsForm(Form):
self.fields['ns'].queryset = Ns.objects.all()
class TxtForm(ModelForm):
class TxtForm(FormRevMixin, ModelForm):
"""Ajout d'un txt pour une zone"""
class Meta:
model = Txt
......@@ -388,7 +389,7 @@ class TxtForm(ModelForm):
super(TxtForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelTxtForm(Form):
class DelTxtForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs TXT"""
txt = forms.ModelMultipleChoiceField(
queryset=Txt.objects.none(),
......@@ -405,7 +406,7 @@ class DelTxtForm(Form):
self.fields['txt'].queryset = Txt.objects.all()
class SrvForm(ModelForm):
class SrvForm(FormRevMixin, ModelForm):
"""Ajout d'un srv pour une zone"""
class Meta:
model = Srv
......@@ -416,7 +417,7 @@ class SrvForm(ModelForm):
super(SrvForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelSrvForm(Form):
class DelSrvForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs Srv"""
srv = forms.ModelMultipleChoiceField(
queryset=Srv.objects.none(),
......@@ -433,7 +434,7 @@ class DelSrvForm(Form):
self.fields['srv'].queryset = Srv.objects.all()
class NasForm(ModelForm):
class NasForm(FormRevMixin, ModelForm):
"""Ajout d'un type de nas (machine d'authentification,
swicths, bornes...)"""
class Meta:
......@@ -445,7 +446,7 @@ class NasForm(ModelForm):
super(NasForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelNasForm(Form):
class DelNasForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs nas"""
nas = forms.ModelMultipleChoiceField(
queryset=Nas.objects.none(),
......@@ -462,7 +463,7 @@ class DelNasForm(Form):
self.fields['nas'].queryset = Nas.objects.all()
class ServiceForm(ModelForm):
class ServiceForm(FormRevMixin, ModelForm):
"""Ajout et edition d'une classe de service : dns, dhcp, etc"""
class Meta:
model = Service
......@@ -482,7 +483,7 @@ class ServiceForm(ModelForm):
return instance
class DelServiceForm(Form):
class DelServiceForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs service"""
service = forms.ModelMultipleChoiceField(
queryset=Service.objects.none(),
......@@ -499,7 +500,7 @@ class DelServiceForm(Form):
self.fields['service'].queryset = Service.objects.all()
class VlanForm(ModelForm):
class VlanForm(FormRevMixin, ModelForm):
"""Ajout d'un vlan : id, nom"""
class Meta:
model = Vlan
......@@ -510,7 +511,7 @@ class VlanForm(ModelForm):
super(VlanForm, self).__init__(*args, prefix=prefix, **kwargs)
class DelVlanForm(Form):
class DelVlanForm(FormRevMixin, Form):
"""Suppression d'un ou plusieurs vlans"""
vlan = forms.ModelMultipleChoiceField(
queryset=Vlan.objects.none(),
......@@ -527,7 +528,7 @@ class DelVlanForm(Form):
self.fields['vlan'].queryset = Vlan.objects.all()
class EditOuverturePortConfigForm(ModelForm):
class EditOuverturePortConfigForm(FormRevMixin, ModelForm):
"""Edition de la liste des profils d'ouverture de ports
pour l'interface"""
class Meta:
......@@ -543,7 +544,7 @@ class EditOuverturePortConfigForm(ModelForm):
)
class EditOuverturePortListForm(ModelForm):
class EditOuverturePortListForm(FormRevMixin, ModelForm):
"""Edition de la liste des ports et profils d'ouverture
des ports"""
class Meta:
......
......@@ -27,6 +27,7 @@ from datetime import timedelta
import re
from netaddr import mac_bare, EUI, IPSet, IPRange, IPNetwork, IPAddress
from ipaddress import IPv6Address
from itertools import chain
from django.db import models
from django.db.models.signals import post_save, post_delete
......@@ -39,13 +40,13 @@ from django.core.validators import MaxValueValidator
from macaddress.fields import MACAddressField
from re2o.field_permissions import FieldPermissionModelMixin
from re2o.mixins import AclMixin
from re2o.mixins import AclMixin, RevMixin
import users.models
import preferences.models
class Machine(FieldPermissionModelMixin, models.Model):
class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
""" Class définissant une machine, object parent user, objets fils
interfaces"""
PRETTY_NAME = "Machine"
......@@ -72,6 +73,11 @@ class Machine(FieldPermissionModelMixin, models.Model):
"""
return Machine.objects.get(pk=machineid)
def linked_objects(self):
"""Return linked objects : machine and domain.
Usefull in history display"""
return chain(self.interface_set.all(), Domain.objects.filter(interface_parent__in=self.interface_set.all()))
@staticmethod
def can_change_user(user_request, *args, **kwargs):
"""Checks if an user is allowed to change the user who owns a
......@@ -163,7 +169,7 @@ class Machine(FieldPermissionModelMixin, models.Model):
return str(self.user) + ' - ' + str(self.id) + ' - ' + str(self.name)
class MachineType(AclMixin, models.Model):
class MachineType(RevMixin, AclMixin, models.Model):
""" Type de machine, relié à un type d'ip, affecté aux interfaces"""
PRETTY_NAME = "Type de machine"
......@@ -203,7 +209,7 @@ class MachineType(AclMixin, models.Model):
return self.type
class IpType(AclMixin, models.Model):
class IpType(RevMixin, AclMixin, models.Model):
""" Type d'ip, définissant un range d'ip, affecté aux machine types"""
PRETTY_NAME = "Type d'ip"
......@@ -333,7 +339,7 @@ class IpType(AclMixin, models.Model):
return self.type
class Vlan(AclMixin, models.Model):
class Vlan(RevMixin, AclMixin, models.Model):
""" Un vlan : vlan_id et nom
On limite le vlan id entre 0 et 4096, comme défini par la norme"""
PRETTY_NAME = "Vlans"
......@@ -351,7 +357,7 @@ class Vlan(AclMixin, models.Model):
return self.name
class Nas(AclMixin, models.Model):
class Nas(RevMixin, AclMixin, models.Model):
""" Les nas. Associé à un machine_type.
Permet aussi de régler le port_access_mode (802.1X ou mac-address) pour
le radius. Champ autocapture de la mac à true ou false"""
......@@ -390,7 +396,7 @@ class Nas(AclMixin, models.Model):
return self.name
class SOA(AclMixin, models.Model):
class SOA(RevMixin, AclMixin, models.Model):
"""
Un enregistrement SOA associé à une extension
Les valeurs par défault viennent des recommandations RIPE :
......@@ -467,7 +473,7 @@ class SOA(AclMixin, models.Model):
class Extension(AclMixin, models.Model):
class Extension(RevMixin, AclMixin, models.Model):
""" Extension dns type example.org. Précise si tout le monde peut
l'utiliser, associé à un origin (ip d'origine)"""
PRETTY_NAME = "Extensions dns"
......@@ -530,7 +536,7 @@ class Extension(AclMixin, models.Model):
super(Extension, self).clean(*args, **kwargs)
class Mx(AclMixin, models.Model):
class Mx(RevMixin, AclMixin, models.Model):
""" Entrées des MX. Enregistre la zone (extension) associée et la
priorité
Todo : pouvoir associer un MX à une interface """
......@@ -555,7 +561,7 @@ class Mx(AclMixin, models.Model):
return str(self.zone) + ' ' + str(self.priority) + ' ' + str(self.name)
class Ns(AclMixin, models.Model):
class Ns(RevMixin, AclMixin, models.Model):
"""Liste des enregistrements name servers par zone considéérée"""
PRETTY_NAME = "Enregistrements NS"
......@@ -576,7 +582,7 @@ class Ns(AclMixin, models.Model):
return str(self.zone) + ' ' + str(self.ns)
class Txt(AclMixin, models.Model):
class Txt(RevMixin, AclMixin, models.Model):
""" Un enregistrement TXT associé à une extension"""
PRETTY_NAME = "Enregistrement TXT"
......@@ -599,7 +605,7 @@ class Txt(AclMixin, models.Model):
return str(self.field1).ljust(15) + " IN TXT " + str(self.field2)
class Srv(AclMixin, models.Model):
class Srv(RevMixin, AclMixin, models.Model):
PRETTY_NAME = "Enregistrement Srv"
TCP = 'TCP'
......@@ -661,7 +667,7 @@ class Srv(AclMixin, models.Model):
str(self.port) + ' ' + str(self.target) + '.'
class Interface(AclMixin, FieldPermissionModelMixin,models.Model):
class Interface(RevMixin, AclMixin, FieldPermissionModelMixin,models.Model):
""" Une interface. Objet clef de l'application machine :
- une address mac unique. Possibilité de la rendre unique avec le
typemachine
......@@ -908,7 +914,7 @@ class Interface(AclMixin, FieldPermissionModelMixin,models.Model):
return self.ipv4 and not self.has_private_ip()
class Ipv6List(AclMixin, FieldPermissionModelMixin, models.Model):
class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
PRETTY_NAME = 'Enregistrements Ipv6 des machines'
ipv6 = models.GenericIPAddressField(
......@@ -1012,7 +1018,7 @@ class Ipv6List(AclMixin, FieldPermissionModelMixin, models.Model):
return str(self.ipv6)
class Domain(AclMixin, models.Model):
class Domain(RevMixin, AclMixin, models.Model):
""" Objet domain. Enregistrement A et CNAME en même temps : permet de
stocker les alias et les nom de machines, suivant si interface_parent
ou cname sont remplis"""
......@@ -1170,7 +1176,7 @@ class Domain(AclMixin, models.Model):
return str(self.name) + str(self.extension)
class IpList(AclMixin, models.Model):
class IpList(RevMixin, AclMixin, models.Model):
PRETTY_NAME = "Addresses ipv4"
ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True)
......@@ -1202,7 +1208,7 @@ class IpList(AclMixin, models.Model):
return self.ipv4
class Service(AclMixin, models.Model):
class Service(RevMixin, AclMixin, models.Model):
""" Definition d'un service (dhcp, dns, etc)"""
PRETTY_NAME = "Services à générer (dhcp, dns, etc)"
......@@ -1256,7 +1262,7 @@ def regen(service):
return
class Service_link(AclMixin, models.Model):
class Service_link(RevMixin, AclMixin, models.Model):
""" Definition du lien entre serveurs et services"""
PRETTY_NAME = "Relation entre service et serveur"
......@@ -1287,7 +1293,7 @@ class Service_link(AclMixin, models.Model):
return str(self.server) + " " + str(self.service)
class OuverturePortList(AclMixin, models.Model):
class OuverturePortList(RevMixin, AclMixin, models.Model):
"""Liste des ports ouverts sur une interface."""
PRETTY_NAME = "Profil d'ouverture de ports"
......@@ -1346,7 +1352,7 @@ class OuverturePortList(AclMixin, models.Model):
)
class OuverturePort(AclMixin, models.Model):
class OuverturePort(RevMixin, AclMixin, models.Model):
"""
Représente un simple port ou une plage de ports.
......
......@@ -38,7 +38,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% can_edit alias %}
{% include 'buttons/edit.html' with href='machines:edit-alias' id=alias.id %}
{% acl_end %}
{% include 'buttons/history.html' with href='machines:history' name='alias' id=alias.id %}
{% include 'buttons/history.html' with href='machines:history' name='domain' id=alias.id %}
</td>
</tr>
{% endfor %}
......
This diff is collapsed.
......@@ -32,7 +32,6 @@ from __future__ import unicode_literals
from django.urls import reverse
from django.shortcuts import render, redirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import ProtectedError
......
......@@ -4,6 +4,7 @@
# quelques clics.
#
# Copyright © 2018 Gabriel Détraz
# Copyright © 2017 Charlie Jacomme
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
......@@ -19,6 +20,29 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from reversion import revisions as reversion
class RevMixin(object):
def save(self, *args, **kwargs):
if self.pk is None:
reversion.set_comment("Création")
return super(RevMixin, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
reversion.set_comment("Suppresion")
return super(RevMixin, self).delete(*args, **kwargs)
class FormRevMixin(object):
def save(self, *args, **kwargs):
if reversion.get_comment() != "" and self.changed_data != []:
reversion.set_comment(reversion.get_comment() + ",%s" % ', '.join(field for field in self.changed_data))
elif self.changed_data:
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in self.changed_data))
return super(FormRevMixin, self).save(*args, **kwargs)
class AclMixin(object):
"""This mixin is used in nearly every class/models defined in re2o apps.
It is used by acl, in models (decorators can_...) and in templates tags
......
# ⁻*- mode: python; coding: utf-8 -*-
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
# Copyright © 2018 Lev-Arcady Sellem
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os, sys, pwd
proj_path="/var/www/re2o"
os.environ.setdefault("DJANGO_SETTINGS_MODULE","re2o.settings")
sys.path.append(proj_path)
os.chdir(proj_path)
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
from django.core.management.base import CommandError
from users.models import User
from django.utils.html import strip_tags
from reversion import revisions as reversion
from django.db import transaction
from getpass import getpass