diff --git a/cotisations/forms.py b/cotisations/forms.py index ba4c066f..3459f0de 100644 --- a/cotisations/forms.py +++ b/cotisations/forms.py @@ -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, diff --git a/cotisations/models.py b/cotisations/models.py index cbf44b79..10aa868e 100644 --- a/cotisations/models.py +++ b/cotisations/models.py @@ -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 @@ -180,7 +181,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 +326,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 +382,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 +397,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 +427,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" diff --git a/cotisations/views.py b/cotisations/views.py index a9c996d6..974f659e 100644 --- a/cotisations/views.py +++ b/cotisations/views.py @@ -39,8 +39,6 @@ from django.forms import modelformset_factory, formset_factory from django.utils import timezone from django.views.decorators.csrf import csrf_exempt from django.views.decorators.debug import sensitive_variables -from reversion import revisions as reversion -from reversion.models import Version # Import des models, forms et fonctions re2o from users.models import User from re2o.settings import LOGO_PATH @@ -126,10 +124,7 @@ def new_facture(request, user, userid): 'users:profil', kwargs={'userid': userid} )) - with transaction.atomic(), reversion.create_revision(): - new_facture_instance.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_facture_instance.save() for art_item in articles: if art_item.cleaned_data: article = art_item.cleaned_data['article'] @@ -142,10 +137,7 @@ def new_facture(request, user, userid): duration=article.duration, number=quantity ) - with transaction.atomic(), reversion.create_revision(): - new_vente.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_vente.save() if any(art_item.cleaned_data['article'].type_cotisation for art_item in articles if art_item.cleaned_data): messages.success( @@ -257,13 +249,8 @@ def edit_facture(request, facture, factureid): ) vente_form = vente_form_set(request.POST or None, queryset=ventes_objects) if facture_form.is_valid() and vente_form.is_valid(): - with transaction.atomic(), reversion.create_revision(): - facture_form.save() - vente_form.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for form in vente_form for field - in facture_form.changed_data + form.changed_data)) + facture_form.save() + vente_form.save() messages.success(request, "La facture a bien été modifiée") return redirect(reverse('cotisations:index')) return form({ @@ -278,9 +265,7 @@ def del_facture(request, facture, factureid): """Suppression d'une facture. Supprime en cascade les ventes et cotisations filles""" if request.method == "POST": - with transaction.atomic(), reversion.create_revision(): - facture.delete() - reversion.set_user(request.user) + facture.delete() messages.success(request, "La facture a été détruite") return redirect(reverse('cotisations:index')) return form({ @@ -297,21 +282,15 @@ def credit_solde(request, user, userid): facture = CreditSoldeForm(request.POST or None) if facture.is_valid(): facture_instance = facture.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - facture_instance.user = user - facture_instance.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + facture_instance.user = user + facture_instance.save() new_vente = Vente.objects.create( facture=facture_instance, name="solde", prix=facture.cleaned_data['montant'], number=1 ) - with transaction.atomic(), reversion.create_revision(): - new_vente.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_vente.save() messages.success(request, "Solde modifié") return redirect(reverse('cotisations:index')) return form({'factureform': facture, 'action_name' : 'Créditer'}, 'cotisations/facture.html', request) @@ -329,10 +308,7 @@ def add_article(request): PAS de conséquence sur les ventes déjà faites""" article = ArticleForm(request.POST or None) if article.is_valid(): - with transaction.atomic(), reversion.create_revision(): - article.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + article.save() messages.success(request, "L'article a été ajouté") return redirect(reverse('cotisations:index-article')) return form({'factureform': article, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request) @@ -345,14 +321,7 @@ def edit_article(request, article_instance, articleid): Réservé au trésorier""" article = ArticleForm(request.POST or None, instance=article_instance) if article.is_valid(): - with transaction.atomic(), reversion.create_revision(): - article.save() - reversion.set_user(request.user) - reversion.set_comment( - "Champs modifié(s) : %s" % ', '.join( - field for field in article.changed_data - ) - ) + article.save() messages.success(request, "Type d'article modifié") return redirect(reverse('cotisations:index-article')) return form({'factureform': article, 'action_name' : 'Editer'}, 'cotisations/facture.html', request) @@ -365,9 +334,7 @@ def del_article(request, instances): article = DelArticleForm(request.POST or None, instances=instances) if article.is_valid(): article_del = article.cleaned_data['articles'] - with transaction.atomic(), reversion.create_revision(): - article_del.delete() - reversion.set_user(request.user) + article_del.delete() messages.success(request, "Le/les articles ont été supprimé") return redirect(reverse('cotisations:index-article')) return form({'factureform': article, 'action_name' : 'Supprimer'}, 'cotisations/facture.html', request) @@ -380,10 +347,7 @@ def add_paiement(request): via foreign key""" paiement = PaiementForm(request.POST or None) if paiement.is_valid(): - with transaction.atomic(), reversion.create_revision(): - paiement.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + paiement.save() messages.success(request, "Le moyen de paiement a été ajouté") return redirect(reverse('cotisations:index-paiement')) return form({'factureform': paiement, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request) @@ -395,14 +359,7 @@ def edit_paiement(request, paiement_instance, paiementid): """Edition d'un moyen de paiement""" paiement = PaiementForm(request.POST or None, instance=paiement_instance) if paiement.is_valid(): - with transaction.atomic(), reversion.create_revision(): - paiement.save() - reversion.set_user(request.user) - reversion.set_comment( - "Champs modifié(s) : %s" % ', '.join( - field for field in paiement.changed_data - ) - ) + paiement.save() messages.success(request, "Type de paiement modifié") return redirect(reverse('cotisations:index-paiement')) return form({'factureform': paiement, 'action_name' : 'Editer'}, 'cotisations/facture.html', request) @@ -417,10 +374,7 @@ def del_paiement(request, instances): paiement_dels = paiement.cleaned_data['paiements'] for paiement_del in paiement_dels: try: - with transaction.atomic(), reversion.create_revision(): - paiement_del.delete() - reversion.set_user(request.user) - reversion.set_comment("Destruction") + paiement_del.delete() messages.success( request, "Le moyen de paiement a été supprimé" @@ -441,10 +395,7 @@ def add_banque(request): """Ajoute une banque à la liste des banques""" banque = BanqueForm(request.POST or None) if banque.is_valid(): - with transaction.atomic(), reversion.create_revision(): - banque.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + banque.save() messages.success(request, "La banque a été ajoutée") return redirect(reverse('cotisations:index-banque')) return form({'factureform': banque, 'action_name' : 'Ajouter'}, 'cotisations/facture.html', request) @@ -456,14 +407,7 @@ def edit_banque(request, banque_instance, banqueid): """Edite le nom d'une banque""" banque = BanqueForm(request.POST or None, instance=banque_instance) if banque.is_valid(): - with transaction.atomic(), reversion.create_revision(): - banque.save() - reversion.set_user(request.user) - reversion.set_comment( - "Champs modifié(s) : %s" % ', '.join( - field for field in banque.changed_data - ) - ) + banque.save() messages.success(request, "Banque modifiée") return redirect(reverse('cotisations:index-banque')) return form({'factureform': banque, 'action_name' : 'Editer'}, 'cotisations/facture.html', request) @@ -478,10 +422,7 @@ def del_banque(request, instances): banque_dels = banque.cleaned_data['banques'] for banque_del in banque_dels: try: - with transaction.atomic(), reversion.create_revision(): - banque_del.delete() - reversion.set_user(request.user) - reversion.set_comment("Destruction") + banque_del.delete() messages.success(request, "La banque a été supprimée") except ProtectedError: messages.error(request, "La banque %s est affectée à au moins\ @@ -519,10 +460,7 @@ def control(request): facture_list = paginator.page(paginator.num.pages) controlform = controlform_set(request.POST or None, queryset=facture_list.object_list) if controlform.is_valid(): - with transaction.atomic(), reversion.create_revision(): - controlform.save() - reversion.set_user(request.user) - reversion.set_comment("Controle trésorier") + controlform.save() return redirect(reverse('cotisations:control')) return render(request, 'cotisations/control.html', { 'facture_list': facture_list, @@ -630,10 +568,7 @@ def new_facture_solde(request, userid): 'users:profil', kwargs={'userid': userid} )) - with transaction.atomic(), reversion.create_revision(): - facture.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + facture.save() for art_item in articles: if art_item.cleaned_data: article = art_item.cleaned_data['article'] @@ -646,10 +581,7 @@ def new_facture_solde(request, userid): duration=article.duration, number=quantity ) - with transaction.atomic(), reversion.create_revision(): - new_vente.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_vente.save() if any(art_item.cleaned_data['article'].type_cotisation for art_item in articles if art_item.cleaned_data): messages.success( diff --git a/machines/forms.py b/machines/forms.py index 5dc9dd8b..6ece03e8 100644 --- a/machines/forms.py +++ b/machines/forms.py @@ -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: diff --git a/machines/models.py b/machines/models.py index d4368b2e..c7d9fe83 100644 --- a/machines/models.py +++ b/machines/models.py @@ -39,13 +39,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" @@ -163,7 +163,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 +203,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 +333,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 +351,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 +390,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 +467,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 +530,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 +555,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 +576,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 +599,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 +661,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 +908,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 +1012,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 +1170,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 +1202,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 +1256,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 +1287,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 +1346,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. diff --git a/machines/views.py b/machines/views.py index eb7086c4..dcc43ff9 100644 --- a/machines/views.py +++ b/machines/views.py @@ -39,7 +39,6 @@ from django.contrib import messages from django.contrib.auth.decorators import login_required, permission_required from django.db.models import ProtectedError, F from django.forms import ValidationError, modelformset_factory -from django.db import transaction from django.contrib.auth import authenticate, login from django.views.decorators.csrf import csrf_exempt @@ -238,20 +237,11 @@ def new_machine(request, user, userid): domain.instance.interface_parent = new_interface if domain.is_valid(): new_domain = domain.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - new_machine.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_machine.save() new_interface.machine = new_machine - with transaction.atomic(), reversion.create_revision(): - new_interface.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_interface.save() new_domain.interface_parent = new_interface - with transaction.atomic(), reversion.create_revision(): - new_domain.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_domain.save() messages.success(request, "La machine a été créée") return redirect(reverse( 'users:profil', @@ -287,18 +277,9 @@ def edit_interface(request, interface_instance, interfaceid): new_machine = machine_form.save(commit=False) new_interface = interface_form.save(commit=False) new_domain = domain_form.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - new_machine.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in machine_form.changed_data)) - with transaction.atomic(), reversion.create_revision(): - new_interface.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in interface_form.changed_data)) - with transaction.atomic(), reversion.create_revision(): - new_domain.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in domain_form.changed_data)) + new_machine.save() + new_interface.save() + new_domain.save() messages.success(request, "La machine a été modifiée") return redirect(reverse( 'users:profil', @@ -318,9 +299,7 @@ def edit_interface(request, interface_instance, interfaceid): def del_machine(request, machine, machineid): """ Supprime une machine, interfaces en mode cascade""" if request.method == "POST": - with transaction.atomic(), reversion.create_revision(): - machine.delete() - reversion.set_user(request.user) + machine.delete() messages.success(request, "La machine a été détruite") return redirect(reverse( 'users:profil', @@ -342,15 +321,9 @@ def new_interface(request, machine, machineid): new_interface.machine = machine if domain_form.is_valid(): new_domain = domain_form.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - new_interface.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_interface.save() new_domain.interface_parent = new_interface - with transaction.atomic(), reversion.create_revision(): - new_domain.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_domain.save() messages.success(request, "L'interface a été ajoutée") return redirect(reverse( 'users:profil', @@ -370,11 +343,9 @@ def del_interface(request, interface, interfaceid): """ Supprime une interface. Domain objet en mode cascade""" if request.method == "POST": machine = interface.machine - with transaction.atomic(), reversion.create_revision(): - interface.delete() - if not machine.interface_set.all(): - machine.delete() - reversion.set_user(request.user) + interface.delete() + if not machine.interface_set.all(): + machine.delete() messages.success(request, "L'interface a été détruite") return redirect(reverse( 'users:profil', @@ -390,10 +361,7 @@ def new_ipv6list(request, interface, interfaceid): ipv6list_instance = Ipv6List(interface=interface) ipv6 = Ipv6ListForm(request.POST or None, instance=ipv6list_instance, user=request.user) if ipv6.is_valid(): - with transaction.atomic(), reversion.create_revision(): - ipv6.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + ipv6.save() messages.success(request, "Ipv6 ajoutée") return redirect(reverse( 'machines:index-ipv6', @@ -407,10 +375,7 @@ def edit_ipv6list(request, ipv6list_instance, ipv6listid): """Edition d'une ipv6""" ipv6 = Ipv6ListForm(request.POST or None, instance=ipv6list_instance, user=request.user) if ipv6.is_valid(): - with transaction.atomic(), reversion.create_revision(): - ipv6.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in ipv6.changed_data)) + ipv6.save() messages.success(request, "Ipv6 modifiée") return redirect(reverse( 'machines:index-ipv6', @@ -424,9 +389,7 @@ def del_ipv6list(request, ipv6list, ipv6listid): """ Supprime une ipv6""" if request.method == "POST": interfaceid = ipv6list.interface.id - with transaction.atomic(), reversion.create_revision(): - ipv6list.delete() - reversion.set_user(request.user) + ipv6list.delete() messages.success(request, "L'ipv6 a été détruite") return redirect(reverse( 'machines:index-ipv6', @@ -441,10 +404,7 @@ def add_iptype(request): iptype = IpTypeForm(request.POST or None) if iptype.is_valid(): - with transaction.atomic(), reversion.create_revision(): - iptype.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + iptype.save() messages.success(request, "Ce type d'ip a été ajouté") return redirect(reverse('machines:index-iptype')) return form({'iptypeform': iptype, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -456,10 +416,7 @@ def edit_iptype(request, iptype_instance, iptypeid): iptype = EditIpTypeForm(request.POST or None, instance=iptype_instance) if iptype.is_valid(): - with transaction.atomic(), reversion.create_revision(): - iptype.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in iptype.changed_data)) + iptype.save() messages.success(request, "Type d'ip modifié") return redirect(reverse('machines:index-iptype')) return form({'iptypeform': iptype, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -473,9 +430,7 @@ def del_iptype(request, instances): iptype_dels = iptype.cleaned_data['iptypes'] for iptype_del in iptype_dels: try: - with transaction.atomic(), reversion.create_revision(): - iptype_del.delete() - reversion.set_user(request.user) + iptype_del.delete() messages.success(request, "Le type d'ip a été supprimé") except ProtectedError: messages.error(request, "Le type d'ip %s est affectée à au moins une machine, vous ne pouvez pas le supprimer" % iptype_del) @@ -488,10 +443,7 @@ def add_machinetype(request): machinetype = MachineTypeForm(request.POST or None) if machinetype.is_valid(): - with transaction.atomic(), reversion.create_revision(): - machinetype.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + machinetype.save() messages.success(request, "Ce type de machine a été ajouté") return redirect(reverse('machines:index-machinetype')) return form({'machinetypeform': machinetype, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -502,10 +454,7 @@ def edit_machinetype(request, machinetype_instance, machinetypeid): machinetype = MachineTypeForm(request.POST or None, instance=machinetype_instance) if machinetype.is_valid(): - with transaction.atomic(), reversion.create_revision(): - machinetype.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in machinetype.changed_data)) + machinetype.save() messages.success(request, "Type de machine modifié") return redirect(reverse('machines:index-machinetype')) return form({'machinetypeform': machinetype, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -518,9 +467,7 @@ def del_machinetype(request, instances): machinetype_dels = machinetype.cleaned_data['machinetypes'] for machinetype_del in machinetype_dels: try: - with transaction.atomic(), reversion.create_revision(): - machinetype_del.delete() - reversion.set_user(request.user) + machinetype_del.delete() messages.success(request, "Le type de machine a été supprimé") except ProtectedError: messages.error(request, "Le type de machine %s est affectée à au moins une machine, vous ne pouvez pas le supprimer" % machinetype_del) @@ -533,10 +480,7 @@ def add_extension(request): extension = ExtensionForm(request.POST or None) if extension.is_valid(): - with transaction.atomic(), reversion.create_revision(): - extension.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + extension.save() messages.success(request, "Cette extension a été ajoutée") return redirect(reverse('machines:index-extension')) return form({'extensionform': extension, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -547,10 +491,7 @@ def edit_extension(request, extension_instance, extensionid): extension = ExtensionForm(request.POST or None, instance=extension_instance) if extension.is_valid(): - with transaction.atomic(), reversion.create_revision(): - extension.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in extension.changed_data)) + extension.save() messages.success(request, "Extension modifiée") return redirect(reverse('machines:index-extension')) return form({'extensionform': extension, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -563,9 +504,7 @@ def del_extension(request, instances): extension_dels = extension.cleaned_data['extensions'] for extension_del in extension_dels: try: - with transaction.atomic(), reversion.create_revision(): - extension_del.delete() - reversion.set_user(request.user) + extension_del.delete() messages.success(request, "L'extension a été supprimée") except ProtectedError: messages.error(request, "L'extension %s est affectée à au moins un type de machine, vous ne pouvez pas la supprimer" % extension_del) @@ -578,10 +517,7 @@ def add_soa(request): soa = SOAForm(request.POST or None) if soa.is_valid(): - with transaction.atomic(), reversion.create_revision(): - soa.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + soa.save() messages.success(request, "Cet enregistrement SOA a été ajouté") return redirect(reverse('machines:index-extension')) return form({'soaform': soa, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -592,10 +528,7 @@ def edit_soa(request, soa_instance, soaid): soa = SOAForm(request.POST or None, instance=soa_instance) if soa.is_valid(): - with transaction.atomic(), reversion.create_revision(): - soa.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in soa.changed_data)) + soa.save() messages.success(request, "SOA modifié") return redirect(reverse('machines:index-extension')) return form({'soaform': soa, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -608,9 +541,7 @@ def del_soa(request, instances): soa_dels = soa.cleaned_data['soa'] for soa_del in soa_dels: try: - with transaction.atomic(), reversion.create_revision(): - soa_del.delete() - reversion.set_user(request.user) + soa_del.delete() messages.success(request, "Le SOA a été supprimée") except ProtectedError: messages.error(request, "Erreur le SOA suivant %s ne peut être supprimé" % soa_del) @@ -623,10 +554,7 @@ def add_mx(request): mx = MxForm(request.POST or None) if mx.is_valid(): - with transaction.atomic(), reversion.create_revision(): - mx.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + mx.save() messages.success(request, "Cet enregistrement mx a été ajouté") return redirect(reverse('machines:index-extension')) return form({'mxform': mx, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -637,10 +565,7 @@ def edit_mx(request, mx_instance, mxid): mx = MxForm(request.POST or None, instance=mx_instance) if mx.is_valid(): - with transaction.atomic(), reversion.create_revision(): - mx.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in mx.changed_data)) + mx.save() messages.success(request, "Mx modifié") return redirect(reverse('machines:index-extension')) return form({'mxform': mx, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -653,9 +578,7 @@ def del_mx(request, instances): mx_dels = mx.cleaned_data['mx'] for mx_del in mx_dels: try: - with transaction.atomic(), reversion.create_revision(): - mx_del.delete() - reversion.set_user(request.user) + mx_del.delete() messages.success(request, "L'mx a été supprimée") except ProtectedError: messages.error(request, "Erreur le Mx suivant %s ne peut être supprimé" % mx_del) @@ -668,10 +591,7 @@ def add_ns(request): ns = NsForm(request.POST or None) if ns.is_valid(): - with transaction.atomic(), reversion.create_revision(): - ns.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + ns.save() messages.success(request, "Cet enregistrement ns a été ajouté") return redirect(reverse('machines:index-extension')) return form({'nsform': ns, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -682,10 +602,7 @@ def edit_ns(request, ns_instance, nsid): ns = NsForm(request.POST or None, instance=ns_instance) if ns.is_valid(): - with transaction.atomic(), reversion.create_revision(): - ns.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in ns.changed_data)) + ns.save() messages.success(request, "Ns modifié") return redirect(reverse('machines:index-extension')) return form({'nsform': ns, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -698,9 +615,7 @@ def del_ns(request, instances): ns_dels = ns.cleaned_data['ns'] for ns_del in ns_dels: try: - with transaction.atomic(), reversion.create_revision(): - ns_del.delete() - reversion.set_user(request.user) + ns_del.delete() messages.success(request, "Le ns a été supprimée") except ProtectedError: messages.error(request, "Erreur le Ns suivant %s ne peut être supprimé" % ns_del) @@ -713,10 +628,7 @@ def add_txt(request): txt = TxtForm(request.POST or None) if txt.is_valid(): - with transaction.atomic(), reversion.create_revision(): - txt.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + txt.save() messages.success(request, "Cet enregistrement text a été ajouté") return redirect(reverse('machines:index-extension')) return form({'txtform': txt, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -727,10 +639,7 @@ def edit_txt(request, txt_instance, txtid): txt = TxtForm(request.POST or None, instance=txt_instance) if txt.is_valid(): - with transaction.atomic(), reversion.create_revision(): - txt.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in txt.changed_data)) + txt.save() messages.success(request, "Txt modifié") return redirect(reverse('machines:index-extension')) return form({'txtform': txt, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -743,9 +652,7 @@ def del_txt(request, instances): txt_dels = txt.cleaned_data['txt'] for txt_del in txt_dels: try: - with transaction.atomic(), reversion.create_revision(): - txt_del.delete() - reversion.set_user(request.user) + txt_del.delete() messages.success(request, "Le txt a été supprimé") except ProtectedError: messages.error(request, "Erreur le Txt suivant %s ne peut être supprimé" % txt_del) @@ -758,10 +665,7 @@ def add_srv(request): srv = SrvForm(request.POST or None) if srv.is_valid(): - with transaction.atomic(), reversion.create_revision(): - srv.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + srv.save() messages.success(request, "Cet enregistrement srv a été ajouté") return redirect(reverse('machines:index-extension')) return form({'srvform': srv, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -772,10 +676,7 @@ def edit_srv(request, srv_instance, srvid): srv = SrvForm(request.POST or None, instance=srv_instance) if srv.is_valid(): - with transaction.atomic(), reversion.create_revision(): - srv.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in srv.changed_data)) + srv.save() messages.success(request, "Srv modifié") return redirect(reverse('machines:index-extension')) return form({'srvform': srv, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -788,9 +689,7 @@ def del_srv(request, instances): srv_dels = srv.cleaned_data['srv'] for srv_del in srv_dels: try: - with transaction.atomic(), reversion.create_revision(): - srv_del.delete() - reversion.set_user(request.user) + srv_del.delete() messages.success(request, "L'srv a été supprimée") except ProtectedError: messages.error(request, "Erreur le Srv suivant %s ne peut être supprimé" % srv_del) @@ -806,10 +705,7 @@ def add_alias(request, interface, interfaceid): if alias.is_valid(): alias = alias.save(commit=False) alias.cname = interface.domain - with transaction.atomic(), reversion.create_revision(): - alias.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + alias.save() messages.success(request, "Cet alias a été ajouté") return redirect(reverse( 'machines:index-alias', @@ -823,10 +719,7 @@ def edit_alias(request, domain_instance, domainid): alias = AliasForm(request.POST or None, instance=domain_instance, user=request.user) if alias.is_valid(): - with transaction.atomic(), reversion.create_revision(): - domain_instance = alias.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in alias.changed_data)) + domain_instance = alias.save() messages.success(request, "Alias modifié") return redirect(reverse( 'machines:index-alias', @@ -842,9 +735,7 @@ def del_alias(request, interface, interfaceid): alias_dels = alias.cleaned_data['alias'] for alias_del in alias_dels: try: - with transaction.atomic(), reversion.create_revision(): - alias_del.delete() - reversion.set_user(request.user) + alias_del.delete() messages.success(request, "L'alias %s a été supprimé" % alias_del) except ProtectedError: messages.error(request, "Erreur l'alias suivant %s ne peut être supprimé" % alias_del) @@ -861,10 +752,7 @@ def add_service(request): service = ServiceForm(request.POST or None) if service.is_valid(): - with transaction.atomic(), reversion.create_revision(): - service.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + service.save() messages.success(request, "Cet enregistrement service a été ajouté") return redirect(reverse('machines:index-service')) return form({'serviceform': service, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -875,10 +763,7 @@ def edit_service(request, service_instance, serviceid): service = ServiceForm(request.POST or None, instance=service_instance) if service.is_valid(): - with transaction.atomic(), reversion.create_revision(): - service.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in service.changed_data)) + service.save() messages.success(request, "Service modifié") return redirect(reverse('machines:index-service')) return form({'serviceform': service, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -891,9 +776,7 @@ def del_service(request, instances): service_dels = service.cleaned_data['service'] for service_del in service_dels: try: - with transaction.atomic(), reversion.create_revision(): - service_del.delete() - reversion.set_user(request.user) + service_del.delete() messages.success(request, "Le service a été supprimée") except ProtectedError: messages.error(request, "Erreur le service suivant %s ne peut être supprimé" % service_del) @@ -906,10 +789,7 @@ def add_vlan(request): vlan = VlanForm(request.POST or None) if vlan.is_valid(): - with transaction.atomic(), reversion.create_revision(): - vlan.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + vlan.save() messages.success(request, "Cet enregistrement vlan a été ajouté") return redirect(reverse('machines:index-vlan')) return form({'vlanform': vlan, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -920,10 +800,7 @@ def edit_vlan(request, vlan_instance, vlanid): vlan = VlanForm(request.POST or None, instance=vlan_instance) if vlan.is_valid(): - with transaction.atomic(), reversion.create_revision(): - vlan.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in vlan.changed_data)) + vlan.save() messages.success(request, "Vlan modifié") return redirect(reverse('machines:index-vlan')) return form({'vlanform': vlan, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -936,9 +813,7 @@ def del_vlan(request, instances): vlan_dels = vlan.cleaned_data['vlan'] for vlan_del in vlan_dels: try: - with transaction.atomic(), reversion.create_revision(): - vlan_del.delete() - reversion.set_user(request.user) + vlan_del.delete() messages.success(request, "Le vlan a été supprimée") except ProtectedError: messages.error(request, "Erreur le Vlan suivant %s ne peut être supprimé" % vlan_del) @@ -951,10 +826,7 @@ def add_nas(request): nas = NasForm(request.POST or None) if nas.is_valid(): - with transaction.atomic(), reversion.create_revision(): - nas.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + nas.save() messages.success(request, "Cet enregistrement nas a été ajouté") return redirect(reverse('machines:index-nas')) return form({'nasform': nas, 'action_name' : 'Créer'}, 'machines/machine.html', request) @@ -965,10 +837,7 @@ def edit_nas(request, nas_instance, nasid): nas = NasForm(request.POST or None, instance=nas_instance) if nas.is_valid(): - with transaction.atomic(), reversion.create_revision(): - nas.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in nas.changed_data)) + nas.save() messages.success(request, "Nas modifié") return redirect(reverse('machines:index-nas')) return form({'nasform': nas, 'action_name' : 'Editer'}, 'machines/machine.html', request) @@ -981,9 +850,7 @@ def del_nas(request, instances): nas_dels = nas.cleaned_data['nas'] for nas_del in nas_dels: try: - with transaction.atomic(), reversion.create_revision(): - nas_del.delete() - reversion.set_user(request.user) + nas_del.delete() messages.success(request, "Le nas a été supprimé") except ProtectedError: messages.error(request, "Erreur le Nas suivant %s ne peut être supprimé" % nas_del) diff --git a/re2o/mixins.py b/re2o/mixins.py index 09c197d5..1432d7d9 100644 --- a/re2o/mixins.py +++ b/re2o/mixins.py @@ -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 != None: + 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 diff --git a/re2o/settings.py b/re2o/settings.py index d1c27192..c101460b 100644 --- a/re2o/settings.py +++ b/re2o/settings.py @@ -89,6 +89,7 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', + 'reversion.middleware.RevisionMiddleware', ) ROOT_URLCONF = 're2o.urls' diff --git a/topologie/forms.py b/topologie/forms.py index 7b8f0955..f6bfaf26 100644 --- a/topologie/forms.py +++ b/topologie/forms.py @@ -50,9 +50,9 @@ from .models import ( ConstructorSwitch, AccessPoint ) +from re2o.mixins import FormRevMixin - -class PortForm(ModelForm): +class PortForm(FormRevMixin, ModelForm): """Formulaire pour la création d'un port d'un switch Relié directement au modèle port""" class Meta: @@ -149,7 +149,7 @@ class NewSwitchForm(NewMachineForm): fields = ['name', 'location', 'number', 'stack', 'stack_member_id'] -class EditRoomForm(ModelForm): +class EditRoomForm(FormRevMixin, ModelForm): """Permet d'éediter le nom et commentaire d'une prise murale""" class Meta: model = Room @@ -160,13 +160,13 @@ class EditRoomForm(ModelForm): super(EditRoomForm, self).__init__(*args, prefix=prefix, **kwargs) -class CreatePortsForm(forms.Form): +class CreatePortsForm(FormRevMixin, forms.Form): """Permet de créer une liste de ports pour un switch.""" begin = forms.IntegerField(label="Début :", min_value=0) end = forms.IntegerField(label="Fin :", min_value=0) -class EditModelSwitchForm(ModelForm): +class EditModelSwitchForm(FormRevMixin, ModelForm): """Permet d'éediter un modèle de switch : nom et constructeur""" class Meta: model = ModelSwitch @@ -177,7 +177,7 @@ class EditModelSwitchForm(ModelForm): super(EditModelSwitchForm, self).__init__(*args, prefix=prefix, **kwargs) -class EditConstructorSwitchForm(ModelForm): +class EditConstructorSwitchForm(FormRevMixin, ModelForm): """Permet d'éediter le nom d'un constructeur""" class Meta: model = ConstructorSwitch diff --git a/topologie/models.py b/topologie/models.py index 9cef5c44..7e08917c 100644 --- a/topologie/models.py +++ b/topologie/models.py @@ -48,9 +48,9 @@ from django.db import transaction from reversion import revisions as reversion from machines.models import Machine, Interface, regen -from re2o.mixins import AclMixin +from re2o.mixins import AclMixin, RevMixin -class Stack(AclMixin, models.Model): +class Stack(AclMixin, RevMixin, models.Model): """Un objet stack. Regrouppe des switchs en foreign key ,contient une id de stack, un switch id min et max dans le stack""" @@ -187,7 +187,7 @@ class Switch(AclMixin, Machine): return str(self.interface_set.first()) -class ModelSwitch(AclMixin, models.Model): +class ModelSwitch(AclMixin, RevMixin, models.Model): """Un modèle (au sens constructeur) de switch""" PRETTY_NAME = "Modèle de switch" reference = models.CharField(max_length=255) @@ -205,7 +205,7 @@ class ModelSwitch(AclMixin, models.Model): return str(self.constructor) + ' ' + self.reference -class ConstructorSwitch(AclMixin, models.Model): +class ConstructorSwitch(AclMixin, RevMixin, models.Model): """Un constructeur de switch""" PRETTY_NAME = "Constructeur de switch" name = models.CharField(max_length=255) @@ -219,7 +219,7 @@ class ConstructorSwitch(AclMixin, models.Model): return self.name -class Port(AclMixin, models.Model): +class Port(AclMixin, RevMixin, models.Model): """ Definition d'un port. Relié à un switch(foreign_key), un port peut etre relié de manière exclusive à : - une chambre (room) @@ -335,7 +335,7 @@ class Port(AclMixin, models.Model): return str(self.switch) + " - " + str(self.port) -class Room(AclMixin, models.Model): +class Room(AclMixin, RevMixin, models.Model): """Une chambre/local contenant une prise murale""" PRETTY_NAME = "Chambre/ Prise murale" diff --git a/topologie/views.py b/topologie/views.py index 97b01ebb..f942f377 100644 --- a/topologie/views.py +++ b/topologie/views.py @@ -44,8 +44,6 @@ from django.db import transaction from django.db.models import ProtectedError, Prefetch from django.core.exceptions import ValidationError from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from reversion import revisions as reversion -from reversion.models import Version from topologie.models import ( Switch, @@ -262,10 +260,7 @@ def new_port(request, switchid): port = port.save(commit=False) port.switch = switch try: - with transaction.atomic(), reversion.create_revision(): - port.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + port.save() messages.success(request, "Port ajouté") except IntegrityError: messages.error(request, "Ce port existe déjà") @@ -284,12 +279,7 @@ def edit_port(request, port_object, portid): port = EditPortForm(request.POST or None, instance=port_object) if port.is_valid(): - with transaction.atomic(), reversion.create_revision(): - port.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in port.changed_data - )) + port.save() messages.success(request, "Le port a bien été modifié") return redirect(reverse( 'topologie:index-port', @@ -304,11 +294,8 @@ def del_port(request, port, portid): """ Supprime le port""" if request.method == "POST": try: - with transaction.atomic(), reversion.create_revision(): - port.delete() - reversion.set_user(request.user) - reversion.set_comment("Destruction") - messages.success(request, "Le port a été détruit") + port.delete() + messages.success(request, "Le port a été détruit") except ProtectedError: messages.error(request, "Le port %s est affecté à un autre objet,\ impossible de le supprimer" % port) @@ -325,10 +312,7 @@ def new_stack(request): """Ajoute un nouveau stack : stackid_min, max, et nombre de switches""" stack = StackForm(request.POST or None) if stack.is_valid(): - with transaction.atomic(), reversion.create_revision(): - stack.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + stack.save() messages.success(request, "Stack crée") return form({'topoform': stack, 'action_name' : 'Créer'}, 'topologie/topo.html', request) @@ -340,15 +324,8 @@ def edit_stack(request, stack, stackid): stack = StackForm(request.POST or None, instance=stack) if stack.is_valid(): - with transaction.atomic(), reversion.create_revision(): - stack.save() - reversion.set_user(request.user) - reversion.set_comment( - "Champs modifié(s) : %s" % ', '.join( - field for field in stack.changed_data - ) - ) - return redirect(reverse('topologie:index-stack')) + stack.save() + return redirect(reverse('topologie:index-stack')) return form({'topoform': stack, 'action_name' : 'Editer'}, 'topologie/topo.html', request) @@ -358,11 +335,8 @@ def del_stack(request, stack, stackid): """Supprime un stack""" if request.method == "POST": try: - with transaction.atomic(), reversion.create_revision(): - stack.delete() - reversion.set_user(request.user) - reversion.set_comment("Destruction") - messages.success(request, "La stack a eté détruite") + stack.delete() + messages.success(request, "La stack a eté détruite") except ProtectedError: messages.error(request, "La stack %s est affectée à un autre\ objet, impossible de la supprimer" % stack) @@ -412,20 +386,11 @@ def new_switch(request): domain.instance.interface_parent = new_interface_instance if domain.is_valid(): new_domain_instance = domain.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - new_switch.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_switch.save() new_interface_instance.machine = new_switch - with transaction.atomic(), reversion.create_revision(): - new_interface_instance.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_interface_instance.save() new_domain_instance.interface_parent = new_interface_instance - with transaction.atomic(), reversion.create_revision(): - new_domain_instance.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_domain_instance.save() messages.success(request, "Le switch a été créé") return redirect(reverse('topologie:index')) i_mbf_param = generate_ipv4_mbf_param(interface, False) @@ -500,26 +465,9 @@ def edit_switch(request, switch, switchid): new_switch = switch_form.save(commit=False) new_interface_instance = interface_form.save(commit=False) new_domain = domain_form.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - new_switch.save() - reversion.set_user(request.user) - reversion.set_comment( - "Champs modifié(s) : %s" % ', '.join( - field for field in switch_form.changed_data - ) - ) - with transaction.atomic(), reversion.create_revision(): - new_interface_instance.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in interface_form.changed_data) - ) - with transaction.atomic(), reversion.create_revision(): - new_domain.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in domain_form.changed_data) - ) + new_switch.save() + new_interface_instance.save() + new_domain.save() messages.success(request, "Le switch a bien été modifié") return redirect(reverse('topologie:index')) i_mbf_param = generate_ipv4_mbf_param(interface_form, False ) @@ -562,20 +510,11 @@ def new_ap(request): domain.instance.interface_parent = new_interface if domain.is_valid(): new_domain_instance = domain.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - new_ap.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_ap.save() new_interface.machine = new_ap - with transaction.atomic(), reversion.create_revision(): - new_interface.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_interface.save() new_domain_instance.interface_parent = new_interface - with transaction.atomic(), reversion.create_revision(): - new_domain_instance.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + new_domain_instance.save() messages.success(request, "La borne a été créé") return redirect(reverse('topologie:index-ap')) i_mbf_param = generate_ipv4_mbf_param(interface, False) @@ -616,26 +555,9 @@ def edit_ap(request, ap, accesspointid): new_ap = ap_form.save(commit=False) new_interface = interface_form.save(commit=False) new_domain = domain_form.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - new_ap.save() - reversion.set_user(request.user) - reversion.set_comment( - "Champs modifié(s) : %s" % ', '.join( - field for field in ap_form.changed_data) - ) - with transaction.atomic(), reversion.create_revision(): - new_interface.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in interface_form.changed_data) - ) - reversion.set_comment("Création") - with transaction.atomic(), reversion.create_revision(): - new_domain.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in domain_form.changed_data) - ) + new_ap.save() + new_interface.save() + new_domain.save() messages.success(request, "La borne a été modifiée") return redirect(reverse('topologie:index-ap')) i_mbf_param = generate_ipv4_mbf_param(interface_form, False ) @@ -654,10 +576,7 @@ def new_room(request): """Nouvelle chambre """ room = EditRoomForm(request.POST or None) if room.is_valid(): - with transaction.atomic(), reversion.create_revision(): - room.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + room.save() messages.success(request, "La chambre a été créé") return redirect(reverse('topologie:index-room')) return form({'topoform': room, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request) @@ -670,12 +589,7 @@ def edit_room(request, room, roomid): room = EditRoomForm(request.POST or None, instance=room) if room.is_valid(): - with transaction.atomic(), reversion.create_revision(): - room.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in room.changed_data) - ) + room.save() messages.success(request, "La chambre a bien été modifiée") return redirect(reverse('topologie:index-room')) return form({'topoform': room, 'action_name' : 'Editer'}, 'topologie/topo.html', request) @@ -687,11 +601,8 @@ def del_room(request, room, roomid): """ Suppression d'un chambre""" if request.method == "POST": try: - with transaction.atomic(), reversion.create_revision(): - room.delete() - reversion.set_user(request.user) - reversion.set_comment("Destruction") - messages.success(request, "La chambre/prise a été détruite") + room.delete() + messages.success(request, "La chambre/prise a été détruite") except ProtectedError: messages.error(request, "La chambre %s est affectée à un autre objet,\ impossible de la supprimer (switch ou user)" % room) @@ -708,10 +619,7 @@ def new_model_switch(request): """Nouveau modèle de switch""" model_switch = EditModelSwitchForm(request.POST or None) if model_switch.is_valid(): - with transaction.atomic(), reversion.create_revision(): - model_switch.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + model_switch.save() messages.success(request, "Le modèle a été créé") return redirect(reverse('topologie:index-model-switch')) return form({'topoform': model_switch, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request) @@ -724,12 +632,7 @@ def edit_model_switch(request, model_switch, modelswitchid): model_switch = EditModelSwitchForm(request.POST or None, instance=model_switch) if model_switch.is_valid(): - with transaction.atomic(), reversion.create_revision(): - model_switch.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in model_switch.changed_data) - ) + model_switch.save() messages.success(request, "Le modèle a bien été modifié") return redirect(reverse('topologie:index-model-switch')) return form({'topoform': model_switch, 'action_name' : 'Editer'}, 'topologie/topo.html', request) @@ -741,11 +644,8 @@ def del_model_switch(request, model_switch, modelswitchid): """ Suppression d'un modèle de switch""" if request.method == "POST": try: - with transaction.atomic(), reversion.create_revision(): - model_switch.delete() - reversion.set_user(request.user) - reversion.set_comment("Destruction") - messages.success(request, "Le modèle a été détruit") + model_switch.delete() + messages.success(request, "Le modèle a été détruit") except ProtectedError: messages.error(request, "Le modèle %s est affectée à un autre objet,\ impossible de la supprimer (switch ou user)" % model_switch) @@ -762,10 +662,7 @@ def new_constructor_switch(request): """Nouveau constructeur de switch""" constructor_switch = EditConstructorSwitchForm(request.POST or None) if constructor_switch.is_valid(): - with transaction.atomic(), reversion.create_revision(): - constructor_switch.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + constructor_switch.save() messages.success(request, "Le constructeur a été créé") return redirect(reverse('topologie:index-model-switch')) return form({'topoform': constructor_switch, 'action_name' : 'Ajouter'}, 'topologie/topo.html', request) @@ -778,12 +675,7 @@ def edit_constructor_switch(request, constructor_switch, constructorswitchid): constructor_switch = EditConstructorSwitchForm(request.POST or None, instance=constructor_switch) if constructor_switch.is_valid(): - with transaction.atomic(), reversion.create_revision(): - constructor_switch.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in constructor_switch.changed_data) - ) + constructor_switch.save() messages.success(request, "Le modèle a bien été modifié") return redirect(reverse('topologie:index-model-switch')) return form({'topoform': constructor_switch, 'action_name' : 'Editer'}, 'topologie/topo.html', request) @@ -795,11 +687,8 @@ def del_constructor_switch(request, constructor_switch, constructorswitchid): """ Suppression d'un constructeur de switch""" if request.method == "POST": try: - with transaction.atomic(), reversion.create_revision(): - constructor_switch.delete() - reversion.set_user(request.user) - reversion.set_comment("Destruction") - messages.success(request, "Le constructeur a été détruit") + constructor_switch.delete() + messages.success(request, "Le constructeur a été détruit") except ProtectedError: messages.error(request, "Le constructeur %s est affecté à un autre objet,\ impossible de la supprimer (switch ou user)" % constructor_switch) diff --git a/users/forms.py b/users/forms.py index 81f1e343..3617b26f 100644 --- a/users/forms.py +++ b/users/forms.py @@ -53,13 +53,11 @@ from .models import ( Club ) from re2o.utils import remove_user_room - +from re2o.mixins import FormRevMixin from re2o.field_permissions import FieldPermissionFormMixin -NOW = timezone.now() - -class PassForm(FieldPermissionFormMixin, forms.ModelForm): +class PassForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm): """Formulaire de changement de mot de passe. Verifie que les 2 nouveaux mots de passe renseignés sont identiques et respectent une norme""" @@ -107,7 +105,7 @@ class PassForm(FieldPermissionFormMixin, forms.ModelForm): user.save() -class UserCreationForm(forms.ModelForm): +class UserCreationForm(FormRevMixin, forms.ModelForm): """A form for creating new users. Includes all the required fields, plus a repeated password. @@ -154,7 +152,7 @@ class UserCreationForm(forms.ModelForm): return user -class ServiceUserCreationForm(forms.ModelForm): +class ServiceUserCreationForm(FormRevMixin, forms.ModelForm): """A form for creating new users. Includes all the required fields, plus a repeated password. @@ -202,7 +200,7 @@ class ServiceUserCreationForm(forms.ModelForm): return user -class UserChangeForm(forms.ModelForm): +class UserChangeForm(FormRevMixin, forms.ModelForm): """A form for updating users. Includes all the fields on the user, but replaces the password field with admin's password hash display field. @@ -238,7 +236,7 @@ class UserChangeForm(forms.ModelForm): return user -class ServiceUserChangeForm(forms.ModelForm): +class ServiceUserChangeForm(FormRevMixin, forms.ModelForm): """A form for updating users. Includes all the fields on the user, but replaces the password field with admin's password hash display field. @@ -281,12 +279,12 @@ class MassArchiveForm(forms.Form): cleaned_data = super(MassArchiveForm, self).clean() date = cleaned_data.get("date") if date: - if date > NOW: + if date > timezone.now(): raise forms.ValidationError("Impossible d'archiver des\ utilisateurs dont la fin d'accès se situe dans le futur !") -class AdherentForm(FieldPermissionFormMixin, ModelForm): +class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): """Formulaire de base d'edition d'un user. Formulaire de base, utilisé pour l'edition de self par self ou un cableur. On formate les champs avec des label plus jolis""" @@ -339,7 +337,7 @@ class AdherentForm(FieldPermissionFormMixin, ModelForm): return -class ClubForm(FieldPermissionFormMixin, ModelForm): +class ClubForm(FormRevMixin, FieldPermissionFormMixin, ModelForm): """Formulaire de base d'edition d'un user. Formulaire de base, utilisé pour l'edition de self par self ou un cableur. On formate les champs avec des label plus jolis""" @@ -379,7 +377,7 @@ class ClubForm(FieldPermissionFormMixin, ModelForm): return telephone -class ClubAdminandMembersForm(ModelForm): +class ClubAdminandMembersForm(FormRevMixin, ModelForm): """Permet d'éditer la liste des membres et des administrateurs d'un club""" class Meta: @@ -391,7 +389,7 @@ class ClubAdminandMembersForm(ModelForm): super(ClubAdminandMembersForm, self).__init__(*args, prefix=prefix, **kwargs) -class PasswordForm(ModelForm): +class PasswordForm(FormRevMixin, ModelForm): """ Formulaire de changement brut de mot de passe. Ne pas utiliser sans traitement""" class Meta: @@ -403,7 +401,7 @@ class PasswordForm(ModelForm): super(PasswordForm, self).__init__(*args, prefix=prefix, **kwargs) -class ServiceUserForm(ModelForm): +class ServiceUserForm(FormRevMixin, ModelForm): """ Modification d'un service user""" password = forms.CharField( label=u'Nouveau mot de passe', @@ -429,7 +427,7 @@ class EditServiceUserForm(ServiceUserForm): fields = ['access_group', 'comment'] -class StateForm(ModelForm): +class StateForm(FormRevMixin, ModelForm): """ Changement de l'état d'un user""" class Meta: model = User @@ -440,7 +438,7 @@ class StateForm(ModelForm): super(StateForm, self).__init__(*args, prefix=prefix, **kwargs) -class GroupForm(ModelForm): +class GroupForm(FormRevMixin, ModelForm): """ Gestion des groupes d'un user""" groups = forms.ModelMultipleChoiceField( Group.objects.all(), @@ -457,7 +455,7 @@ class GroupForm(ModelForm): super(GroupForm, self).__init__(*args, prefix=prefix, **kwargs) -class SchoolForm(ModelForm): +class SchoolForm(FormRevMixin, ModelForm): """Edition, creation d'un école""" class Meta: model = School @@ -469,7 +467,7 @@ class SchoolForm(ModelForm): self.fields['name'].label = 'Établissement' -class ShellForm(ModelForm): +class ShellForm(FormRevMixin, ModelForm): """Edition, creation d'un école""" class Meta: model = ListShell @@ -481,7 +479,7 @@ class ShellForm(ModelForm): self.fields['shell'].label = 'Nom du shell' -class ListRightForm(ModelForm): +class ListRightForm(FormRevMixin, ModelForm): """Edition, d'un groupe , équivalent à un droit Ne peremet pas d'editer le gid, car il sert de primary key""" permissions = forms.ModelMultipleChoiceField( @@ -545,7 +543,7 @@ class DelSchoolForm(Form): self.fields['schools'].queryset = School.objects.all() -class BanForm(ModelForm): +class BanForm(FormRevMixin, ModelForm): """Creation, edition d'un objet bannissement""" def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) @@ -557,7 +555,7 @@ class BanForm(ModelForm): exclude = ['user'] -class WhitelistForm(ModelForm): +class WhitelistForm(FormRevMixin, ModelForm): """Creation, edition d'un objet whitelist""" def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) diff --git a/users/models.py b/users/models.py index 512259ae..caa03ce3 100644 --- a/users/models.py +++ b/users/models.py @@ -76,7 +76,7 @@ import ldapdb.models.fields from re2o.settings import RIGHTS_LINK, LDAP, GID_RANGES, UID_RANGES from re2o.login import hashNT from re2o.field_permissions import FieldPermissionModelMixin -from re2o.mixins import AclMixin +from re2o.mixins import AclMixin, RevMixin from cotisations.models import Cotisation, Facture, Paiement, Vente from machines.models import Domain, Interface, Machine, regen @@ -171,7 +171,7 @@ class UserManager(BaseUserManager): """ return self._create_user(pseudo, surname, email, password, True) -class User(FieldPermissionModelMixin, AbstractBaseUser, PermissionsMixin, AclMixin): +class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMixin, AclMixin): """ Definition de l'utilisateur de base. Champs principaux : name, surnname, pseudo, email, room, password Herite du django BaseUser et du système d'auth django""" @@ -907,7 +907,7 @@ def user_post_delete(sender, **kwargs): user.ldap_del() regen('mailing') -class ServiceUser(AclMixin, AbstractBaseUser): +class ServiceUser(RevMixin, AclMixin, AbstractBaseUser): """ Classe des users daemons, règle leurs accès au ldap""" readonly = 'readonly' ACCESS = ( @@ -991,7 +991,7 @@ def service_user_post_delete(sender, **kwargs): service_user.ldap_del() -class School(AclMixin, models.Model): +class School(RevMixin, AclMixin, models.Model): """ Etablissement d'enseignement""" PRETTY_NAME = "Établissements enregistrés" @@ -1006,7 +1006,7 @@ class School(AclMixin, models.Model): return self.name -class ListRight(AclMixin, Group): +class ListRight(RevMixin, AclMixin, Group): """ Ensemble des droits existants. Chaque droit crée un groupe ldap synchronisé, avec gid. Permet de gérer facilement les accès serveurs et autres @@ -1073,7 +1073,7 @@ def listright_post_delete(sender, **kwargs): right.ldap_del() -class ListShell(AclMixin, models.Model): +class ListShell(RevMixin, AclMixin, models.Model): """Un shell possible. Pas de check si ce shell existe, les admin sont des grands""" PRETTY_NAME = "Liste des shells disponibles" @@ -1093,7 +1093,7 @@ class ListShell(AclMixin, models.Model): return self.shell -class Ban(AclMixin, models.Model): +class Ban(RevMixin, AclMixin, models.Model): """ Bannissement. Actuellement a un effet tout ou rien. Gagnerait à être granulaire""" PRETTY_NAME = "Liste des bannissements" @@ -1189,7 +1189,7 @@ def ban_post_delete(sender, **kwargs): regen('mac_ip_list') -class Whitelist(AclMixin, models.Model): +class Whitelist(RevMixin, AclMixin, models.Model): """Accès à titre gracieux. L'utilisateur ne paye pas; se voit accorder un accès internet pour une durée défini. Moins fort qu'un ban quel qu'il soit""" diff --git a/users/views.py b/users/views.py index 73332e8b..3374fea9 100644 --- a/users/views.py +++ b/users/views.py @@ -115,10 +115,7 @@ def new_user(request): GTU = GeneralOption.get_cached_value('GTU') if user.is_valid(): user = user.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - user.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + user.save() user.reset_passwd_mail(request) messages.success(request, "L'utilisateur %s a été crée, un mail\ pour l'initialisation du mot de passe a été envoyé" % user.pseudo) @@ -137,10 +134,7 @@ def new_club(request): club = ClubForm(request.POST or None, user=request.user) if club.is_valid(): club = club.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - club.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + club.save() club.reset_passwd_mail(request) messages.success(request, "L'utilisateur %s a été crée, un mail\ pour l'initialisation du mot de passe a été envoyé" % club.pseudo) @@ -158,12 +152,7 @@ def edit_club_admin_members(request, club_instance, clubid): membres d'un club""" club = ClubAdminandMembersForm(request.POST or None, instance=club_instance) if club.is_valid(): - with transaction.atomic(), reversion.create_revision(): - club.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in club.changed_data - )) + club.save() messages.success(request, "Le club a bien été modifié") return redirect(reverse( 'users:profil', @@ -191,12 +180,7 @@ def edit_info(request, user, userid): user=request.user ) if user.is_valid(): - with transaction.atomic(), reversion.create_revision(): - user.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in user.changed_data - )) + user.save() messages.success(request, "L'user a bien été modifié") return redirect(reverse( 'users:profil', @@ -212,18 +196,13 @@ def state(request, user, userid): need droit bureau """ state = StateForm(request.POST or None, instance=user) if state.is_valid(): - with transaction.atomic(), reversion.create_revision(): - if state.cleaned_data['state'] == User.STATE_ARCHIVE: - user.archive() - elif state.cleaned_data['state'] == User.STATE_ACTIVE: - user.unarchive() - elif state.cleaned_data['state'] == User.STATE_DISABLED: - user.state = User.STATE_DISABLED - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in state.changed_data - )) - user.save() + if state.cleaned_data['state'] == User.STATE_ARCHIVE: + user.archive() + elif state.cleaned_data['state'] == User.STATE_ACTIVE: + user.unarchive() + elif state.cleaned_data['state'] == User.STATE_DISABLED: + user.state = User.STATE_DISABLED + user.save() messages.success(request, "Etat changé avec succès") return redirect(reverse( 'users:profil', @@ -237,11 +216,6 @@ def state(request, user, userid): def groups(request, user, userid): group = GroupForm(request.POST or None, instance=user) if group.is_valid(): - with transaction.atomic(), reversion.create_revision(): - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in group.changed_data - )) group.save() messages.success(request, "Groupes changés avec succès") return redirect(reverse( @@ -259,10 +233,7 @@ def password(request, user, userid): pour tous si droit bureau """ u_form = PassForm(request.POST or None, instance=user, user=request.user) if u_form.is_valid(): - with transaction.atomic(), reversion.create_revision(): - u_form.save() - reversion.set_user(request.user) - reversion.set_comment("Changement du mot de passe") + u_form.save() messages.success(request, "Le mot de passe a changé") return redirect(reverse( 'users:profil', @@ -274,12 +245,9 @@ def password(request, user, userid): @login_required @can_edit(User, 'groups') def del_group(request, user, userid, listrightid): - with transaction.atomic(), reversion.create_revision(): - user.groups.remove(ListRight.objects.get(id=listrightid)) - user.save() - reversion.set_user(request.user) - reversion.set_comment("Suppression de droit") - messages.success(request, "Droit supprimé à %s" % user) + user.groups.remove(ListRight.objects.get(id=listrightid)) + user.save() + messages.success(request, "Droit supprimé à %s" % user) return HttpResponseRedirect(request.META.get('HTTP_REFERER')) @@ -290,11 +258,8 @@ def new_serviceuser(request): user = ServiceUserForm(request.POST or None) if user.is_valid(): user_object = user.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - user_object.set_password(user.cleaned_data['password']) - user_object.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + user_object.set_password(user.cleaned_data['password']) + user_object.save() messages.success( request, "L'utilisateur %s a été crée" % user_object.pseudo @@ -310,14 +275,9 @@ def edit_serviceuser(request, user, userid): user = EditServiceUserForm(request.POST or None, instance=user) if user.is_valid(): user_object = user.save(commit=False) - with transaction.atomic(), reversion.create_revision(): - if user.cleaned_data['password']: - user_object.set_password(user.cleaned_data['password']) - user_object.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in user.changed_data - )) + if user.cleaned_data['password']: + user_object.set_password(user.cleaned_data['password']) + user_object.save() messages.success(request, "L'user a bien été modifié") return redirect(reverse('users:index-serviceusers')) return form({'userform': user, 'action_name':'Editer un serviceuser'}, 'users/user.html', request) @@ -328,9 +288,7 @@ def edit_serviceuser(request, user, userid): def del_serviceuser(request, user, userid): """Suppression d'un ou plusieurs serviceusers""" if request.method == "POST": - with transaction.atomic(), reversion.create_revision(): - user.delete() - reversion.set_user(request.user) + user.delete() messages.success(request, "L'user a été détruite") return redirect(reverse('users:index-serviceusers')) return form( @@ -350,10 +308,7 @@ def add_ban(request, user, userid): ban_instance = Ban(user=user) ban = BanForm(request.POST or None, instance=ban_instance) if ban.is_valid(): - with transaction.atomic(), reversion.create_revision(): - _ban_object = ban.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + _ban_object = ban.save() messages.success(request, "Bannissement ajouté") return redirect(reverse( 'users:profil', @@ -374,12 +329,7 @@ def edit_ban(request, ban_instance, banid): Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement""" ban = BanForm(request.POST or None, instance=ban_instance) if ban.is_valid(): - with transaction.atomic(), reversion.create_revision(): - ban.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in ban.changed_data - )) + ban.save() messages.success(request, "Bannissement modifié") return redirect(reverse('users:index')) return form({'userform': ban, 'action_name': 'Editer un ban'}, 'users/user.html', request) @@ -399,10 +349,7 @@ def add_whitelist(request, user, userid): instance=whitelist_instance ) if whitelist.is_valid(): - with transaction.atomic(), reversion.create_revision(): - whitelist.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + whitelist.save() messages.success(request, "Accès à titre gracieux accordé") return redirect(reverse( 'users:profil', @@ -428,12 +375,7 @@ def edit_whitelist(request, whitelist_instance, whitelistid): instance=whitelist_instance ) if whitelist.is_valid(): - with transaction.atomic(), reversion.create_revision(): - whitelist.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in whitelist.changed_data - )) + whitelist.save() messages.success(request, "Whitelist modifiée") return redirect(reverse('users:index')) return form({'userform': whitelist, 'action_name': 'Editer une whitelist'}, 'users/user.html', request) @@ -446,10 +388,7 @@ def add_school(request): need cableur""" school = SchoolForm(request.POST or None) if school.is_valid(): - with transaction.atomic(), reversion.create_revision(): - school.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + school.save() messages.success(request, "L'établissement a été ajouté") return redirect(reverse('users:index-school')) return form({'userform': school, 'action_name':'Ajouter'}, 'users/user.html', request) @@ -462,12 +401,7 @@ def edit_school(request, school_instance, schoolid): la base de donnée, need cableur""" school = SchoolForm(request.POST or None, instance=school_instance) if school.is_valid(): - with transaction.atomic(), reversion.create_revision(): - school.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in school.changed_data - )) + school.save() messages.success(request, "Établissement modifié") return redirect(reverse('users:index-school')) return form({'userform': school, 'action_name':'Editer'}, 'users/user.html', request) @@ -485,9 +419,7 @@ def del_school(request, instances): school_dels = school.cleaned_data['schools'] for school_del in school_dels: try: - with transaction.atomic(), reversion.create_revision(): - school_del.delete() - reversion.set_comment("Destruction") + school_del.delete() messages.success(request, "L'établissement a été supprimé") except ProtectedError: messages.error( @@ -504,10 +436,7 @@ def add_shell(request): """ Ajouter un shell à la base de donnée""" shell = ShellForm(request.POST or None) if shell.is_valid(): - with transaction.atomic(), reversion.create_revision(): - shell.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + shell.save() messages.success(request, "Le shell a été ajouté") return redirect(reverse('users:index-shell')) return form({'userform': shell, 'action_name':'Ajouter'}, 'users/user.html', request) @@ -519,12 +448,7 @@ def edit_shell(request, shell_instance, listshellid): """ Editer un shell à partir du listshellid""" shell = ShellForm(request.POST or None, instance=shell_instance) if shell.is_valid(): - with transaction.atomic(), reversion.create_revision(): - shell.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in shell.changed_data - )) + shell.save() messages.success(request, "Le shell a été modifié") return redirect(reverse('users:index-shell')) return form({'userform': shell, 'action_name':'Editer'}, 'users/user.html', request) @@ -535,9 +459,7 @@ def edit_shell(request, shell_instance, listshellid): def del_shell(request, shell, listshellid): """Destruction d'un shell""" if request.method == "POST": - with transaction.atomic(), reversion.create_revision(): - shell.delete() - reversion.set_user(request.user) + shell.delete() messages.success(request, "Le shell a été détruit") return redirect(reverse('users:index-shell')) return form( @@ -554,10 +476,7 @@ def add_listright(request): Obligation de fournir un gid pour la synchro ldap, unique """ listright = NewListRightForm(request.POST or None) if listright.is_valid(): - with transaction.atomic(), reversion.create_revision(): - listright.save() - reversion.set_user(request.user) - reversion.set_comment("Création") + listright.save() messages.success(request, "Le droit/groupe a été ajouté") return redirect(reverse('users:index-listright')) return form({'userform': listright, 'action_name': 'Ajouter'}, 'users/user.html', request) @@ -573,12 +492,7 @@ def edit_listright(request, listright_instance, listrightid): instance=listright_instance ) if listright.is_valid(): - with transaction.atomic(), reversion.create_revision(): - listright.save() - reversion.set_user(request.user) - reversion.set_comment("Champs modifié(s) : %s" % ', '.join( - field for field in listright.changed_data - )) + listright.save() messages.success(request, "Droit modifié") return redirect(reverse('users:index-listright')) return form({'userform': listright, 'action_name': 'Editer'}, 'users/user.html', request) @@ -594,9 +508,7 @@ def del_listright(request, instances): listright_dels = listright.cleaned_data['listrights'] for listright_del in listright_dels: try: - with transaction.atomic(), reversion.create_revision(): - listright_del.delete() - reversion.set_comment("Destruction") + listright_del.delete() messages.success(request, "Le droit/groupe a été supprimé") except ProtectedError: messages.error( @@ -625,7 +537,6 @@ def mass_archive(request): with transaction.atomic(), reversion.create_revision(): user.archive() user.save() - reversion.set_user(request.user) reversion.set_comment("Archivage") messages.success(request, "%s users ont été archivés" % len( to_archive_list