mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-09-12 01:03:09 +00:00
Pylint compliance on re2o
This commit is contained in:
parent
332e8a3413
commit
2ca271bf82
15 changed files with 295 additions and 181 deletions
|
@ -20,3 +20,15 @@
|
|||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
"""re2o
|
||||
The main app of Re2o. In charge of all the basics elements which are not
|
||||
specific to anyother apps. It includes :
|
||||
* Templates used in multiple places
|
||||
* Templatetags used in multiple places
|
||||
* ACL base
|
||||
* Mixins base
|
||||
* Settings for the Django project
|
||||
* The login part
|
||||
* Some utility scripts
|
||||
* ...
|
||||
"""
|
||||
|
|
139
re2o/acl.py
139
re2o/acl.py
|
@ -33,14 +33,6 @@ from django.contrib import messages
|
|||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
|
||||
import cotisations
|
||||
import logs
|
||||
import machines
|
||||
import preferences
|
||||
import search
|
||||
import topologie
|
||||
import users
|
||||
|
||||
|
||||
def can_create(model):
|
||||
"""Decorator to check if an user can create a model.
|
||||
|
@ -49,7 +41,11 @@ def can_create(model):
|
|||
of models.
|
||||
"""
|
||||
def decorator(view):
|
||||
"""The decorator to use on a specific view
|
||||
"""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
can, msg = model.can_create(request.user, *args, **kwargs)
|
||||
if not can:
|
||||
messages.error(
|
||||
|
@ -68,31 +64,37 @@ def can_edit(model, *field_list):
|
|||
kind of models.
|
||||
"""
|
||||
def decorator(view):
|
||||
"""The decorator to use on a specific view
|
||||
"""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
try:
|
||||
instance = model.get_instance(*args, **kwargs)
|
||||
except model.DoesNotExist:
|
||||
messages.error(request, u"Entrée inexistante")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
can, msg = instance.can_edit(request.user)
|
||||
if not can:
|
||||
messages.error(
|
||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
for field in field_list:
|
||||
can_change = getattr(instance, 'can_change_' + field)
|
||||
can, msg = can_change(request.user, *args, **kwargs)
|
||||
can_change_fct = getattr(instance, 'can_change_' + field)
|
||||
can, msg = can_change_fct(request.user, *args, **kwargs)
|
||||
if not can:
|
||||
messages.error(
|
||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(
|
||||
request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return view(request, instance, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@ -103,17 +105,21 @@ def can_change(model, *field_list):
|
|||
Difference with can_edit : take a class and not an instance
|
||||
"""
|
||||
def decorator(view):
|
||||
"""The decorator to use on a specific view
|
||||
"""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
for field in field_list:
|
||||
can_change = getattr(model, 'can_change_' + field)
|
||||
can, msg = can_change(request.user, *args, **kwargs)
|
||||
can_change_fct = getattr(model, 'can_change_' + field)
|
||||
can, msg = can_change_fct(request.user, *args, **kwargs)
|
||||
if not can:
|
||||
messages.error(
|
||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(
|
||||
request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return view(request, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@ -127,21 +133,27 @@ def can_delete(model):
|
|||
kind of models.
|
||||
"""
|
||||
def decorator(view):
|
||||
"""The decorator to use on a specific view
|
||||
"""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
try:
|
||||
instance = model.get_instance(*args, **kwargs)
|
||||
except model.DoesNotExist:
|
||||
messages.error(request, u"Entrée inexistante")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
can, msg = instance.can_delete(request.user)
|
||||
if not can:
|
||||
messages.error(
|
||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return view(request, instance, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@ -151,7 +163,11 @@ def can_delete_set(model):
|
|||
"""Decorator which returns a list of detable models by request user.
|
||||
If none of them, return an error"""
|
||||
def decorator(view):
|
||||
"""The decorator to use on a specific view
|
||||
"""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
all_objects = model.objects.all()
|
||||
instances_id = []
|
||||
for instance in all_objects:
|
||||
|
@ -160,10 +176,12 @@ def can_delete_set(model):
|
|||
instances_id.append(instance.id)
|
||||
instances = model.objects.filter(id__in=instances_id)
|
||||
if not instances:
|
||||
messages.error(request, "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
messages.error(
|
||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return view(request, instances, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@ -177,21 +195,27 @@ def can_view(model):
|
|||
kind of models.
|
||||
"""
|
||||
def decorator(view):
|
||||
"""The decorator to use on a specific view
|
||||
"""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
try:
|
||||
instance = model.get_instance(*args, **kwargs)
|
||||
except model.DoesNotExist:
|
||||
messages.error(request, u"Entrée inexistante")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
can, msg = instance.can_view(request.user)
|
||||
if not can:
|
||||
messages.error(
|
||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return view(request, instance, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@ -201,14 +225,19 @@ def can_view_all(model):
|
|||
"""Decorator to check if an user can view a class of model.
|
||||
"""
|
||||
def decorator(view):
|
||||
"""The decorator to use on a specific view
|
||||
"""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
can, msg = model.can_view_all(request.user)
|
||||
if not can:
|
||||
messages.error(
|
||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return view(request, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
@ -220,15 +249,20 @@ def can_view_app(app_name):
|
|||
assert app_name in sys.modules.keys()
|
||||
|
||||
def decorator(view):
|
||||
"""The decorator to use on a specific view
|
||||
"""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
app = sys.modules[app_name]
|
||||
can, msg = app.can_view(request.user)
|
||||
if can:
|
||||
return view(request, *args, **kwargs)
|
||||
messages.error(request, msg)
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
@ -236,13 +270,16 @@ def can_view_app(app_name):
|
|||
def can_edit_history(view):
|
||||
"""Decorator to check if an user can edit history."""
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""The wrapper used for a specific request
|
||||
"""
|
||||
if request.user.has_perm('admin.change_logentry'):
|
||||
return view(request, *args, **kwargs)
|
||||
messages.error(
|
||||
request,
|
||||
"Vous ne pouvez pas éditer l'historique."
|
||||
)
|
||||
return redirect(reverse('users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid': str(request.user.id)}
|
||||
))
|
||||
return wrapper
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#!/usr/bin/env python3
|
||||
"""re2o.contributors
|
||||
A list of the proud contributors to Re2o
|
||||
"""
|
||||
|
||||
CONTRIBUTORS = [
|
||||
'Gabriel "Chirac" Détraz',
|
||||
|
|
|
@ -1,15 +1,45 @@
|
|||
from django.db import models
|
||||
from django import forms
|
||||
from functools import partial
|
||||
|
||||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||
# se veut agnostique au réseau considéré, de manière à être installable en
|
||||
# quelques clics.
|
||||
#
|
||||
# Copyright © 2017 Gabriel Détraz
|
||||
# Copyright © 2017 Goulven Kermarec
|
||||
# Copyright © 2017 Augustin Lemesle
|
||||
# Copyright © 2018 Maël Kervella
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
"""re2o.field_permissions
|
||||
A model mixin and a field mixin used to remove some unauthorized fields
|
||||
from the form automatically generated from the model. The model must
|
||||
subclass `FieldPermissionModelMixin` and the form must subclass
|
||||
`FieldPermissionFieldMixin` so when a Django form is generated from the
|
||||
fields of the models, some fields will be removed if the user don't have
|
||||
the rights to change them (can_change_{name})
|
||||
"""
|
||||
|
||||
class FieldPermissionModelMixin:
|
||||
""" The model mixin. Defines the `has_field_perm` function """
|
||||
field_permissions = {} # {'field_name': callable}
|
||||
FIELD_PERM_CODENAME = 'can_change_{model}_{name}'
|
||||
FIELD_PERMISSION_GETTER = 'can_change_{name}'
|
||||
FIELD_PERMISSION_MISSING_DEFAULT = True
|
||||
|
||||
def has_field_perm(self, user, field):
|
||||
""" Checks if a `user` has the right to edit the `field`
|
||||
of this model """
|
||||
if field in self.field_permissions:
|
||||
checks = self.field_permissions[field]
|
||||
if not isinstance(checks, (list, tuple)):
|
||||
|
@ -39,7 +69,7 @@ class FieldPermissionModelMixin:
|
|||
# Try to find a user setting that qualifies them for permission.
|
||||
for perm in checks:
|
||||
if callable(perm):
|
||||
result, reason = perm(user_request=user)
|
||||
result, _reason = perm(user_request=user)
|
||||
if result is not None:
|
||||
return result
|
||||
else:
|
||||
|
@ -52,11 +82,6 @@ class FieldPermissionModelMixin:
|
|||
return False
|
||||
|
||||
|
||||
class FieldPermissionModel(FieldPermissionModelMixin, models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class FieldPermissionFormMixin:
|
||||
"""
|
||||
Construit le formulaire et retire les champs interdits
|
||||
|
@ -73,8 +98,5 @@ class FieldPermissionFormMixin:
|
|||
self.remove_unauthorized_field(name)
|
||||
|
||||
def remove_unauthorized_field(self, name):
|
||||
""" Remove one field from the fields of the form """
|
||||
del self.fields[name]
|
||||
|
||||
|
||||
class FieldPermissionForm(FieldPermissionFormMixin, forms.ModelForm):
|
||||
pass
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Module d'authentification
|
||||
# David Sinquin, Gabriel Détraz, Goulven Kermarec
|
||||
|
||||
"""re2o.login
|
||||
Module in charge of handling the login process and verifications
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import binascii
|
||||
|
@ -42,6 +44,7 @@ DIGEST_LEN = 20
|
|||
|
||||
|
||||
def makeSecret(password):
|
||||
""" Build a hashed and salted version of the password """
|
||||
salt = os.urandom(4)
|
||||
h = hashlib.sha1(password.encode())
|
||||
h.update(salt)
|
||||
|
@ -49,11 +52,13 @@ def makeSecret(password):
|
|||
|
||||
|
||||
def hashNT(password):
|
||||
hash = hashlib.new('md4', password.encode('utf-16le')).digest()
|
||||
return binascii.hexlify(hash).upper()
|
||||
""" Build a md4 hash of the password to use as the NT-password """
|
||||
hash_str = hashlib.new('md4', password.encode('utf-16le')).digest()
|
||||
return binascii.hexlify(hash_str).upper()
|
||||
|
||||
|
||||
def checkPassword(challenge_password, password):
|
||||
""" Check if a given password match the hash of a stored password """
|
||||
challenge_bytes = decodestring(challenge_password[ALGO_LEN:].encode())
|
||||
digest = challenge_bytes[:DIGEST_LEN]
|
||||
salt = challenge_bytes[DIGEST_LEN:]
|
||||
|
@ -74,7 +79,7 @@ class SSHAPasswordHasher(hashers.BasePasswordHasher):
|
|||
|
||||
algorithm = ALGO_NAME
|
||||
|
||||
def encode(self, password, salt, iterations=None):
|
||||
def encode(self, password, salt):
|
||||
"""
|
||||
Hash and salt the given password using SSHA algorithm
|
||||
|
||||
|
@ -92,16 +97,16 @@ class SSHAPasswordHasher(hashers.BasePasswordHasher):
|
|||
|
||||
def safe_summary(self, encoded):
|
||||
"""
|
||||
Provides a safe summary ofthe password
|
||||
Provides a safe summary of the password
|
||||
"""
|
||||
assert encoded.startswith(self.algorithm)
|
||||
hash = encoded[ALGO_LEN:]
|
||||
hash = binascii.hexlify(decodestring(hash.encode())).decode()
|
||||
hash_str = encoded[ALGO_LEN:]
|
||||
hash_str = binascii.hexlify(decodestring(hash_str.encode())).decode()
|
||||
return OrderedDict([
|
||||
('algorithm', self.algorithm),
|
||||
('iterations', 0),
|
||||
('salt', hashers.mask_hash(hash[2*DIGEST_LEN:], show=2)),
|
||||
('hash', hashers.mask_hash(hash[:2*DIGEST_LEN])),
|
||||
('salt', hashers.mask_hash(hash_str[2*DIGEST_LEN:], show=2)),
|
||||
('hash', hashers.mask_hash(hash_str[:2*DIGEST_LEN])),
|
||||
])
|
||||
|
||||
def harden_runtime(self, password, encoded):
|
||||
|
|
|
@ -24,11 +24,12 @@ Write in a python file the list of all contributors sorted by number of
|
|||
commits. This list is extracted from the current gitlab repository.
|
||||
"""
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
import os
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
""" The command object for `gen_contrib` """
|
||||
help = 'Update contributors list'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
@ -39,6 +40,8 @@ class Command(BaseCommand):
|
|||
]
|
||||
self.stdout.write(self.style.SUCCESS("Exportation Sucessfull"))
|
||||
with open("re2o/contributors.py", "w") as contrib_file:
|
||||
contrib_file.write("#!/usr/bin/env python3\n")
|
||||
contrib_file.write("\"\"\"re2o.contributors\n")
|
||||
contrib_file.write("A list of the proud contributors to Re2o\n")
|
||||
contrib_file.write("\"\"\"\n")
|
||||
contrib_file.write("\n")
|
||||
contrib_file.write("CONTRIBUTORS = " + str(contributeurs))
|
||||
|
|
|
@ -19,23 +19,34 @@
|
|||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
"""re2o.mixins
|
||||
A set of mixins used all over the project to avoid duplicating code
|
||||
"""
|
||||
|
||||
from reversion import revisions as reversion
|
||||
|
||||
|
||||
class RevMixin(object):
|
||||
""" A mixin to subclass the save and delete function of a model
|
||||
to enforce the versioning of the object before those actions
|
||||
really happen """
|
||||
def save(self, *args, **kwargs):
|
||||
""" Creates a version of this object and save it to database """
|
||||
if self.pk is None:
|
||||
reversion.set_comment("Création")
|
||||
return super(RevMixin, self).save(*args, **kwargs)
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
""" Creates a version of this object and delete it from database """
|
||||
reversion.set_comment("Suppresion")
|
||||
return super(RevMixin, self).delete(*args, **kwargs)
|
||||
|
||||
|
||||
class FormRevMixin(object):
|
||||
""" A mixin to subclass the save function of a form
|
||||
to enforce the versionning of the object before it is really edited """
|
||||
def save(self, *args, **kwargs):
|
||||
""" Create a version of this object and save it to database """
|
||||
if reversion.get_comment() != "" and self.changed_data != []:
|
||||
reversion.set_comment(
|
||||
reversion.get_comment() + ",%s"
|
||||
|
@ -66,14 +77,16 @@ class AclMixin(object):
|
|||
|
||||
@classmethod
|
||||
def get_classname(cls):
|
||||
""" Returns the name of the class where this mixin is used """
|
||||
return str(cls.__name__).lower()
|
||||
|
||||
@classmethod
|
||||
def get_modulename(cls):
|
||||
""" Returns the name of the module where this mixin is used """
|
||||
return str(cls.__module__).split('.')[0].lower()
|
||||
|
||||
@classmethod
|
||||
def get_instance(cls, *args, **kwargs):
|
||||
def get_instance(cls, *_args, **kwargs):
|
||||
"""Récupère une instance
|
||||
:param objectid: Instance id à trouver
|
||||
:return: Une instance de la classe évidemment"""
|
||||
|
@ -81,7 +94,7 @@ class AclMixin(object):
|
|||
return cls.objects.get(pk=object_id)
|
||||
|
||||
@classmethod
|
||||
def can_create(cls, user_request, *args, **kwargs):
|
||||
def can_create(cls, user_request, *_args, **_kwargs):
|
||||
"""Verifie que l'user a les bons droits pour créer
|
||||
un object
|
||||
:param user_request: instance utilisateur qui fait la requête
|
||||
|
@ -93,7 +106,7 @@ class AclMixin(object):
|
|||
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
|
||||
cette instance
|
||||
:param self: Instance à editer
|
||||
|
@ -106,7 +119,7 @@ class AclMixin(object):
|
|||
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
|
||||
cette instance
|
||||
:param self: Instance à delete
|
||||
|
@ -120,7 +133,7 @@ class AclMixin(object):
|
|||
)
|
||||
|
||||
@classmethod
|
||||
def can_view_all(cls, user_request, *args, **kwargs):
|
||||
def can_view_all(cls, user_request, *_args, **_kwargs):
|
||||
"""Vérifie qu'on peut bien afficher l'ensemble des objets,
|
||||
droit particulier view objet correspondant
|
||||
:param user_request: instance user qui fait l'edition
|
||||
|
@ -132,7 +145,7 @@ class AclMixin(object):
|
|||
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
|
||||
droit view objet
|
||||
:param self: instance à voir
|
||||
|
|
|
@ -18,22 +18,27 @@
|
|||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
"""re2o.script_utils
|
||||
A set of utility scripts that can be used as standalone to interact easily
|
||||
with Re2o throught the CLI
|
||||
"""
|
||||
|
||||
import os
|
||||
from os.path import dirname
|
||||
import sys
|
||||
import pwd
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
from getpass import getpass
|
||||
from reversion import revisions as reversion
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
from django.core.management.base import CommandError
|
||||
from django.db import transaction
|
||||
from django.utils.html import strip_tags
|
||||
|
||||
from users.models import User
|
||||
|
||||
from django.utils.html import strip_tags
|
||||
from reversion import revisions as reversion
|
||||
from django.db import transaction
|
||||
from getpass import getpass
|
||||
|
||||
proj_path = "/var/www/re2o"
|
||||
proj_path = dirname(dirname(__file__))
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings")
|
||||
sys.path.append(proj_path)
|
||||
os.chdir(proj_path)
|
||||
|
|
100
re2o/settings.py
100
re2o/settings.py
|
@ -35,38 +35,37 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
|
|||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
from .settings_local import *
|
||||
|
||||
# The root directory for the project
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
|
||||
|
||||
# Auth definition
|
||||
|
||||
PASSWORD_HASHERS = (
|
||||
're2o.login.SSHAPasswordHasher',
|
||||
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||
)
|
||||
|
||||
AUTH_USER_MODEL = 'users.User'
|
||||
LOGIN_URL = '/login/'
|
||||
LOGIN_REDIRECT_URL = '/'
|
||||
|
||||
AUTH_USER_MODEL = 'users.User' # The class to use for authentication
|
||||
LOGIN_URL = '/login/' # The URL for login page
|
||||
LOGIN_REDIRECT_URL = '/' # The URL for redirecting after login
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = (
|
||||
DJANGO_CONTRIB_APPS = (
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
)
|
||||
EXTERNAL_CONTRIB_APPS = (
|
||||
'bootstrap3',
|
||||
'rest_framework',
|
||||
'reversion',
|
||||
)
|
||||
LOCAL_APPS = (
|
||||
'users',
|
||||
'machines',
|
||||
'cotisations',
|
||||
|
@ -75,11 +74,14 @@ INSTALLED_APPS = (
|
|||
're2o',
|
||||
'preferences',
|
||||
'logs',
|
||||
'rest_framework',
|
||||
'reversion',
|
||||
'api'
|
||||
) + OPTIONNAL_APPS
|
||||
|
||||
'api',
|
||||
)
|
||||
INSTALLED_APPS = (
|
||||
DJANGO_CONTRIB_APPS +
|
||||
EXTERNAL_CONTRIB_APPS +
|
||||
LOCAL_APPS +
|
||||
OPTIONNAL_APPS
|
||||
)
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
|
@ -93,14 +95,17 @@ MIDDLEWARE_CLASSES = (
|
|||
'reversion.middleware.RevisionMiddleware',
|
||||
)
|
||||
|
||||
# The root url module to define the project URLs
|
||||
ROOT_URLCONF = 're2o.urls'
|
||||
|
||||
# The templates configuration (see Django documentation)
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [
|
||||
os.path.join(BASE_DIR, 'templates').replace('\\', '/'),
|
||||
],
|
||||
# Use only absolute paths with '/' delimiters even on Windows
|
||||
os.path.join(BASE_DIR, 'templates').replace('\\', '/'),
|
||||
],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
|
@ -115,57 +120,50 @@ TEMPLATES = [
|
|||
},
|
||||
]
|
||||
|
||||
# The WSGI module to use in a server environment
|
||||
WSGI_APPLICATION = 're2o.wsgi.application'
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'en'
|
||||
|
||||
USE_I18N = True
|
||||
USE_L10N = True
|
||||
# Proritary location search for translations
|
||||
# then searches in {app}/locale/ for app in INSTALLED_APPS
|
||||
# Use only absolute paths with '/' delimiters even on Windows
|
||||
LOCALE_PATHS = [
|
||||
BASE_DIR + '/templates/locale/' # For translations outside of apps
|
||||
# For translations outside of apps
|
||||
os.path.join(BASE_DIR, 'templates', 'locale').replace('\\', '/')
|
||||
]
|
||||
|
||||
TIME_ZONE = 'Europe/Paris'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
# Should use time zone ?
|
||||
USE_TZ = True
|
||||
|
||||
# Router config for database
|
||||
DATABASE_ROUTERS = ['ldapdb.router.Router']
|
||||
|
||||
|
||||
# django-bootstrap3 config dictionnary
|
||||
# django-bootstrap3 config
|
||||
BOOTSTRAP3 = {
|
||||
'jquery_url': '/static/js/jquery-2.2.4.min.js',
|
||||
'base_url': '/static/bootstrap/',
|
||||
'include_jquery': True,
|
||||
}
|
||||
|
||||
'jquery_url': '/static/js/jquery-2.2.4.min.js',
|
||||
'base_url': '/static/bootstrap/',
|
||||
'include_jquery': True,
|
||||
}
|
||||
BOOTSTRAP_BASE_URL = '/static/bootstrap/'
|
||||
|
||||
# Directories where collectstatic should look for static files
|
||||
# Use only absolute paths with '/' delimiters even on Windows
|
||||
STATICFILES_DIRS = (
|
||||
# Put strings here, like "/home/html/static" or "C:/www/django/static".
|
||||
# Always use forward slashes, even on Windows.
|
||||
# Don't forget to use absolute paths, not relative paths.
|
||||
os.path.join(
|
||||
BASE_DIR,
|
||||
'static',
|
||||
),
|
||||
os.path.join(BASE_DIR, 'static').replace('\\', '/'),
|
||||
)
|
||||
|
||||
MEDIA_ROOT = '/var/www/re2o/media'
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
# Directory where the static files serverd by the server are stored
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
|
||||
# The URL to access the static files
|
||||
STATIC_URL = '/static/'
|
||||
# Directory where the media files serverd by the server are stored
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')
|
||||
|
||||
# Models to use for graphs
|
||||
GRAPH_MODELS = {
|
||||
'all_applications': True,
|
||||
'group_models': True,
|
||||
'all_applications': True,
|
||||
'group_models': True,
|
||||
}
|
||||
|
|
|
@ -19,45 +19,56 @@
|
|||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
"""re2o.settings_locale.example
|
||||
The example settings_locale.py file with all the available
|
||||
options for a locale configuration of re2o
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# A secret key used by the server.
|
||||
SECRET_KEY = 'SUPER_SECRET_KEY'
|
||||
|
||||
# The password to access the project database
|
||||
DB_PASSWORD = 'SUPER_SECRET_DB'
|
||||
|
||||
# AES key for secret key encryption length must be a multiple of 16
|
||||
AES_KEY = 'THE_AES_KEY'
|
||||
|
||||
# AES key for secret key encryption.
|
||||
# The length must be a multiple of 16
|
||||
AES_KEY = 'A_SECRET_AES_KEY'
|
||||
|
||||
# Should the server run in debug mode ?
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = False
|
||||
|
||||
# A list of admins of the services. Receive mails when an error occurs
|
||||
ADMINS = [('Example', 'rezo-admin@example.org')]
|
||||
|
||||
SERVER_EMAIL = 'no-reply@example.org'
|
||||
|
||||
# Obligatoire, liste des host autorisés
|
||||
# The list of hostname the server will respond to.
|
||||
ALLOWED_HOSTS = ['URL_SERVER']
|
||||
|
||||
# The time zone the server is runned in
|
||||
TIME_ZONE = 'Europe/Paris'
|
||||
|
||||
# The storage systems parameters to use
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'default': { # The DB
|
||||
'ENGINE': 'db_engine',
|
||||
'NAME': 'db_name_value',
|
||||
'USER': 'db_user_value',
|
||||
'PASSWORD': DB_PASSWORD,
|
||||
'HOST': 'db_host_value',
|
||||
},
|
||||
'ldap': {
|
||||
'ldap': { # The LDAP
|
||||
'ENGINE': 'ldapdb.backends.ldap',
|
||||
'NAME': 'ldap://ldap_host_ip/',
|
||||
'USER': 'ldap_dn',
|
||||
# 'TLS': True,
|
||||
'TLS': True,
|
||||
'PASSWORD': 'SUPER_SECRET_LDAP',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Security settings, à activer une fois https en place
|
||||
# Security settings for secure https
|
||||
# Activate once https is correctly configured
|
||||
SECURE_CONTENT_TYPE_NOSNIFF = False
|
||||
SECURE_BROWSER_XSS_FILTER = False
|
||||
SESSION_COOKIE_SECURE = False
|
||||
|
@ -66,12 +77,15 @@ CSRF_COOKIE_HTTPONLY = False
|
|||
X_FRAME_OPTIONS = 'DENY'
|
||||
SESSION_COOKIE_AGE = 60 * 60 * 3
|
||||
|
||||
# The path where your organization logo is stored
|
||||
LOGO_PATH = "static_files/logo.png"
|
||||
|
||||
EMAIL_HOST = 'MY_EMAIL_HOST'
|
||||
EMAIL_PORT = MY_EMAIL_PORT
|
||||
# The mail configuration for Re2o to send mails
|
||||
SERVER_EMAIL = 'no-reply@example.org' # The mail address to use
|
||||
EMAIL_HOST = 'MY_EMAIL_HOST' # The host to use
|
||||
EMAIL_PORT = MY_EMAIL_PORT # The port to use
|
||||
|
||||
# Reglages pour la bdd ldap
|
||||
# Settings of the LDAP structure
|
||||
LDAP = {
|
||||
'base_user_dn': 'cn=Utilisateurs,dc=example,dc=org',
|
||||
'base_userservice_dn': 'ou=service-users,dc=example,dc=org',
|
||||
|
@ -80,15 +94,16 @@ LDAP = {
|
|||
'user_gid': 500,
|
||||
}
|
||||
|
||||
|
||||
# A range of UID to use. Used in linux environement
|
||||
UID_RANGES = {
|
||||
'users': [21001, 30000],
|
||||
'service-users': [20000, 21000],
|
||||
}
|
||||
|
||||
# Chaque groupe a un gid assigné, voici la place libre pour assignation
|
||||
# A range of GID to use. Used in linux environement
|
||||
GID_RANGES = {
|
||||
'posix': [501, 600],
|
||||
}
|
||||
|
||||
# Some Django apps you want to add in you local project
|
||||
OPTIONNAL_APPS = ()
|
||||
|
|
|
@ -302,7 +302,7 @@ def acl_change_filter(parser, token):
|
|||
|
||||
try:
|
||||
tag_content = token.split_contents()
|
||||
tag_name = tag_content[0]
|
||||
# tag_name = tag_content[0]
|
||||
model_name = tag_content[1]
|
||||
field_name = tag_content[2]
|
||||
args = tag_content[3:]
|
||||
|
|
|
@ -19,13 +19,20 @@
|
|||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
"""re2o.templatetags.self_adhesion
|
||||
A simple templatagetag which returns the value of the option `self_adhesion`
|
||||
which indicated if a user can creates an account by himself
|
||||
"""
|
||||
|
||||
from django import template
|
||||
from preferences.models import OptionalUser, GeneralOption
|
||||
from preferences.models import OptionalUser
|
||||
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def self_adhesion():
|
||||
""" Returns True if the user are allowed to create accounts """
|
||||
options, _created = OptionalUser.objects.get_or_create()
|
||||
return options.self_adhesion
|
||||
|
|
|
@ -36,18 +36,13 @@ Fonction :
|
|||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
from django.utils import timezone
|
||||
from django.db.models import Q
|
||||
from django.contrib import messages
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
|
||||
from cotisations.models import Cotisation, Facture, Paiement, Vente
|
||||
from machines.models import Domain, Interface, Machine
|
||||
from cotisations.models import Cotisation, Facture, Vente
|
||||
from machines.models import Interface, Machine
|
||||
from users.models import Adherent, User, Ban, Whitelist
|
||||
from preferences.models import Service
|
||||
|
||||
|
||||
def all_adherent(search_time=None):
|
||||
|
|
|
@ -26,32 +26,28 @@ les views
|
|||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from itertools import chain
|
||||
import git
|
||||
from reversion.models import Version
|
||||
|
||||
from django.http import Http404
|
||||
from django.urls import reverse
|
||||
from django.shortcuts import render, redirect
|
||||
from django.template.context_processors import csrf
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from reversion.models import Version
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib import messages
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.decorators.cache import cache_page
|
||||
|
||||
import git
|
||||
import os
|
||||
import time
|
||||
from itertools import chain
|
||||
|
||||
from preferences.models import Service
|
||||
from preferences.models import OptionalUser, GeneralOption, AssoOption
|
||||
import users
|
||||
import preferences
|
||||
from preferences.models import Service, GeneralOption, AssoOption
|
||||
import users
|
||||
import cotisations
|
||||
import topologie
|
||||
import machines
|
||||
|
||||
from .utils import re2o_paginator
|
||||
from .settings import BASE_DIR, INSTALLED_APPS, MIDDLEWARE_CLASSES
|
||||
from .contributors import CONTRIBUTORS
|
||||
|
||||
|
||||
|
@ -143,7 +139,7 @@ def history(request, application, object_name, object_id):
|
|||
"""
|
||||
try:
|
||||
model = HISTORY_BIND[application][object_name]
|
||||
except KeyError as e:
|
||||
except KeyError:
|
||||
raise Http404(u"Il n'existe pas d'historique pour ce modèle.")
|
||||
object_name_id = object_name + 'id'
|
||||
kwargs = {object_name_id: object_id}
|
||||
|
@ -178,10 +174,13 @@ def history(request, application, object_name, object_id):
|
|||
|
||||
@cache_page(7 * 24 * 60 * 60)
|
||||
def about_page(request):
|
||||
""" The view for the about page.
|
||||
Fetch some info about the configuration of the project. If it can't
|
||||
get the info from the Git repository, fallback to default string """
|
||||
option = AssoOption.objects.get()
|
||||
git_info_contributors = CONTRIBUTORS
|
||||
try:
|
||||
git_repo = git.Repo(BASE_DIR)
|
||||
git_repo = git.Repo(settings.BASE_DIR)
|
||||
git_info_remote = ", ".join(git_repo.remote().urls)
|
||||
git_info_branch = git_repo.active_branch.name
|
||||
last_commit = git_repo.commit()
|
||||
|
@ -194,7 +193,7 @@ def about_page(request):
|
|||
git_info_commit = NO_GIT_MSG
|
||||
git_info_commit_date = NO_GIT_MSG
|
||||
|
||||
dependencies = INSTALLED_APPS + MIDDLEWARE_CLASSES
|
||||
dependencies = settings.INSTALLED_APPS + settings.MIDDLEWARE_CLASSES
|
||||
|
||||
return render(
|
||||
request,
|
||||
|
|
|
@ -32,8 +32,9 @@ https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import sys
|
||||
from os.path import dirname
|
||||
import sys
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue