mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-25 22:22:26 +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
|
# 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.
|
||||||
|
"""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.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
import cotisations
|
|
||||||
import logs
|
|
||||||
import machines
|
|
||||||
import preferences
|
|
||||||
import search
|
|
||||||
import topologie
|
|
||||||
import users
|
|
||||||
|
|
||||||
|
|
||||||
def can_create(model):
|
def can_create(model):
|
||||||
"""Decorator to check if an user can create a model.
|
"""Decorator to check if an user can create a model.
|
||||||
|
@ -49,7 +41,11 @@ def can_create(model):
|
||||||
of models.
|
of models.
|
||||||
"""
|
"""
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
|
"""The decorator to use on a specific view
|
||||||
|
"""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
can, msg = model.can_create(request.user, *args, **kwargs)
|
can, msg = model.can_create(request.user, *args, **kwargs)
|
||||||
if not can:
|
if not can:
|
||||||
messages.error(
|
messages.error(
|
||||||
|
@ -68,31 +64,37 @@ def can_edit(model, *field_list):
|
||||||
kind of models.
|
kind of models.
|
||||||
"""
|
"""
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
|
"""The decorator to use on a specific view
|
||||||
|
"""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
instance = model.get_instance(*args, **kwargs)
|
instance = model.get_instance(*args, **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_edit(request.user)
|
can, msg = instance.can_edit(request.user)
|
||||||
if not can:
|
if not can:
|
||||||
messages.error(
|
messages.error(
|
||||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||||
return redirect(reverse('users:profil',
|
return redirect(reverse(
|
||||||
kwargs={'userid': str(request.user.id)}
|
'users:profil',
|
||||||
))
|
kwargs={'userid': str(request.user.id)}
|
||||||
|
))
|
||||||
for field in field_list:
|
for field in field_list:
|
||||||
can_change = getattr(instance, 'can_change_' + field)
|
can_change_fct = getattr(instance, 'can_change_' + field)
|
||||||
can, msg = can_change(request.user, *args, **kwargs)
|
can, msg = can_change_fct(request.user, *args, **kwargs)
|
||||||
if not can:
|
if not can:
|
||||||
messages.error(
|
messages.error(
|
||||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||||
return redirect(reverse('users:profil',
|
return redirect(reverse(
|
||||||
kwargs={'userid': str(
|
'users:profil',
|
||||||
request.user.id)}
|
kwargs={'userid': str(request.user.id)}
|
||||||
))
|
))
|
||||||
return view(request, instance, *args, **kwargs)
|
return view(request, instance, *args, **kwargs)
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -103,17 +105,21 @@ def can_change(model, *field_list):
|
||||||
Difference with can_edit : take a class and not an instance
|
Difference with can_edit : take a class and not an instance
|
||||||
"""
|
"""
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
|
"""The decorator to use on a specific view
|
||||||
|
"""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
for field in field_list:
|
for field in field_list:
|
||||||
can_change = getattr(model, 'can_change_' + field)
|
can_change_fct = getattr(model, 'can_change_' + field)
|
||||||
can, msg = can_change(request.user, *args, **kwargs)
|
can, msg = can_change_fct(request.user, *args, **kwargs)
|
||||||
if not can:
|
if not can:
|
||||||
messages.error(
|
messages.error(
|
||||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||||
return redirect(reverse('users:profil',
|
return redirect(reverse(
|
||||||
kwargs={'userid': str(
|
'users:profil',
|
||||||
request.user.id)}
|
kwargs={'userid': str(request.user.id)}
|
||||||
))
|
))
|
||||||
return view(request, *args, **kwargs)
|
return view(request, *args, **kwargs)
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -127,21 +133,27 @@ def can_delete(model):
|
||||||
kind of models.
|
kind of models.
|
||||||
"""
|
"""
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
|
"""The decorator to use on a specific view
|
||||||
|
"""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
instance = model.get_instance(*args, **kwargs)
|
instance = model.get_instance(*args, **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_delete(request.user)
|
can, msg = instance.can_delete(request.user)
|
||||||
if not can:
|
if not can:
|
||||||
messages.error(
|
messages.error(
|
||||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||||
return redirect(reverse('users:profil',
|
return redirect(reverse(
|
||||||
kwargs={'userid': str(request.user.id)}
|
'users:profil',
|
||||||
))
|
kwargs={'userid': str(request.user.id)}
|
||||||
|
))
|
||||||
return view(request, instance, *args, **kwargs)
|
return view(request, instance, *args, **kwargs)
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -151,7 +163,11 @@ def can_delete_set(model):
|
||||||
"""Decorator which returns a list of detable models by request user.
|
"""Decorator which returns a list of detable models by request user.
|
||||||
If none of them, return an error"""
|
If none of them, return an error"""
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
|
"""The decorator to use on a specific view
|
||||||
|
"""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
all_objects = model.objects.all()
|
all_objects = model.objects.all()
|
||||||
instances_id = []
|
instances_id = []
|
||||||
for instance in all_objects:
|
for instance in all_objects:
|
||||||
|
@ -160,10 +176,12 @@ def can_delete_set(model):
|
||||||
instances_id.append(instance.id)
|
instances_id.append(instance.id)
|
||||||
instances = model.objects.filter(id__in=instances_id)
|
instances = model.objects.filter(id__in=instances_id)
|
||||||
if not instances:
|
if not instances:
|
||||||
messages.error(request, "Vous ne pouvez pas accéder à ce menu")
|
messages.error(
|
||||||
return redirect(reverse('users:profil',
|
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||||
kwargs={'userid': str(request.user.id)}
|
return redirect(reverse(
|
||||||
))
|
'users:profil',
|
||||||
|
kwargs={'userid': str(request.user.id)}
|
||||||
|
))
|
||||||
return view(request, instances, *args, **kwargs)
|
return view(request, instances, *args, **kwargs)
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -177,21 +195,27 @@ def can_view(model):
|
||||||
kind of models.
|
kind of models.
|
||||||
"""
|
"""
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
|
"""The decorator to use on a specific view
|
||||||
|
"""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
instance = model.get_instance(*args, **kwargs)
|
instance = model.get_instance(*args, **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(
|
messages.error(
|
||||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||||
return redirect(reverse('users:profil',
|
return redirect(reverse(
|
||||||
kwargs={'userid': str(request.user.id)}
|
'users:profil',
|
||||||
))
|
kwargs={'userid': str(request.user.id)}
|
||||||
|
))
|
||||||
return view(request, instance, *args, **kwargs)
|
return view(request, instance, *args, **kwargs)
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -201,14 +225,19 @@ def can_view_all(model):
|
||||||
"""Decorator to check if an user can view a class of model.
|
"""Decorator to check if an user can view a class of model.
|
||||||
"""
|
"""
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
|
"""The decorator to use on a specific view
|
||||||
|
"""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
can, msg = model.can_view_all(request.user)
|
can, msg = model.can_view_all(request.user)
|
||||||
if not can:
|
if not can:
|
||||||
messages.error(
|
messages.error(
|
||||||
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
request, msg or "Vous ne pouvez pas accéder à ce menu")
|
||||||
return redirect(reverse('users:profil',
|
return redirect(reverse(
|
||||||
kwargs={'userid': str(request.user.id)}
|
'users:profil',
|
||||||
))
|
kwargs={'userid': str(request.user.id)}
|
||||||
|
))
|
||||||
return view(request, *args, **kwargs)
|
return view(request, *args, **kwargs)
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -220,15 +249,20 @@ def can_view_app(app_name):
|
||||||
assert app_name in sys.modules.keys()
|
assert app_name in sys.modules.keys()
|
||||||
|
|
||||||
def decorator(view):
|
def decorator(view):
|
||||||
|
"""The decorator to use on a specific view
|
||||||
|
"""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
app = sys.modules[app_name]
|
app = sys.modules[app_name]
|
||||||
can, msg = app.can_view(request.user)
|
can, msg = app.can_view(request.user)
|
||||||
if can:
|
if can:
|
||||||
return view(request, *args, **kwargs)
|
return view(request, *args, **kwargs)
|
||||||
messages.error(request, msg)
|
messages.error(request, msg)
|
||||||
return redirect(reverse('users:profil',
|
return redirect(reverse(
|
||||||
kwargs={'userid': str(request.user.id)}
|
'users:profil',
|
||||||
))
|
kwargs={'userid': str(request.user.id)}
|
||||||
|
))
|
||||||
return wrapper
|
return wrapper
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
@ -236,13 +270,16 @@ def can_view_app(app_name):
|
||||||
def can_edit_history(view):
|
def can_edit_history(view):
|
||||||
"""Decorator to check if an user can edit history."""
|
"""Decorator to check if an user can edit history."""
|
||||||
def wrapper(request, *args, **kwargs):
|
def wrapper(request, *args, **kwargs):
|
||||||
|
"""The wrapper used for a specific request
|
||||||
|
"""
|
||||||
if request.user.has_perm('admin.change_logentry'):
|
if request.user.has_perm('admin.change_logentry'):
|
||||||
return view(request, *args, **kwargs)
|
return view(request, *args, **kwargs)
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
"Vous ne pouvez pas éditer l'historique."
|
"Vous ne pouvez pas éditer l'historique."
|
||||||
)
|
)
|
||||||
return redirect(reverse('users:profil',
|
return redirect(reverse(
|
||||||
kwargs={'userid': str(request.user.id)}
|
'users:profil',
|
||||||
))
|
kwargs={'userid': str(request.user.id)}
|
||||||
|
))
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
"""re2o.contributors
|
||||||
|
A list of the proud contributors to Re2o
|
||||||
|
"""
|
||||||
|
|
||||||
CONTRIBUTORS = [
|
CONTRIBUTORS = [
|
||||||
'Gabriel "Chirac" Détraz',
|
'Gabriel "Chirac" Détraz',
|
||||||
|
|
|
@ -1,15 +1,45 @@
|
||||||
from django.db import models
|
# -*- mode: python; coding: utf-8 -*-
|
||||||
from django import forms
|
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||||
from functools import partial
|
# 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:
|
class FieldPermissionModelMixin:
|
||||||
|
""" The model mixin. Defines the `has_field_perm` function """
|
||||||
field_permissions = {} # {'field_name': callable}
|
field_permissions = {} # {'field_name': callable}
|
||||||
FIELD_PERM_CODENAME = 'can_change_{model}_{name}'
|
FIELD_PERM_CODENAME = 'can_change_{model}_{name}'
|
||||||
FIELD_PERMISSION_GETTER = 'can_change_{name}'
|
FIELD_PERMISSION_GETTER = 'can_change_{name}'
|
||||||
FIELD_PERMISSION_MISSING_DEFAULT = True
|
FIELD_PERMISSION_MISSING_DEFAULT = True
|
||||||
|
|
||||||
def has_field_perm(self, user, field):
|
def has_field_perm(self, user, field):
|
||||||
|
""" Checks if a `user` has the right to edit the `field`
|
||||||
|
of this model """
|
||||||
if field in self.field_permissions:
|
if field in self.field_permissions:
|
||||||
checks = self.field_permissions[field]
|
checks = self.field_permissions[field]
|
||||||
if not isinstance(checks, (list, tuple)):
|
if not isinstance(checks, (list, tuple)):
|
||||||
|
@ -39,7 +69,7 @@ class FieldPermissionModelMixin:
|
||||||
# Try to find a user setting that qualifies them for permission.
|
# Try to find a user setting that qualifies them for permission.
|
||||||
for perm in checks:
|
for perm in checks:
|
||||||
if callable(perm):
|
if callable(perm):
|
||||||
result, reason = perm(user_request=user)
|
result, _reason = perm(user_request=user)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
|
@ -52,11 +82,6 @@ class FieldPermissionModelMixin:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
class FieldPermissionModel(FieldPermissionModelMixin, models.Model):
|
|
||||||
class Meta:
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
|
|
||||||
class FieldPermissionFormMixin:
|
class FieldPermissionFormMixin:
|
||||||
"""
|
"""
|
||||||
Construit le formulaire et retire les champs interdits
|
Construit le formulaire et retire les champs interdits
|
||||||
|
@ -73,8 +98,5 @@ class FieldPermissionFormMixin:
|
||||||
self.remove_unauthorized_field(name)
|
self.remove_unauthorized_field(name)
|
||||||
|
|
||||||
def remove_unauthorized_field(self, name):
|
def remove_unauthorized_field(self, name):
|
||||||
|
""" Remove one field from the fields of the form """
|
||||||
del self.fields[name]
|
del self.fields[name]
|
||||||
|
|
||||||
|
|
||||||
class FieldPermissionForm(FieldPermissionFormMixin, forms.ModelForm):
|
|
||||||
pass
|
|
||||||
|
|
|
@ -24,7 +24,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Module d'authentification
|
# Module d'authentification
|
||||||
# David Sinquin, Gabriel Détraz, Goulven Kermarec
|
# David Sinquin, Gabriel Détraz, Goulven Kermarec
|
||||||
|
"""re2o.login
|
||||||
|
Module in charge of handling the login process and verifications
|
||||||
|
"""
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import binascii
|
import binascii
|
||||||
|
@ -42,6 +44,7 @@ DIGEST_LEN = 20
|
||||||
|
|
||||||
|
|
||||||
def makeSecret(password):
|
def makeSecret(password):
|
||||||
|
""" Build a hashed and salted version of the password """
|
||||||
salt = os.urandom(4)
|
salt = os.urandom(4)
|
||||||
h = hashlib.sha1(password.encode())
|
h = hashlib.sha1(password.encode())
|
||||||
h.update(salt)
|
h.update(salt)
|
||||||
|
@ -49,11 +52,13 @@ def makeSecret(password):
|
||||||
|
|
||||||
|
|
||||||
def hashNT(password):
|
def hashNT(password):
|
||||||
hash = hashlib.new('md4', password.encode('utf-16le')).digest()
|
""" Build a md4 hash of the password to use as the NT-password """
|
||||||
return binascii.hexlify(hash).upper()
|
hash_str = hashlib.new('md4', password.encode('utf-16le')).digest()
|
||||||
|
return binascii.hexlify(hash_str).upper()
|
||||||
|
|
||||||
|
|
||||||
def checkPassword(challenge_password, password):
|
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())
|
challenge_bytes = decodestring(challenge_password[ALGO_LEN:].encode())
|
||||||
digest = challenge_bytes[:DIGEST_LEN]
|
digest = challenge_bytes[:DIGEST_LEN]
|
||||||
salt = challenge_bytes[DIGEST_LEN:]
|
salt = challenge_bytes[DIGEST_LEN:]
|
||||||
|
@ -74,7 +79,7 @@ class SSHAPasswordHasher(hashers.BasePasswordHasher):
|
||||||
|
|
||||||
algorithm = ALGO_NAME
|
algorithm = ALGO_NAME
|
||||||
|
|
||||||
def encode(self, password, salt, iterations=None):
|
def encode(self, password, salt):
|
||||||
"""
|
"""
|
||||||
Hash and salt the given password using SSHA algorithm
|
Hash and salt the given password using SSHA algorithm
|
||||||
|
|
||||||
|
@ -92,16 +97,16 @@ class SSHAPasswordHasher(hashers.BasePasswordHasher):
|
||||||
|
|
||||||
def safe_summary(self, encoded):
|
def safe_summary(self, encoded):
|
||||||
"""
|
"""
|
||||||
Provides a safe summary ofthe password
|
Provides a safe summary of the password
|
||||||
"""
|
"""
|
||||||
assert encoded.startswith(self.algorithm)
|
assert encoded.startswith(self.algorithm)
|
||||||
hash = encoded[ALGO_LEN:]
|
hash_str = encoded[ALGO_LEN:]
|
||||||
hash = binascii.hexlify(decodestring(hash.encode())).decode()
|
hash_str = binascii.hexlify(decodestring(hash_str.encode())).decode()
|
||||||
return OrderedDict([
|
return OrderedDict([
|
||||||
('algorithm', self.algorithm),
|
('algorithm', self.algorithm),
|
||||||
('iterations', 0),
|
('iterations', 0),
|
||||||
('salt', hashers.mask_hash(hash[2*DIGEST_LEN:], show=2)),
|
('salt', hashers.mask_hash(hash_str[2*DIGEST_LEN:], show=2)),
|
||||||
('hash', hashers.mask_hash(hash[:2*DIGEST_LEN])),
|
('hash', hashers.mask_hash(hash_str[:2*DIGEST_LEN])),
|
||||||
])
|
])
|
||||||
|
|
||||||
def harden_runtime(self, password, encoded):
|
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.
|
commits. This list is extracted from the current gitlab repository.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
|
||||||
import os
|
import os
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
""" The command object for `gen_contrib` """
|
||||||
help = 'Update contributors list'
|
help = 'Update contributors list'
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
@ -39,6 +40,8 @@ class Command(BaseCommand):
|
||||||
]
|
]
|
||||||
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("\"\"\"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("\n")
|
||||||
contrib_file.write("CONTRIBUTORS = " + str(contributeurs))
|
contrib_file.write("CONTRIBUTORS = " + str(contributeurs))
|
||||||
|
|
|
@ -19,23 +19,34 @@
|
||||||
# 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.
|
||||||
|
"""re2o.mixins
|
||||||
|
A set of mixins used all over the project to avoid duplicating code
|
||||||
|
"""
|
||||||
|
|
||||||
from reversion import revisions as reversion
|
from reversion import revisions as reversion
|
||||||
|
|
||||||
|
|
||||||
class RevMixin(object):
|
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):
|
def save(self, *args, **kwargs):
|
||||||
|
""" Creates a version of this object and save it to database """
|
||||||
if self.pk is None:
|
if self.pk is None:
|
||||||
reversion.set_comment("Création")
|
reversion.set_comment("Création")
|
||||||
return super(RevMixin, self).save(*args, **kwargs)
|
return super(RevMixin, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
|
""" Creates a version of this object and delete it from database """
|
||||||
reversion.set_comment("Suppresion")
|
reversion.set_comment("Suppresion")
|
||||||
return super(RevMixin, self).delete(*args, **kwargs)
|
return super(RevMixin, self).delete(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class FormRevMixin(object):
|
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):
|
def save(self, *args, **kwargs):
|
||||||
|
""" Create a version of this object and save it to database """
|
||||||
if reversion.get_comment() != "" and self.changed_data != []:
|
if reversion.get_comment() != "" and self.changed_data != []:
|
||||||
reversion.set_comment(
|
reversion.set_comment(
|
||||||
reversion.get_comment() + ",%s"
|
reversion.get_comment() + ",%s"
|
||||||
|
@ -66,14 +77,16 @@ class AclMixin(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_classname(cls):
|
def get_classname(cls):
|
||||||
|
""" Returns the name of the class where this mixin is used """
|
||||||
return str(cls.__name__).lower()
|
return str(cls.__name__).lower()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_modulename(cls):
|
def get_modulename(cls):
|
||||||
|
""" Returns the name of the module where this mixin is used """
|
||||||
return str(cls.__module__).split('.')[0].lower()
|
return str(cls.__module__).split('.')[0].lower()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_instance(cls, *args, **kwargs):
|
def get_instance(cls, *_args, **kwargs):
|
||||||
"""Récupère une instance
|
"""Récupère une instance
|
||||||
:param objectid: Instance id à trouver
|
:param objectid: Instance id à trouver
|
||||||
:return: Une instance de la classe évidemment"""
|
:return: Une instance de la classe évidemment"""
|
||||||
|
@ -81,7 +94,7 @@ class AclMixin(object):
|
||||||
return cls.objects.get(pk=object_id)
|
return cls.objects.get(pk=object_id)
|
||||||
|
|
||||||
@classmethod
|
@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
|
"""Verifie que l'user a les bons droits pour créer
|
||||||
un object
|
un object
|
||||||
:param user_request: instance utilisateur qui fait la requête
|
: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()
|
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
|
||||||
cette instance
|
cette instance
|
||||||
:param self: Instance à editer
|
:param self: Instance à editer
|
||||||
|
@ -106,7 +119,7 @@ class AclMixin(object):
|
||||||
u"Vous n'avez pas le droit d'éditer des " + 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
|
||||||
cette instance
|
cette instance
|
||||||
:param self: Instance à delete
|
:param self: Instance à delete
|
||||||
|
@ -120,7 +133,7 @@ class AclMixin(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@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,
|
"""Vérifie qu'on peut bien afficher l'ensemble des objets,
|
||||||
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
|
||||||
|
@ -132,7 +145,7 @@ class AclMixin(object):
|
||||||
u"Vous n'avez pas le droit de voir des " + 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
|
||||||
droit view objet
|
droit view objet
|
||||||
:param self: instance à voir
|
:param self: instance à voir
|
||||||
|
|
|
@ -18,22 +18,27 @@
|
||||||
# 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.
|
||||||
|
"""re2o.script_utils
|
||||||
|
A set of utility scripts that can be used as standalone to interact easily
|
||||||
|
with Re2o throught the CLI
|
||||||
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from os.path import dirname
|
||||||
import sys
|
import sys
|
||||||
import pwd
|
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.core.management.base import CommandError
|
||||||
|
from django.db import transaction
|
||||||
|
from django.utils.html import strip_tags
|
||||||
|
|
||||||
from users.models import User
|
from users.models import User
|
||||||
|
|
||||||
from django.utils.html import strip_tags
|
proj_path = dirname(dirname(__file__))
|
||||||
from reversion import revisions as reversion
|
|
||||||
from django.db import transaction
|
|
||||||
from getpass import getpass
|
|
||||||
|
|
||||||
proj_path = "/var/www/re2o"
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings")
|
||||||
sys.path.append(proj_path)
|
sys.path.append(proj_path)
|
||||||
os.chdir(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
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
|
||||||
import os
|
import os
|
||||||
from .settings_local import *
|
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__)))
|
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
|
# Auth definition
|
||||||
|
|
||||||
PASSWORD_HASHERS = (
|
PASSWORD_HASHERS = (
|
||||||
're2o.login.SSHAPasswordHasher',
|
're2o.login.SSHAPasswordHasher',
|
||||||
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||||
)
|
)
|
||||||
|
AUTH_USER_MODEL = 'users.User' # The class to use for authentication
|
||||||
AUTH_USER_MODEL = 'users.User'
|
LOGIN_URL = '/login/' # The URL for login page
|
||||||
LOGIN_URL = '/login/'
|
LOGIN_REDIRECT_URL = '/' # The URL for redirecting after login
|
||||||
LOGIN_REDIRECT_URL = '/'
|
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
DJANGO_CONTRIB_APPS = (
|
||||||
INSTALLED_APPS = (
|
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
)
|
||||||
|
EXTERNAL_CONTRIB_APPS = (
|
||||||
'bootstrap3',
|
'bootstrap3',
|
||||||
|
'rest_framework',
|
||||||
|
'reversion',
|
||||||
|
)
|
||||||
|
LOCAL_APPS = (
|
||||||
'users',
|
'users',
|
||||||
'machines',
|
'machines',
|
||||||
'cotisations',
|
'cotisations',
|
||||||
|
@ -75,11 +74,14 @@ INSTALLED_APPS = (
|
||||||
're2o',
|
're2o',
|
||||||
'preferences',
|
'preferences',
|
||||||
'logs',
|
'logs',
|
||||||
'rest_framework',
|
'api',
|
||||||
'reversion',
|
)
|
||||||
'api'
|
INSTALLED_APPS = (
|
||||||
) + OPTIONNAL_APPS
|
DJANGO_CONTRIB_APPS +
|
||||||
|
EXTERNAL_CONTRIB_APPS +
|
||||||
|
LOCAL_APPS +
|
||||||
|
OPTIONNAL_APPS
|
||||||
|
)
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE_CLASSES = (
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.locale.LocaleMiddleware',
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
|
@ -93,14 +95,17 @@ MIDDLEWARE_CLASSES = (
|
||||||
'reversion.middleware.RevisionMiddleware',
|
'reversion.middleware.RevisionMiddleware',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# The root url module to define the project URLs
|
||||||
ROOT_URLCONF = 're2o.urls'
|
ROOT_URLCONF = 're2o.urls'
|
||||||
|
|
||||||
|
# The templates configuration (see Django documentation)
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [
|
'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,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
|
@ -115,57 +120,50 @@ TEMPLATES = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# The WSGI module to use in a server environment
|
||||||
WSGI_APPLICATION = 're2o.wsgi.application'
|
WSGI_APPLICATION = 're2o.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en'
|
LANGUAGE_CODE = 'en'
|
||||||
|
USE_I18N = True
|
||||||
|
USE_L10N = True
|
||||||
# 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
|
||||||
|
# Use only absolute paths with '/' delimiters even on Windows
|
||||||
LOCALE_PATHS = [
|
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'
|
# Should use time zone ?
|
||||||
|
|
||||||
USE_I18N = True
|
|
||||||
|
|
||||||
USE_L10N = True
|
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
# Router config for database
|
||||||
DATABASE_ROUTERS = ['ldapdb.router.Router']
|
DATABASE_ROUTERS = ['ldapdb.router.Router']
|
||||||
|
|
||||||
|
# django-bootstrap3 config
|
||||||
# django-bootstrap3 config dictionnary
|
|
||||||
BOOTSTRAP3 = {
|
BOOTSTRAP3 = {
|
||||||
'jquery_url': '/static/js/jquery-2.2.4.min.js',
|
'jquery_url': '/static/js/jquery-2.2.4.min.js',
|
||||||
'base_url': '/static/bootstrap/',
|
'base_url': '/static/bootstrap/',
|
||||||
'include_jquery': True,
|
'include_jquery': True,
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOTSTRAP_BASE_URL = '/static/bootstrap/'
|
BOOTSTRAP_BASE_URL = '/static/bootstrap/'
|
||||||
|
|
||||||
|
# Directories where collectstatic should look for static files
|
||||||
|
# Use only absolute paths with '/' delimiters even on Windows
|
||||||
STATICFILES_DIRS = (
|
STATICFILES_DIRS = (
|
||||||
# Put strings here, like "/home/html/static" or "C:/www/django/static".
|
os.path.join(BASE_DIR, 'static').replace('\\', '/'),
|
||||||
# Always use forward slashes, even on Windows.
|
|
||||||
# Don't forget to use absolute paths, not relative paths.
|
|
||||||
os.path.join(
|
|
||||||
BASE_DIR,
|
|
||||||
'static',
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
# Directory where the static files serverd by the server are stored
|
||||||
MEDIA_ROOT = '/var/www/re2o/media'
|
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
|
||||||
|
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static_files')
|
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 = {
|
GRAPH_MODELS = {
|
||||||
'all_applications': True,
|
'all_applications': True,
|
||||||
'group_models': True,
|
'group_models': True,
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,45 +19,56 @@
|
||||||
# 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.
|
||||||
|
"""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
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
# A secret key used by the server.
|
||||||
SECRET_KEY = 'SUPER_SECRET_KEY'
|
SECRET_KEY = 'SUPER_SECRET_KEY'
|
||||||
|
|
||||||
|
# The password to access the project database
|
||||||
DB_PASSWORD = 'SUPER_SECRET_DB'
|
DB_PASSWORD = 'SUPER_SECRET_DB'
|
||||||
|
|
||||||
# AES key for secret key encryption length must be a multiple of 16
|
# AES key for secret key encryption.
|
||||||
AES_KEY = 'THE_AES_KEY'
|
# 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!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
|
|
||||||
|
# A list of admins of the services. Receive mails when an error occurs
|
||||||
ADMINS = [('Example', 'rezo-admin@example.org')]
|
ADMINS = [('Example', 'rezo-admin@example.org')]
|
||||||
|
|
||||||
SERVER_EMAIL = 'no-reply@example.org'
|
# The list of hostname the server will respond to.
|
||||||
|
|
||||||
# Obligatoire, liste des host autorisés
|
|
||||||
ALLOWED_HOSTS = ['URL_SERVER']
|
ALLOWED_HOSTS = ['URL_SERVER']
|
||||||
|
|
||||||
|
# The time zone the server is runned in
|
||||||
|
TIME_ZONE = 'Europe/Paris'
|
||||||
|
|
||||||
|
# The storage systems parameters to use
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': { # The DB
|
||||||
'ENGINE': 'db_engine',
|
'ENGINE': 'db_engine',
|
||||||
'NAME': 'db_name_value',
|
'NAME': 'db_name_value',
|
||||||
'USER': 'db_user_value',
|
'USER': 'db_user_value',
|
||||||
'PASSWORD': DB_PASSWORD,
|
'PASSWORD': DB_PASSWORD,
|
||||||
'HOST': 'db_host_value',
|
'HOST': 'db_host_value',
|
||||||
},
|
},
|
||||||
'ldap': {
|
'ldap': { # The LDAP
|
||||||
'ENGINE': 'ldapdb.backends.ldap',
|
'ENGINE': 'ldapdb.backends.ldap',
|
||||||
'NAME': 'ldap://ldap_host_ip/',
|
'NAME': 'ldap://ldap_host_ip/',
|
||||||
'USER': 'ldap_dn',
|
'USER': 'ldap_dn',
|
||||||
# 'TLS': True,
|
'TLS': True,
|
||||||
'PASSWORD': 'SUPER_SECRET_LDAP',
|
'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_CONTENT_TYPE_NOSNIFF = False
|
||||||
SECURE_BROWSER_XSS_FILTER = False
|
SECURE_BROWSER_XSS_FILTER = False
|
||||||
SESSION_COOKIE_SECURE = False
|
SESSION_COOKIE_SECURE = False
|
||||||
|
@ -66,12 +77,15 @@ CSRF_COOKIE_HTTPONLY = False
|
||||||
X_FRAME_OPTIONS = 'DENY'
|
X_FRAME_OPTIONS = 'DENY'
|
||||||
SESSION_COOKIE_AGE = 60 * 60 * 3
|
SESSION_COOKIE_AGE = 60 * 60 * 3
|
||||||
|
|
||||||
|
# The path where your organization logo is stored
|
||||||
LOGO_PATH = "static_files/logo.png"
|
LOGO_PATH = "static_files/logo.png"
|
||||||
|
|
||||||
EMAIL_HOST = 'MY_EMAIL_HOST'
|
# The mail configuration for Re2o to send mails
|
||||||
EMAIL_PORT = MY_EMAIL_PORT
|
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 = {
|
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',
|
||||||
|
@ -80,15 +94,16 @@ LDAP = {
|
||||||
'user_gid': 500,
|
'user_gid': 500,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# A range of UID to use. Used in linux environement
|
||||||
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
|
# A range of GID to use. Used in linux environement
|
||||||
GID_RANGES = {
|
GID_RANGES = {
|
||||||
'posix': [501, 600],
|
'posix': [501, 600],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Some Django apps you want to add in you local project
|
||||||
OPTIONNAL_APPS = ()
|
OPTIONNAL_APPS = ()
|
||||||
|
|
|
@ -302,7 +302,7 @@ def acl_change_filter(parser, token):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tag_content = token.split_contents()
|
tag_content = token.split_contents()
|
||||||
tag_name = tag_content[0]
|
# tag_name = tag_content[0]
|
||||||
model_name = tag_content[1]
|
model_name = tag_content[1]
|
||||||
field_name = tag_content[2]
|
field_name = tag_content[2]
|
||||||
args = tag_content[3:]
|
args = tag_content[3:]
|
||||||
|
|
|
@ -19,13 +19,20 @@
|
||||||
# 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.
|
||||||
|
"""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 django import template
|
||||||
from preferences.models import OptionalUser, GeneralOption
|
from preferences.models import OptionalUser
|
||||||
|
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def self_adhesion():
|
def self_adhesion():
|
||||||
|
""" Returns True if the user are allowed to create accounts """
|
||||||
options, _created = OptionalUser.objects.get_or_create()
|
options, _created = OptionalUser.objects.get_or_create()
|
||||||
return options.self_adhesion
|
return options.self_adhesion
|
||||||
|
|
|
@ -36,18 +36,13 @@ Fonction :
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.db.models import Q
|
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 django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||||
|
|
||||||
from cotisations.models import Cotisation, Facture, Paiement, Vente
|
from cotisations.models import Cotisation, Facture, Vente
|
||||||
from machines.models import Domain, Interface, Machine
|
from machines.models import Interface, Machine
|
||||||
from users.models import Adherent, User, Ban, Whitelist
|
from users.models import Adherent, User, Ban, Whitelist
|
||||||
from preferences.models import Service
|
|
||||||
|
|
||||||
|
|
||||||
def all_adherent(search_time=None):
|
def all_adherent(search_time=None):
|
||||||
|
|
|
@ -26,32 +26,28 @@ les views
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from itertools import chain
|
||||||
|
import git
|
||||||
|
from reversion.models import Version
|
||||||
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
from django.template.context_processors import csrf
|
from django.template.context_processors import csrf
|
||||||
from django.contrib.auth.decorators import login_required, permission_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from reversion.models import Version
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.views.decorators.cache import cache_page
|
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
|
import preferences
|
||||||
|
from preferences.models import Service, GeneralOption, AssoOption
|
||||||
|
import users
|
||||||
import cotisations
|
import cotisations
|
||||||
import topologie
|
import topologie
|
||||||
import machines
|
import machines
|
||||||
|
|
||||||
from .utils import re2o_paginator
|
from .utils import re2o_paginator
|
||||||
from .settings import BASE_DIR, INSTALLED_APPS, MIDDLEWARE_CLASSES
|
|
||||||
from .contributors import CONTRIBUTORS
|
from .contributors import CONTRIBUTORS
|
||||||
|
|
||||||
|
|
||||||
|
@ -143,7 +139,7 @@ def history(request, application, object_name, object_id):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
model = HISTORY_BIND[application][object_name]
|
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.")
|
raise Http404(u"Il n'existe pas d'historique pour ce modèle.")
|
||||||
object_name_id = object_name + 'id'
|
object_name_id = object_name + 'id'
|
||||||
kwargs = {object_name_id: object_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)
|
@cache_page(7 * 24 * 60 * 60)
|
||||||
def about_page(request):
|
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()
|
option = AssoOption.objects.get()
|
||||||
git_info_contributors = CONTRIBUTORS
|
git_info_contributors = CONTRIBUTORS
|
||||||
try:
|
try:
|
||||||
git_repo = git.Repo(BASE_DIR)
|
git_repo = git.Repo(settings.BASE_DIR)
|
||||||
git_info_remote = ", ".join(git_repo.remote().urls)
|
git_info_remote = ", ".join(git_repo.remote().urls)
|
||||||
git_info_branch = git_repo.active_branch.name
|
git_info_branch = git_repo.active_branch.name
|
||||||
last_commit = git_repo.commit()
|
last_commit = git_repo.commit()
|
||||||
|
@ -194,7 +193,7 @@ def about_page(request):
|
||||||
git_info_commit = NO_GIT_MSG
|
git_info_commit = NO_GIT_MSG
|
||||||
git_info_commit_date = NO_GIT_MSG
|
git_info_commit_date = NO_GIT_MSG
|
||||||
|
|
||||||
dependencies = INSTALLED_APPS + MIDDLEWARE_CLASSES
|
dependencies = settings.INSTALLED_APPS + settings.MIDDLEWARE_CLASSES
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
|
|
|
@ -32,8 +32,9 @@ https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
from os.path import dirname
|
from os.path import dirname
|
||||||
|
import sys
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue