8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-25 22:22:26 +00:00

Pep8 compliance on re2o

This commit is contained in:
Maël Kervella 2018-04-13 23:42:22 +00:00
parent 287ce23d1c
commit 48d904b6de
19 changed files with 313 additions and 224 deletions

View file

@ -26,6 +26,7 @@
Here are defined some functions to check acl on the application. Here are defined some functions to check acl on the application.
""" """
def can_view(user): def can_view(user):
"""Check if an user can view the application. """Check if an user can view the application.

View file

@ -44,12 +44,16 @@ class EditOptionalUserForm(ModelForm):
prefix=prefix, prefix=prefix,
**kwargs **kwargs
) )
self.fields['is_tel_mandatory'].label = 'Exiger un numéro de\ self.fields['is_tel_mandatory'].label = (
téléphone' 'Exiger un numéro de téléphone'
self.fields['user_solde'].label = 'Activation du solde pour\ )
les utilisateurs' self.fields['user_solde'].label = (
'Activation du solde pour les utilisateurs'
)
self.fields['max_solde'].label = 'Solde maximum' self.fields['max_solde'].label = 'Solde maximum'
self.fields['min_online_payment'].label = 'Montant de rechargement minimum en ligne' self.fields['min_online_payment'].label = (
'Montant de rechargement minimum en ligne'
)
self.fields['self_adhesion'].label = 'Auto inscription' self.fields['self_adhesion'].label = 'Auto inscription'
@ -162,7 +166,6 @@ class EditAssoOptionForm(ModelForm):
return cleaned_data return cleaned_data
class EditMailMessageOptionForm(ModelForm): class EditMailMessageOptionForm(ModelForm):
"""Formulaire d'edition des messages de bienvenue personnalisés""" """Formulaire d'edition des messages de bienvenue personnalisés"""
class Meta: class Meta:

View file

@ -36,6 +36,7 @@ from django.core.cache import cache
from .aes_field import AESEncryptedField from .aes_field import AESEncryptedField
from re2o.mixins import AclMixin from re2o.mixins import AclMixin
class PreferencesModel(models.Model): class PreferencesModel(models.Model):
@classmethod @classmethod
def set_in_cache(cls): def set_in_cache(cls):
@ -46,7 +47,7 @@ class PreferencesModel(models.Model):
@classmethod @classmethod
def get_cached_value(cls, key): def get_cached_value(cls, key):
instance = cache.get(cls().__class__.__name__.lower()) instance = cache.get(cls().__class__.__name__.lower())
if instance == None: if instance is None:
instance = cls.set_in_cache() instance = cls.set_in_cache()
return getattr(instance, key) return getattr(instance, key)
@ -230,7 +231,7 @@ class GeneralOption(AclMixin, PreferencesModel):
blank=True, blank=True,
) )
GTU = models.FileField( GTU = models.FileField(
upload_to = '', upload_to='',
default="", default="",
null=True, null=True,
blank=True, blank=True,

View file

@ -73,7 +73,7 @@ urlpatterns = [
r'^history/(?P<object_name>\w+)/(?P<object_id>[0-9]+)$', r'^history/(?P<object_name>\w+)/(?P<object_id>[0-9]+)$',
re2o.views.history, re2o.views.history,
name='history', name='history',
kwargs={'application':'preferences'}, kwargs={'application': 'preferences'},
), ),
url(r'^$', views.display_options, name='display-options'), url(r'^$', views.display_options, name='display-options'),
] ]

View file

@ -128,7 +128,7 @@ def add_service(request):
messages.success(request, "Ce service a été ajouté") messages.success(request, "Ce service a été ajouté")
return redirect(reverse('preferences:display-options')) return redirect(reverse('preferences:display-options'))
return form( return form(
{'preferenceform': service, 'action_name' : 'Ajouter'}, {'preferenceform': service, 'action_name': 'Ajouter'},
'preferences/preferences.html', 'preferences/preferences.html',
request request
) )
@ -151,7 +151,7 @@ def edit_service(request, service_instance, serviceid):
messages.success(request, "Service modifié") messages.success(request, "Service modifié")
return redirect(reverse('preferences:display-options')) return redirect(reverse('preferences:display-options'))
return form( return form(
{'preferenceform': service, 'action_name' : 'Editer'}, {'preferenceform': service, 'action_name': 'Editer'},
'preferences/preferences.html', 'preferences/preferences.html',
request request
) )
@ -175,7 +175,7 @@ def del_services(request, instances):
suivant %s ne peut être supprimé" % services_del) suivant %s ne peut être supprimé" % services_del)
return redirect(reverse('preferences:display-options')) return redirect(reverse('preferences:display-options'))
return form( return form(
{'preferenceform': services, 'action_name' : 'Supprimer'}, {'preferenceform': services, 'action_name': 'Supprimer'},
'preferences/preferences.html', 'preferences/preferences.html',
request request
) )

View file

@ -20,4 +20,3 @@
# You should have received a copy of the GNU General Public License along # You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

View file

@ -1,3 +1,28 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
CONTRIBUTORS = ['Gabriel "Chirac" Détraz', 'Maël "MoaMoaK" Kervella', 'Hugo "Klafyvel" Levy--Falk', 'Augustin "Dahlaro" Lemesle', 'Goulven "Lhark" Kermarec', 'Guillaume "Guimoz" Goessel', 'Yoann "Nanoy" Pietri', 'Matthieu "Lebanni" Michelet', 'Arthur "Grizzly" Grisel-Davy', 'Simon "Rezatoune" Brélivet', 'Sellem Lev-Arcady', 'David "5-1" Sinquin', 'Pierre "Redstorm" Cadart', 'Éloi "Goslig" Alain', 'Laouen "Volgarr" Fernet', 'Joanne Steiner', '"Krokmou"', 'Thibault "Tipunchetrhum" de Boutray', 'Baptiste "B" Fournier', 'Daniel "Dstan" Stan', 'Hugo "Shaka" Hervieux', '"Mikachu"', 'Thomas "Nymous" Gaudin', '"Esum"'] CONTRIBUTORS = [
'Gabriel "Chirac" Détraz',
'Maël "MoaMoaK" Kervella',
'Hugo "Klafyvel" Levy--Falk',
'Augustin "Dahlaro" Lemesle',
'Goulven "Lhark" Kermarec',
'Guillaume "Guimoz" Goessel',
'Yoann "Nanoy" Pietri',
'Matthieu "Lebanni" Michelet',
'Arthur "Grizzly" Grisel-Davy',
'Simon "Rezatoune" Brélivet',
'Sellem Lev-Arcady',
'David "5-1" Sinquin',
'Pierre "Redstorm" Cadart',
'Éloi "Goslig" Alain',
'Laouen "Volgarr" Fernet',
'Joanne Steiner',
'"Krokmou"',
'Thibault "Tipunchetrhum" de Boutray',
'Baptiste "B" Fournier',
'Daniel "Dstan" Stan',
'Hugo "Shaka" Hervieux',
'"Mikachu"',
'Thomas "Nymous" Gaudin',
'"Esum"'
]

View file

@ -43,13 +43,15 @@ class FieldPermissionModelMixin:
if result is not None: if result is not None:
return result return result
else: else:
result = user.has_perm(perm) # Don't supply 'obj', or else infinite recursion. # Don't supply 'obj', or else infinite recursion.
result = user.has_perm(perm)
if result: if result:
return True return True
# If no requirement can be met, then permission is denied. # If no requirement can be met, then permission is denied.
return False return False
class FieldPermissionModel(FieldPermissionModelMixin, models.Model): class FieldPermissionModel(FieldPermissionModelMixin, models.Model):
class Meta: class Meta:
abstract = True abstract = True
@ -76,4 +78,3 @@ class FieldPermissionFormMixin:
class FieldPermissionForm(FieldPermissionFormMixin, forms.ModelForm): class FieldPermissionForm(FieldPermissionFormMixin, forms.ModelForm):
pass pass

View file

@ -20,18 +20,23 @@
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
""" """
Write in a python file the list of all contributors sorted by number of commits. Write in a python file the list of all contributors sorted by number of
This list is extracted from the FedeRez gitlab repository. commits. This list is extracted from the current gitlab repository.
""" """
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
import os import os
class Command(BaseCommand): class Command(BaseCommand):
help = 'Update contributors list' help = 'Update contributors list'
def handle(self, *args, **options): def handle(self, *args, **options):
contributeurs = [item.split('\t')[1] for item in os.popen("git shortlog -s -n").read().split("\n") if '\t' in item] contributeurs = [
item.split('\t')[1]
for item in os.popen("git shortlog -s -n").read().split("\n")
if '\t' in item
]
self.stdout.write(self.style.SUCCESS("Exportation Sucessfull")) self.stdout.write(self.style.SUCCESS("Exportation Sucessfull"))
with open("re2o/contributors.py", "w") as contrib_file: with open("re2o/contributors.py", "w") as contrib_file:
contrib_file.write("#!/usr/bin/env python3\n") contrib_file.write("#!/usr/bin/env python3\n")

View file

@ -37,9 +37,15 @@ class RevMixin(object):
class FormRevMixin(object): class FormRevMixin(object):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if reversion.get_comment() != "" and self.changed_data != []: if reversion.get_comment() != "" and self.changed_data != []:
reversion.set_comment(reversion.get_comment() + ",%s" % ', '.join(field for field in self.changed_data)) reversion.set_comment(
reversion.get_comment() + ",%s"
% ', '.join(field for field in self.changed_data)
)
elif self.changed_data: elif self.changed_data:
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in 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) return super(FormRevMixin, self).save(*args, **kwargs)
@ -47,12 +53,16 @@ class AclMixin(object):
"""This mixin is used in nearly every class/models defined in re2o apps. """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 It is used by acl, in models (decorators can_...) and in templates tags
:get_instance: Applied on a class, take an id argument, return an instance :get_instance: Applied on a class, take an id argument, return an instance
:can_create: Applied on a class, take the requested user, return if the user :can_create: Applied on a class, take the requested user, return if the
can do the creation user can do the creation
:can_edit: Applied on an instance, return if the user can edit the instance :can_edit: Applied on an instance, return if the user can edit the
:can_delete: Applied on an instance, return if the user can delete the instance instance
:can_view: Applied on an instance, return if the user can view the instance :can_delete: Applied on an instance, return if the user can delete the
:can_view_all: Applied on a class, return if the user can view all instances""" instance
:can_view: Applied on an instance, return if the user can view the
instance
:can_view_all: Applied on a class, return if the user can view all
instances"""
@classmethod @classmethod
def get_classname(cls): def get_classname(cls):
@ -76,8 +86,12 @@ class AclMixin(object):
un object un object
:param user_request: instance utilisateur qui fait la requête :param user_request: instance utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec""" :return: soit True, soit False avec la raison de l'échec"""
return user_request.has_perm(cls.get_modulename() + '.add_' + cls.get_classname()), u"Vous n'avez pas le droit\ return (
de créer un " + cls.get_classname() user_request.has_perm(
cls.get_modulename() + '.add_' + cls.get_classname()
),
u"Vous n'avez pas le droit de créer un " + cls.get_classname()
)
def can_edit(self, user_request, *args, **kwargs): def can_edit(self, user_request, *args, **kwargs):
"""Verifie que l'user a les bons droits pour editer """Verifie que l'user a les bons droits pour editer
@ -85,7 +99,12 @@ class AclMixin(object):
:param self: Instance à editer :param self: Instance à editer
:param user_request: Utilisateur qui fait la requête :param user_request: Utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec""" :return: soit True, soit False avec la raison de l'échec"""
return user_request.has_perm(self.get_modulename() + '.change_' + self.get_classname()), u"Vous n'avez pas le droit d'éditer des " + self.get_classname() return (
user_request.has_perm(
self.get_modulename() + '.change_' + self.get_classname()
),
u"Vous n'avez pas le droit d'éditer des " + self.get_classname()
)
def can_delete(self, user_request, *args, **kwargs): def can_delete(self, user_request, *args, **kwargs):
"""Verifie que l'user a les bons droits pour delete """Verifie que l'user a les bons droits pour delete
@ -93,7 +112,12 @@ class AclMixin(object):
:param self: Instance à delete :param self: Instance à delete
:param user_request: Utilisateur qui fait la requête :param user_request: Utilisateur qui fait la requête
:return: soit True, soit False avec la raison de l'échec""" :return: soit True, soit False avec la raison de l'échec"""
return user_request.has_perm(self.get_modulename() + '.delete_' + self.get_classname()), u"Vous n'avez pas le droit d'éditer des " + self.get_classname() return (
user_request.has_perm(
self.get_modulename() + '.delete_' + self.get_classname()
),
u"Vous n'avez pas le droit d'éditer des " + self.get_classname()
)
@classmethod @classmethod
def can_view_all(cls, user_request, *args, **kwargs): def can_view_all(cls, user_request, *args, **kwargs):
@ -101,7 +125,12 @@ class AclMixin(object):
droit particulier view objet correspondant droit particulier view objet correspondant
:param user_request: instance user qui fait l'edition :param user_request: instance user qui fait l'edition
:return: True ou False avec la raison de l'échec le cas échéant""" :return: True ou False avec la raison de l'échec le cas échéant"""
return user_request.has_perm(cls.get_modulename() + '.view_' + cls.get_classname()), u"Vous n'avez pas le droit de voir des " + cls.get_classname() return (
user_request.has_perm(
cls.get_modulename() + '.view_' + cls.get_classname()
),
u"Vous n'avez pas le droit de voir des " + cls.get_classname()
)
def can_view(self, user_request, *args, **kwargs): def can_view(self, user_request, *args, **kwargs):
"""Vérifie qu'on peut bien voir cette instance particulière avec """Vérifie qu'on peut bien voir cette instance particulière avec
@ -109,4 +138,9 @@ class AclMixin(object):
:param self: instance à voir :param self: instance à voir
:param user_request: instance user qui fait l'edition :param user_request: instance user qui fait l'edition
:return: True ou False avec la raison de l'échec le cas échéant""" :return: True ou False avec la raison de l'échec le cas échéant"""
return user_request.has_perm(self.get_modulename() + '.view_' + self.get_classname()), u"Vous n'avez pas le droit de voir des " + self.get_classname() return (
user_request.has_perm(
self.get_modulename() + '.view_' + self.get_classname()
),
u"Vous n'avez pas le droit de voir des " + self.get_classname()
)

View file

@ -19,15 +19,11 @@
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os, sys, pwd import os
import sys
import 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 from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
from django.core.management.base import CommandError from django.core.management.base import CommandError
from users.models import User from users.models import User
@ -37,14 +33,22 @@ from reversion import revisions as reversion
from django.db import transaction from django.db import transaction
from getpass import getpass from getpass import getpass
proj_path = "/var/www/re2o"
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings")
sys.path.append(proj_path)
os.chdir(proj_path)
application = get_wsgi_application()
def get_user(pseudo): def get_user(pseudo):
"""Cherche un utilisateur re2o à partir de son pseudo""" """Cherche un utilisateur re2o à partir de son pseudo"""
user = User.objects.filter(pseudo=pseudo) user = User.objects.filter(pseudo=pseudo)
if len(user)==0: if len(user) == 0:
raise CommandError("Utilisateur invalide") raise CommandError("Utilisateur invalide")
if len(user)>1: if len(user) > 1:
raise CommandError("Plusieurs utilisateurs correspondant à ce pseudo. Ceci NE DEVRAIT PAS arriver") raise CommandError("Plusieurs utilisateurs correspondant à ce "
"pseudo. Ceci NE DEVRAIT PAS arriver")
return user[0] return user[0]
@ -53,7 +57,7 @@ def get_system_user():
return pwd.getpwuid(int(os.getenv("SUDO_UID") or os.getuid())).pw_name return pwd.getpwuid(int(os.getenv("SUDO_UID") or os.getuid())).pw_name
def form_cli(Form,user,action,*args,**kwargs): def form_cli(Form, user, action, *args, **kwargs):
""" """
Remplit un formulaire à partir de la ligne de commande Remplit un formulaire à partir de la ligne de commande
Form : le formulaire (sous forme de classe) à remplir Form : le formulaire (sous forme de classe) à remplir
@ -61,21 +65,24 @@ def form_cli(Form,user,action,*args,**kwargs):
action : l'action réalisée par le formulaire (pour les logs) action : l'action réalisée par le formulaire (pour les logs)
Les arguments suivants sont transmis tels quels au formulaire. Les arguments suivants sont transmis tels quels au formulaire.
""" """
data={} data = {}
dumb_form = Form(user=user,*args,**kwargs) dumb_form = Form(user=user, *args, **kwargs)
for key in dumb_form.fields: for key in dumb_form.fields:
if not dumb_form.fields[key].widget.input_type=='hidden': if not dumb_form.fields[key].widget.input_type == 'hidden':
if dumb_form.fields[key].widget.input_type=='password': if dumb_form.fields[key].widget.input_type == 'password':
data[key]=getpass("%s : " % dumb_form.fields[key].label) data[key] = getpass("%s : " % dumb_form.fields[key].label)
else: else:
data[key]=input("%s : " % dumb_form.fields[key].label) data[key] = input("%s : " % dumb_form.fields[key].label)
form = Form(data,user=user,*args,**kwargs) form = Form(data, user=user, *args, **kwargs)
if not form.is_valid(): if not form.is_valid():
sys.stderr.write("Erreurs : \n") sys.stderr.write("Erreurs : \n")
for err in form.errors: for err in form.errors:
#Oui, oui, on gère du HTML là où d'autres ont eu la lumineuse idée de le mettre # Oui, oui, on gère du HTML là où d'autres ont eu la
sys.stderr.write("\t%s : %s\n" % (err,strip_tags(form.errors[err]))) # lumineuse idée de le mettre
sys.stderr.write(
"\t%s : %s\n" % (err, strip_tags(form.errors[err]))
)
raise CommandError("Formulaire invalide") raise CommandError("Formulaire invalide")
with transaction.atomic(), reversion.create_revision(): with transaction.atomic(), reversion.create_revision():
@ -83,4 +90,5 @@ def form_cli(Form,user,action,*args,**kwargs):
reversion.set_user(user) reversion.set_user(user)
reversion.set_comment(action) reversion.set_comment(action)
sys.stdout.write("%s : effectué. La modification peut prendre quelques minutes pour s'appliquer.\n" % action) sys.stdout.write("%s : effectué. La modification peut prendre "
"quelques minutes pour s'appliquer.\n" % action)

View file

@ -126,7 +126,7 @@ LANGUAGE_CODE = 'en'
# Proritary location search for translations # Proritary location search for translations
# then searches in {app}/locale/ for app in INSTALLED_APPS # then searches in {app}/locale/ for app in INSTALLED_APPS
LOCALE_PATHS = [ LOCALE_PATHS = [
BASE_DIR + '/templates/locale/' # to define translations outside of apps BASE_DIR + '/templates/locale/' # For translations outside of apps
] ]
TIME_ZONE = 'Europe/Paris' TIME_ZONE = 'Europe/Paris'

View file

@ -73,23 +73,22 @@ EMAIL_PORT = MY_EMAIL_PORT
# Reglages pour la bdd ldap # Reglages pour la bdd ldap
LDAP = { LDAP = {
'base_user_dn' : 'cn=Utilisateurs,dc=example,dc=org', 'base_user_dn': 'cn=Utilisateurs,dc=example,dc=org',
'base_userservice_dn' : 'ou=service-users,dc=example,dc=org', 'base_userservice_dn': 'ou=service-users,dc=example,dc=org',
'base_usergroup_dn' : 'ou=posix,ou=groups,dc=example,dc=org', 'base_usergroup_dn': 'ou=posix,ou=groups,dc=example,dc=org',
'base_userservicegroup_dn' : 'ou=services,ou=groups,dc=example,dc=org', 'base_userservicegroup_dn': 'ou=services,ou=groups,dc=example,dc=org',
'user_gid' : 500, 'user_gid': 500,
} }
UID_RANGES = { UID_RANGES = {
'users' : [21001,30000], 'users': [21001, 30000],
'service-users' : [20000,21000], 'service-users': [20000, 21000],
} }
# Chaque groupe a un gid assigné, voici la place libre pour assignation # Chaque groupe a un gid assigné, voici la place libre pour assignation
GID_RANGES = { GID_RANGES = {
'posix' : [501, 600], 'posix': [501, 600],
} }
OPTIONNAL_APPS = () OPTIONNAL_APPS = ()

View file

@ -18,4 +18,3 @@
# You should have received a copy of the GNU General Public License along # You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

View file

@ -85,32 +85,32 @@ register = template.Library()
MODEL_NAME = { MODEL_NAME = {
# cotisations # cotisations
'Facture' : cotisations.models.Facture, 'Facture': cotisations.models.Facture,
'Vente' : cotisations.models.Vente, 'Vente': cotisations.models.Vente,
'Article' : cotisations.models.Article, 'Article': cotisations.models.Article,
'Banque' : cotisations.models.Banque, 'Banque': cotisations.models.Banque,
'Paiement' : cotisations.models.Paiement, 'Paiement': cotisations.models.Paiement,
'Cotisation' : cotisations.models.Cotisation, 'Cotisation': cotisations.models.Cotisation,
# machines # machines
'Machine' : machines.models.Machine, 'Machine': machines.models.Machine,
'MachineType' : machines.models.MachineType, 'MachineType': machines.models.MachineType,
'IpType' : machines.models.IpType, 'IpType': machines.models.IpType,
'Vlan' : machines.models.Vlan, 'Vlan': machines.models.Vlan,
'Nas' : machines.models.Nas, 'Nas': machines.models.Nas,
'SOA' : machines.models.SOA, 'SOA': machines.models.SOA,
'Extension' : machines.models.Extension, 'Extension': machines.models.Extension,
'Mx' : machines.models.Mx, 'Mx': machines.models.Mx,
'Ns' : machines.models.Ns, 'Ns': machines.models.Ns,
'Txt' : machines.models.Txt, 'Txt': machines.models.Txt,
'Srv' : machines.models.Srv, 'Srv': machines.models.Srv,
'Interface' : machines.models.Interface, 'Interface': machines.models.Interface,
'Domain' : machines.models.Domain, 'Domain': machines.models.Domain,
'IpList' : machines.models.IpList, 'IpList': machines.models.IpList,
'Ipv6List' : machines.models.Ipv6List, 'Ipv6List': machines.models.Ipv6List,
'machines.Service' : machines.models.Service, 'machines.Service': machines.models.Service,
'Service_link' : machines.models.Service_link, 'Service_link': machines.models.Service_link,
'OuverturePortList' : machines.models.OuverturePortList, 'OuverturePortList': machines.models.OuverturePortList,
'OuverturePort' : machines.models.OuverturePort, 'OuverturePort': machines.models.OuverturePort,
# preferences # preferences
'OptionalUser': preferences.models.OptionalUser, 'OptionalUser': preferences.models.OptionalUser,
'OptionalMachine': preferences.models.OptionalMachine, 'OptionalMachine': preferences.models.OptionalMachine,
@ -120,25 +120,25 @@ MODEL_NAME = {
'AssoOption': preferences.models.AssoOption, 'AssoOption': preferences.models.AssoOption,
'MailMessageOption': preferences.models.MailMessageOption, 'MailMessageOption': preferences.models.MailMessageOption,
# topologie # topologie
'Stack' : topologie.models.Stack, 'Stack': topologie.models.Stack,
'Switch' : topologie.models.Switch, 'Switch': topologie.models.Switch,
'AccessPoint' : topologie.models.AccessPoint, 'AccessPoint': topologie.models.AccessPoint,
'ModelSwitch' : topologie.models.ModelSwitch, 'ModelSwitch': topologie.models.ModelSwitch,
'ConstructorSwitch' : topologie.models.ConstructorSwitch, 'ConstructorSwitch': topologie.models.ConstructorSwitch,
'Port' : topologie.models.Port, 'Port': topologie.models.Port,
'Room' : topologie.models.Room, 'Room': topologie.models.Room,
'Building' : topologie.models.Building, 'Building': topologie.models.Building,
'SwitchBay' : topologie.models.SwitchBay, 'SwitchBay': topologie.models.SwitchBay,
# users # users
'User' : users.models.User, 'User': users.models.User,
'Adherent' : users.models.Adherent, 'Adherent': users.models.Adherent,
'Club' : users.models.Club, 'Club': users.models.Club,
'ServiceUser' : users.models.ServiceUser, 'ServiceUser': users.models.ServiceUser,
'School' : users.models.School, 'School': users.models.School,
'ListRight' : users.models.ListRight, 'ListRight': users.models.ListRight,
'ListShell' : users.models.ListShell, 'ListShell': users.models.ListShell,
'Ban' : users.models.Ban, 'Ban': users.models.Ban,
'Whitelist' : users.models.Whitelist, 'Whitelist': users.models.Whitelist,
} }
@ -184,17 +184,41 @@ def get_callback(tag_name, obj=None):
if tag_name == 'cannot_view_all': if tag_name == 'cannot_view_all':
return acl_fct(obj.can_view_all, True) return acl_fct(obj.can_view_all, True)
if tag_name == 'can_view_app': if tag_name == 'can_view_app':
return acl_fct(lambda x : (not any(not sys.modules[o].can_view(x) for o in obj), None), False) return acl_fct(
lambda x: (
not any(not sys.modules[o].can_view(x) for o in obj),
None
),
False
)
if tag_name == 'cannot_view_app': if tag_name == 'cannot_view_app':
return acl_fct(lambda x : (not any(not sys.modules[o].can_view(x) for o in obj), None), True) return acl_fct(
lambda x: (
not any(not sys.modules[o].can_view(x) for o in obj),
None
),
True
)
if tag_name == 'can_edit_history': if tag_name == 'can_edit_history':
return acl_fct(lambda user:(user.has_perm('admin.change_logentry'),None),False) return acl_fct(
lambda user: (user.has_perm('admin.change_logentry'), None),
False
)
if tag_name == 'cannot_edit_history': if tag_name == 'cannot_edit_history':
return acl_fct(lambda user:(user.has_perm('admin.change_logentry'),None),True) return acl_fct(
lambda user: (user.has_perm('admin.change_logentry'), None),
True
)
if tag_name == 'can_view_any_app': if tag_name == 'can_view_any_app':
return acl_fct(lambda x : (any(sys.modules[o].can_view(x) for o in obj), None), False) return acl_fct(
lambda x: (any(sys.modules[o].can_view(x) for o in obj), None),
False
)
if tag_name == 'cannot_view_any_app': if tag_name == 'cannot_view_any_app':
return acl_fct(lambda x : (any(sys.modules[o].can_view(x) for o in obj), None), True) return acl_fct(
lambda x: (any(sys.modules[o].can_view(x) for o in obj), None),
True
)
raise template.TemplateSyntaxError( raise template.TemplateSyntaxError(
"%r tag is not a valid can_xxx tag" % tag_name "%r tag is not a valid can_xxx tag" % tag_name
@ -246,11 +270,11 @@ def acl_app_filter(parser, token):
tag_name, *app_name = token.split_contents() tag_name, *app_name = token.split_contents()
except ValueError: except ValueError:
raise template.TemplateSyntaxError( raise template.TemplateSyntaxError(
"%r tag require 1 argument : an application" "%r tag require 1 argument: an application"
% token.contents.split()[0] % token.contents.split()[0]
) )
for name in app_name: for name in app_name:
if not name in sys.modules.keys(): if name not in sys.modules.keys():
raise template.TemplateSyntaxError( raise template.TemplateSyntaxError(
"%r is not a registered application for acl." "%r is not a registered application for acl."
% name % name
@ -270,6 +294,7 @@ def acl_app_filter(parser, token):
return AclNode(callback, oknodes, konodes) return AclNode(callback, oknodes, konodes)
@register.tag('can_change') @register.tag('can_change')
@register.tag('cannot_change') @register.tag('cannot_change')
def acl_change_filter(parser, token): def acl_change_filter(parser, token):
@ -283,7 +308,7 @@ def acl_change_filter(parser, token):
args = tag_content[3:] args = tag_content[3:]
except ValueError: except ValueError:
raise template.TemplateSyntaxError( raise template.TemplateSyntaxError(
"%r tag require at least 2 argument : the model and the field" "%r tag require at least 2 argument: the model and the field"
% token.contents.split()[0] % token.contents.split()[0]
) )
@ -306,6 +331,7 @@ def acl_change_filter(parser, token):
return AclNode(callback, oknodes, konodes, *args) return AclNode(callback, oknodes, konodes, *args)
@register.tag('can_create') @register.tag('can_create')
@register.tag('cannot_create') @register.tag('cannot_create')
@register.tag('can_edit_all') @register.tag('can_edit_all')
@ -324,7 +350,7 @@ def acl_model_filter(parser, token):
args = tag_content[2:] args = tag_content[2:]
except ValueError: except ValueError:
raise template.TemplateSyntaxError( raise template.TemplateSyntaxError(
"%r tag require at least 1 argument : the model" "%r tag require at least 1 argument: the model"
% token.contents.split()[0] % token.contents.split()[0]
) )
@ -364,7 +390,7 @@ def acl_instance_filter(parser, token):
args = tag_content[2:] args = tag_content[2:]
except ValueError: except ValueError:
raise template.TemplateSyntaxError( raise template.TemplateSyntaxError(
"%r tag require at least 1 argument : the instance" "%r tag require at least 1 argument: the instance"
% token.contents.split()[0] % token.contents.split()[0]
) )

View file

@ -36,13 +36,14 @@ from bootstrap3.forms import render_field
register = template.Library() register = template.Library()
@register.simple_tag @register.simple_tag
def massive_bootstrap_form(form, mbf_fields, *args, **kwargs): def massive_bootstrap_form(form, mbf_fields, *args, **kwargs):
""" """
Render a form where some specific fields are rendered using Twitter Render a form where some specific fields are rendered using Twitter
Typeahead and/or splitree's Bootstrap Tokenfield to improve the performance, the Typeahead and/or splitree's Bootstrap Tokenfield to improve the
speed and UX when dealing with very large datasets (select with 50k+ elts performance, the speed and UX when dealing with very large datasets
for instance). (select with 50k+ elts for instance).
When the fields specified should normally be rendered as a select with When the fields specified should normally be rendered as a select with
single selectable option, Twitter Typeahead is used for a better display single selectable option, Twitter Typeahead is used for a better display
and the matching query engine. When dealing with multiple selectable and the matching query engine. When dealing with multiple selectable
@ -189,8 +190,6 @@ def massive_bootstrap_form(form, mbf_fields, *args, **kwargs):
return mbf_form.render() return mbf_form.render()
class MBFForm(): class MBFForm():
""" An object to hold all the information and useful methods needed to """ An object to hold all the information and useful methods needed to
create and render a massive django form into an actual HTML and JS create and render a massive django form into an actual HTML and JS
@ -198,7 +197,6 @@ class MBFForm():
Every field that is not listed is rendered as a normal bootstrap_field. Every field that is not listed is rendered as a normal bootstrap_field.
""" """
def __init__(self, form, mbf_fields, *args, **kwargs): def __init__(self, form, mbf_fields, *args, **kwargs):
# The django form object # The django form object
self.form = form self.form = form
@ -224,14 +222,13 @@ class MBFForm():
# HTML code to insert inside a template # HTML code to insert inside a template
self.html = "" self.html = ""
def render(self): def render(self):
""" HTML code for the fully rendered form with all the necessary form """ HTML code for the fully rendered form with all the necessary form
""" """
for name, field in self.form.fields.items(): for name, field in self.form.fields.items():
if not name in self.exclude: if name not in self.exclude:
if name in self.fields and not name in self.hidden_fields: if name in self.fields and name not in self.hidden_fields:
mbf_field = MBFField( mbf_field = MBFField(
name, name,
field, field,
@ -256,9 +253,6 @@ class MBFForm():
return mark_safe(self.html) return mark_safe(self.html)
class MBFField(): class MBFField():
""" An object to hold all the information and useful methods needed to """ An object to hold all the information and useful methods needed to
create and render a massive django form field into an actual HTML and JS create and render a massive django form field into an actual HTML and JS
@ -270,7 +264,6 @@ class MBFField():
the displayed input. It's used to store the actual data that will be sent the displayed input. It's used to store the actual data that will be sent
to the server """ to the server """
def __init__(self, name_, field_, bound_, choices_, engine_, match_func_, def __init__(self, name_, field_, bound_, choices_, engine_, match_func_,
update_on_, gen_select_, *args_, **kwargs_): update_on_, gen_select_, *args_, **kwargs_):
@ -278,8 +271,8 @@ class MBFField():
if not isinstance(field_.widget, Select): if not isinstance(field_.widget, Select):
raise ValueError( raise ValueError(
('Field named {f_name} is not a Select and' ('Field named {f_name} is not a Select and'
'can\'t be rendered with massive_bootstrap_form.' 'can\'t be rendered with massive_bootstrap_form.')
).format( .format(
f_name=name_ f_name=name_
) )
) )
@ -324,7 +317,6 @@ class MBFField():
self.args = args_ self.args = args_
self.kwargs = kwargs_ self.kwargs = kwargs_
def default_choices(self): def default_choices(self):
""" JS code of the variable choices_<fieldname> """ """ JS code of the variable choices_<fieldname> """
@ -351,7 +343,6 @@ class MBFField():
) )
) )
def default_engine(self): def default_engine(self):
""" Default JS code of the variable engine_<field_name> """ """ Default JS code of the variable engine_<field_name> """
return ( return (
@ -365,7 +356,6 @@ class MBFField():
name=self.name name=self.name
) )
def default_datasets(self): def default_datasets(self):
""" Default JS script of the datasets to use with typeahead """ """ Default JS script of the datasets to use with typeahead """
return ( return (
@ -384,7 +374,6 @@ class MBFField():
match_func=self.match_func match_func=self.match_func
) )
def default_match_func(self): def default_match_func(self):
""" Default JS code of the matching function to use with typeahed """ """ Default JS code of the matching function to use with typeahed """
return ( return (
@ -402,14 +391,12 @@ class MBFField():
name=self.name name=self.name
) )
def render(self): def render(self):
""" HTML code for the fully rendered field """ """ HTML code for the fully rendered field """
self.gen_displayed_div() self.gen_displayed_div()
self.gen_hidden_div() self.gen_hidden_div()
return mark_safe(self.html) return mark_safe(self.html)
def gen_displayed_div(self): def gen_displayed_div(self):
""" Generate HTML code for the div that contains displayed tags """ """ Generate HTML code for the div that contains displayed tags """
if self.gen_select: if self.gen_select:
@ -434,7 +421,6 @@ class MBFField():
if not self.gen_select: if not self.gen_select:
self.html += self.replace_input self.html += self.replace_input
def gen_hidden_div(self): def gen_hidden_div(self):
""" Generate HTML code for the div that contains hidden tags """ """ Generate HTML code for the div that contains hidden tags """
self.gen_full_js() self.gen_full_js()
@ -449,7 +435,6 @@ class MBFField():
attrs={'id': self.div2_id} attrs={'id': self.div2_id}
) )
def hidden_input(self): def hidden_input(self):
""" HTML for the hidden input element """ """ HTML for the hidden input element """
return render_tag( return render_tag(
@ -462,14 +447,12 @@ class MBFField():
} }
) )
def gen_full_js(self): def gen_full_js(self):
""" Generate the full script tag containing the JS code """ """ Generate the full script tag containing the JS code """
self.create_js() self.create_js()
self.fill_js() self.fill_js()
self.get_script() self.get_script()
def create_js(self): def create_js(self):
""" Generate a template for the whole script to use depending on """ Generate a template for the whole script to use depending on
gen_select and multiple """ gen_select and multiple """
@ -549,7 +532,6 @@ class MBFField():
'}} );' '}} );'
) )
def fill_js(self): def fill_js(self):
""" Fill the template with the correct values """ """ Fill the template with the correct values """
self.js_script = self.js_script.format( self.js_script = self.js_script.format(
@ -571,11 +553,12 @@ class MBFField():
typ_init_input=self.typeahead_init_input() typ_init_input=self.typeahead_init_input()
) )
def get_script(self): def get_script(self):
""" Insert the JS code inside a script tag """ """ Insert the JS code inside a script tag """
self.js_script = render_tag('script', content=mark_safe(self.js_script)) self.js_script = render_tag(
'script',
content=mark_safe(self.js_script)
)
def del_select(self): def del_select(self):
""" JS code to delete the select if it has been generated and replace """ JS code to delete the select if it has been generated and replace
@ -589,7 +572,6 @@ class MBFField():
replace_input=self.replace_input replace_input=self.replace_input
) )
def gen_hidden(self): def gen_hidden(self):
""" JS code to add a hidden tag to store the value. """ """ JS code to add a hidden tag to store the value. """
return ( return (
@ -606,7 +588,6 @@ class MBFField():
html_name=self.bound.html_name html_name=self.bound.html_name
) )
def typeahead_init_input(self): def typeahead_init_input(self):
""" JS code to init the fields values """ """ JS code to init the fields values """
init_key = self.bound.value() or '""' init_key = self.bound.value() or '""'
@ -624,7 +605,6 @@ class MBFField():
hidden_id=self.hidden_id hidden_id=self.hidden_id
) )
def typeahead_reset_input(self): def typeahead_reset_input(self):
""" JS code to reset the fields values """ """ JS code to reset the fields values """
return ( return (
@ -635,7 +615,6 @@ class MBFField():
hidden_id=self.hidden_id hidden_id=self.hidden_id
) )
def typeahead_select(self): def typeahead_select(self):
""" JS code to create the function triggered when an item is selected """ JS code to create the function triggered when an item is selected
through typeahead """ through typeahead """
@ -649,7 +628,6 @@ class MBFField():
hidden_id=self.hidden_id hidden_id=self.hidden_id
) )
def typeahead_change(self): def typeahead_change(self):
""" JS code of the function triggered when an item is changed (i.e. """ JS code of the function triggered when an item is changed (i.e.
looses focus and value has changed since the moment it gained focus ) looses focus and value has changed since the moment it gained focus )
@ -666,7 +644,6 @@ class MBFField():
hidden_id=self.hidden_id hidden_id=self.hidden_id
) )
def typeahead_updates(self): def typeahead_updates(self):
""" JS code for binding external fields changes with a reset """ """ JS code for binding external fields changes with a reset """
reset_input = self.typeahead_reset_input() reset_input = self.typeahead_reset_input()
@ -683,7 +660,6 @@ class MBFField():
) for u_id in self.update_on] ) for u_id in self.update_on]
return ''.join(updates) return ''.join(updates)
def tokenfield_init_input(self): def tokenfield_init_input(self):
""" JS code to init the fields values """ """ JS code to init the fields values """
init_key = self.bound.value() or '""' init_key = self.bound.value() or '""'
@ -700,7 +676,6 @@ class MBFField():
) )
) )
def tokenfield_reset_input(self): def tokenfield_reset_input(self):
""" JS code to reset the fields values """ """ JS code to reset the fields values """
return ( return (
@ -709,7 +684,6 @@ class MBFField():
input_id=self.input_id input_id=self.input_id
) )
def tokenfield_create(self): def tokenfield_create(self):
""" JS code triggered when a new token is created in tokenfield. """ """ JS code triggered when a new token is created in tokenfield. """
return ( return (
@ -739,7 +713,6 @@ class MBFField():
div2_id=self.div2_id div2_id=self.div2_id
) )
def tokenfield_edit(self): def tokenfield_edit(self):
""" JS code triggered when a token is edited in tokenfield. """ """ JS code triggered when a token is edited in tokenfield. """
return ( return (
@ -765,7 +738,6 @@ class MBFField():
hidden_id=self.hidden_id hidden_id=self.hidden_id
) )
def tokenfield_remove(self): def tokenfield_remove(self):
""" JS code trigggered when a token is removed from tokenfield. """ """ JS code trigggered when a token is removed from tokenfield. """
return ( return (
@ -791,7 +763,6 @@ class MBFField():
hidden_id=self.hidden_id hidden_id=self.hidden_id
) )
def tokenfield_updates(self): def tokenfield_updates(self):
""" JS code for binding external fields changes with a reset """ """ JS code for binding external fields changes with a reset """
reset_input = self.tokenfield_reset_input() reset_input = self.tokenfield_reset_input()

View file

@ -24,6 +24,7 @@ from preferences.models import OptionalUser, GeneralOption
register = template.Library() register = template.Library()
@register.simple_tag @register.simple_tag
def self_adhesion(): def self_adhesion():
options, _created = OptionalUser.objects.get_or_create() options, _created = OptionalUser.objects.get_or_create()

View file

@ -118,14 +118,18 @@ def all_has_access(search_time=None):
def filter_active_interfaces(interface_set): def filter_active_interfaces(interface_set):
"""Filtre les machines autorisées à sortir sur internet dans une requête""" """Filtre les machines autorisées à sortir sur internet dans une requête"""
return interface_set.filter( return (interface_set
.filter(
machine__in=Machine.objects.filter( machine__in=Machine.objects.filter(
user__in=all_has_access() user__in=all_has_access()
).filter(active=True) ).filter(active=True)
).select_related('domain').select_related('machine')\ ).select_related('domain')
.select_related('type').select_related('ipv4')\ .select_related('machine')
.select_related('domain__extension').select_related('ipv4__ip_type')\ .select_related('type')
.distinct() .select_related('ipv4')
.select_related('domain__extension')
.select_related('ipv4__ip_type')
.distinct())
def filter_complete_interfaces(interface_set): def filter_complete_interfaces(interface_set):
@ -160,6 +164,7 @@ def all_active_assigned_interfaces_count():
""" Version light seulement pour compter""" """ Version light seulement pour compter"""
return all_active_interfaces_count().filter(ipv4__isnull=False) return all_active_interfaces_count().filter(ipv4__isnull=False)
class SortTable: class SortTable:
""" Class gathering uselful stuff to sort the colums of a table, according """ Class gathering uselful stuff to sort the colums of a table, according
to the column and order requested. It's used with a dict of possible to the column and order requested. It's used with a dict of possible
@ -171,7 +176,8 @@ class SortTable:
# the url value and the values are a list of model field name to use to # the url value and the values are a list of model field name to use to
# order the request. They are applied in the order they are given. # order the request. They are applied in the order they are given.
# A 'default' might be provided to specify what to do if the requested col # A 'default' might be provided to specify what to do if the requested col
# doesn't match any keys. # doesn't match any keys.
USERS_INDEX = { USERS_INDEX = {
'user_name': ['name'], 'user_name': ['name'],
'user_surname': ['surname'], 'user_surname': ['surname'],
@ -255,7 +261,7 @@ class SortTable:
} }
TOPOLOGIE_INDEX_MODEL_SWITCH = { TOPOLOGIE_INDEX_MODEL_SWITCH = {
'model-switch_name': ['reference'], 'model-switch_name': ['reference'],
'model-switch_contructor' : ['constructor__name'], 'model-switch_contructor': ['constructor__name'],
'default': ['reference'], 'default': ['reference'],
} }
TOPOLOGIE_INDEX_SWITCH_BAY = { TOPOLOGIE_INDEX_SWITCH_BAY = {
@ -290,6 +296,7 @@ class SortTable:
else: else:
return request return request
def re2o_paginator(request, query_set, pagination_number): def re2o_paginator(request, query_set, pagination_number):
"""Paginator script for list display in re2o. """Paginator script for list display in re2o.
:request: :request:
@ -307,6 +314,7 @@ def re2o_paginator(request, query_set, pagination_number):
results = paginator.page(paginator.num_pages) results = paginator.page(paginator.num_pages)
return results return results
def remove_user_room(room): def remove_user_room(room):
""" Déménage de force l'ancien locataire de la chambre """ """ Déménage de force l'ancien locataire de la chambre """
try: try:

View file

@ -44,12 +44,17 @@ from itertools import chain
from preferences.models import Service from preferences.models import Service
from preferences.models import OptionalUser, GeneralOption, AssoOption from preferences.models import OptionalUser, GeneralOption, AssoOption
import users, preferences, cotisations, topologie, machines import users
import preferences
import cotisations
import topologie
import machines
from .utils import re2o_paginator from .utils import re2o_paginator
from .settings import BASE_DIR, INSTALLED_APPS, MIDDLEWARE_CLASSES from .settings import BASE_DIR, INSTALLED_APPS, MIDDLEWARE_CLASSES
from .contributors import CONTRIBUTORS from .contributors import CONTRIBUTORS
def form(ctx, template, request): def form(ctx, template, request):
"""Form générique, raccourci importé par les fonctions views du site""" """Form générique, raccourci importé par les fonctions views du site"""
context = ctx context = ctx
@ -64,56 +69,58 @@ def index(request):
services[indice % 3].append(serv) services[indice % 3].append(serv)
return form({'services_urls': services}, 're2o/index.html', request) return form({'services_urls': services}, 're2o/index.html', request)
#: Binding the corresponding char sequence of history url to re2o models. #: Binding the corresponding char sequence of history url to re2o models.
HISTORY_BIND = { HISTORY_BIND = {
'users' : { 'users': {
'user' : users.models.User, 'user': users.models.User,
'ban' : users.models.Ban, 'ban': users.models.Ban,
'whitelist' : users.models.Whitelist, 'whitelist': users.models.Whitelist,
'school' : users.models.School, 'school': users.models.School,
'listright' : users.models.ListRight, 'listright': users.models.ListRight,
'serviceuser' : users.models.ServiceUser, 'serviceuser': users.models.ServiceUser,
'listshell' : users.models.ListShell, 'listshell': users.models.ListShell,
}, },
'preferences' : { 'preferences': {
'service' : preferences.models.Service, 'service': preferences.models.Service,
}, },
'cotisations' : { 'cotisations': {
'facture' : cotisations.models.Facture, 'facture': cotisations.models.Facture,
'article' : cotisations.models.Article, 'article': cotisations.models.Article,
'paiement' : cotisations.models.Paiement, 'paiement': cotisations.models.Paiement,
'banque' : cotisations.models.Banque, 'banque': cotisations.models.Banque,
}, },
'topologie' : { 'topologie': {
'switch' : topologie.models.Switch, 'switch': topologie.models.Switch,
'port' : topologie.models.Port, 'port': topologie.models.Port,
'room' : topologie.models.Room, 'room': topologie.models.Room,
'stack' : topologie.models.Stack, 'stack': topologie.models.Stack,
'modelswitch' : topologie.models.ModelSwitch, 'modelswitch': topologie.models.ModelSwitch,
'constructorswitch' : topologie.models.ConstructorSwitch, 'constructorswitch': topologie.models.ConstructorSwitch,
'accesspoint' : topologie.models.AccessPoint, 'accesspoint': topologie.models.AccessPoint,
'switchbay' : topologie.models.SwitchBay, 'switchbay': topologie.models.SwitchBay,
'building' : topologie.models.Building, 'building': topologie.models.Building,
}, },
'machines' : { 'machines': {
'machine' : machines.models.Machine, 'machine': machines.models.Machine,
'interface' : machines.models.Interface, 'interface': machines.models.Interface,
'domain' : machines.models.Domain, 'domain': machines.models.Domain,
'machinetype' : machines.models.MachineType, 'machinetype': machines.models.MachineType,
'iptype' : machines.models.IpType, 'iptype': machines.models.IpType,
'extension' : machines.models.Extension, 'extension': machines.models.Extension,
'soa' : machines.models.SOA, 'soa': machines.models.SOA,
'mx' : machines.models.Mx, 'mx': machines.models.Mx,
'txt' : machines.models.Txt, 'txt': machines.models.Txt,
'srv' : machines.models.Srv, 'srv': machines.models.Srv,
'ns' : machines.models.Ns, 'ns': machines.models.Ns,
'service' : machines.models.Service, 'service': machines.models.Service,
'vlan' : machines.models.Vlan, 'vlan': machines.models.Vlan,
'nas' : machines.models.Nas, 'nas': machines.models.Nas,
'ipv6list' : machines.models.Ipv6List, 'ipv6list': machines.models.Ipv6List,
}, },
} }
@login_required @login_required
def history(request, application, object_name, object_id): def history(request, application, object_name, object_id):
"""Render history for a model. """Render history for a model.
@ -144,21 +151,23 @@ def history(request, application, object_name, object_id):
instance = model.get_instance(**kwargs) instance = model.get_instance(**kwargs)
except model.DoesNotExist: except model.DoesNotExist:
messages.error(request, u"Entrée inexistante") messages.error(request, u"Entrée inexistante")
return redirect(reverse('users:profil', return redirect(reverse(
kwargs={'userid':str(request.user.id)} 'users:profil',
kwargs={'userid': str(request.user.id)}
)) ))
can, msg = instance.can_view(request.user) can, msg = instance.can_view(request.user)
if not can: if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu") messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse( return redirect(reverse(
'users:profil', 'users:profil',
kwargs={'userid':str(request.user.id)} kwargs={'userid': str(request.user.id)}
)) ))
pagination_number = GeneralOption.get_cached_value('pagination_number') pagination_number = GeneralOption.get_cached_value('pagination_number')
reversions = Version.objects.get_for_object(instance) reversions = Version.objects.get_for_object(instance)
if hasattr(instance, 'linked_objects'): if hasattr(instance, 'linked_objects'):
for related_object in chain(instance.linked_objects()): for related_object in chain(instance.linked_objects()):
reversions = reversions | Version.objects.get_for_object(related_object) reversions = (reversions |
Version.objects.get_for_object(related_object))
reversions = re2o_paginator(request, reversions, pagination_number) reversions = re2o_paginator(request, reversions, pagination_number)
return render( return render(
request, request,
@ -191,8 +200,8 @@ def about_page(request):
request, request,
"re2o/about.html", "re2o/about.html",
{ {
'description': option.description , 'description': option.description,
'AssoName' : option.name , 'AssoName': option.name,
'git_info_contributors': git_info_contributors, 'git_info_contributors': git_info_contributors,
'git_info_remote': git_info_remote, 'git_info_remote': git_info_remote,
'git_info_branch': git_info_branch, 'git_info_branch': git_info_branch,
@ -201,4 +210,3 @@ def about_page(request):
'dependencies': dependencies 'dependencies': dependencies
} }
) )