8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-30 08:32:26 +00:00
This commit is contained in:
lhark 2016-07-06 22:46:46 +02:00
commit bfb07c3a24
49 changed files with 840 additions and 139 deletions

4
.gitignore vendored
View file

@ -1,4 +1,4 @@
settings.py settings_local.py
settings*
*.swp *.swp
*.pyc *.pyc
__pycache__

View file

@ -3,10 +3,10 @@ from django.contrib import admin
from .models import Facture, Article, Banque, Paiement, Cotisation from .models import Facture, Article, Banque, Paiement, Cotisation
class FactureAdmin(admin.ModelAdmin): class FactureAdmin(admin.ModelAdmin):
list_display = ('user','paiement','name', 'number', 'date') list_display = ('user','paiement','name', 'number','prix', 'date','valid')
class ArticleAdmin(admin.ModelAdmin): class ArticleAdmin(admin.ModelAdmin):
list_display = ('name','prix','cotisation') list_display = ('name','prix','cotisation','duration')
class BanqueAdmin(admin.ModelAdmin): class BanqueAdmin(admin.ModelAdmin):
list_display = ('name',) list_display = ('name',)

88
cotisations/forms.py Normal file
View file

@ -0,0 +1,88 @@
from django import forms
from django.forms import ModelForm
from .models import Article, Paiement, Facture, Banque
class NewFactureForm(ModelForm):
article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article")
def __init__(self, *args, **kwargs):
super(NewFactureForm, self).__init__(*args, **kwargs)
self.fields['number'].label = 'Quantité'
self.fields['cheque'].required = False
self.fields['banque'].required = False
self.fields['cheque'].label = 'Numero de chèque'
self.fields['banque'].empty_label = "Non renseigné"
self.fields['paiement'].empty_label = "Séléctionner un moyen de paiement"
class Meta:
model = Facture
fields = ['paiement','banque','cheque','number']
def clean(self):
cleaned_data=super(NewFactureForm, self).clean()
paiement = cleaned_data.get("paiement")
cheque = cleaned_data.get("cheque")
banque = cleaned_data.get("banque")
if paiement.moyen=="chèque" and not (cheque and banque):
raise forms.ValidationError("Le numero de chèque et la banque sont obligatoires")
return cleaned_data
class EditFactureForm(NewFactureForm):
class Meta(NewFactureForm.Meta):
fields = '__all__'
def __init__(self, *args, **kwargs):
super(EditFactureForm, self).__init__(*args, **kwargs)
self.fields['user'].label = 'Adherent'
self.fields['name'].label = 'Designation'
self.fields['prix'].label = 'Prix unitaire'
self.fields['user'].empty_label = "Séléctionner l'adhérent propriétaire"
self.fields.pop('article')
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = '__all__'
def __init__(self, *args, **kwargs):
super(ArticleForm, self).__init__(*args, **kwargs)
self.fields['name'].label = "Désignation de l'article"
class DelArticleForm(ModelForm):
articles = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Articles actuels", widget=forms.CheckboxSelectMultiple)
class Meta:
fields = ['articles']
model = Article
class PaiementForm(ModelForm):
class Meta:
model = Paiement
fields = ['moyen']
def __init__(self, *args, **kwargs):
super(PaiementForm, self).__init__(*args, **kwargs)
self.fields['moyen'].label = 'Moyen de paiement à ajouter'
class DelPaiementForm(ModelForm):
paiements = forms.ModelMultipleChoiceField(queryset=Paiement.objects.all(), label="Moyens de paiement actuels", widget=forms.CheckboxSelectMultiple)
class Meta:
exclude = ['moyen']
model = Paiement
class BanqueForm(ModelForm):
class Meta:
model = Banque
fields = ['name']
def __init__(self, *args, **kwargs):
super(BanqueForm, self).__init__(*args, **kwargs)
self.fields['name'].label = 'Banque à ajouter'
class DelBanqueForm(ModelForm):
banques = forms.ModelMultipleChoiceField(queryset=Banque.objects.all(), label="Banques actuelles", widget=forms.CheckboxSelectMultiple)
class Meta:
exclude = ['name']
model = Banque

View file

@ -1,8 +1,5 @@
from django.db import models from django.db import models
from django import forms
from django.forms import ModelForm
from users.models import User
class Facture(models.Model): class Facture(models.Model):
user = models.ForeignKey('users.User', on_delete=models.PROTECT) user = models.ForeignKey('users.User', on_delete=models.PROTECT)
@ -47,31 +44,3 @@ class Cotisation(models.Model):
def __str__(self): def __str__(self):
return str(self.facture) return str(self.facture)
class NewFactureForm(ModelForm):
article = forms.ModelMultipleChoiceField(queryset=Article.objects.all(), label="Article")
def __init__(self, *args, **kwargs):
super(NewFactureForm, self).__init__(*args, **kwargs)
self.fields['number'].label = 'Quantité'
self.fields['cheque'].required = False
self.fields['banque'].required = False
self.fields['cheque'].label = 'Numero de chèque'
class Meta:
model = Facture
exclude = ['user', 'prix', 'name', 'valid']
class EditFactureForm(ModelForm):
def __init__(self, *args, **kwargs):
super(EditFactureForm, self).__init__(*args, **kwargs)
self.fields['user'].label = 'Adherent'
self.fields['number'].label = 'Quantité'
self.fields['cheque'].required = False
self.fields['banque'].required = False
self.fields['cheque'].label = 'Numero de chèque'
self.fields['name'].label = 'Designation'
self.fields['prix'].label = 'Prix unitaire'
class Meta:
model = Facture
fields = '__all__'

View file

@ -18,7 +18,7 @@
<td>{{ facture.prix }}</td> <td>{{ facture.prix }}</td>
<td>{{ facture.paiement }}</td> <td>{{ facture.paiement }}</td>
<td>{{ facture.date }}</td> <td>{{ facture.date }}</td>
<td><a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:edit-facture' facture.id %}"><i class="glyphicon glyphicon-tree-conifer"></i> Editer</a></td> <td><a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:edit-facture' facture.id %}"><i class="glyphicon glyphicon-bitcoin"></i> Editer</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View file

@ -1,7 +1,11 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block sidebar %} {% block sidebar %}
<p><a href="{% url "search:search" %}">Créer une facture</a></p>
<p><a href="{% url "search:search" %}">Editer une facture</a></p>
<p><a href="{% url "cotisations:index" %}">Liste des factures</a></p> <p><a href="{% url "cotisations:index" %}">Liste des factures</a></p>
<p><a href="{% url "cotisations:add-article" %}">Ajouter un article</a></p>
<p><a href="{% url "cotisations:del-article" %}">Retirer un article</a></p>
<p><a href="{% url "cotisations:add-paiement" %}">Ajouter un moyen de paiement</a></p>
<p><a href="{% url "cotisations:del-paiement" %}">Retirer un moyen de paiement</a></p>
<p><a href="{% url "cotisations:add-banque" %}">Ajouter une banque</a></p>
<p><a href="{% url "cotisations:del-banque" %}">Retirer une banque</a></p>
{% endblock %} {% endblock %}

View file

@ -5,6 +5,12 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^new_facture/(?P<userid>[0-9]+)$', views.new_facture, name='new-facture'), url(r'^new_facture/(?P<userid>[0-9]+)$', views.new_facture, name='new-facture'),
url(r'^edit_facture/(?P<factureid>[0-9]+)$', views.edit_facture, name='edit-facture'), url(r'^edit_facture/(?P<factureid>[0-9]+)$', views.edit_facture, name='edit-facture'),
url(r'^add_article/$', views.add_article, name='add-article'),
url(r'^del_article/$', views.del_article, name='del-article'),
url(r'^add_paiement/$', views.add_paiement, name='add-paiement'),
url(r'^del_paiement/$', views.del_paiement, name='del-paiement'),
url(r'^add_banque/$', views.add_banque, name='add-banque'),
url(r'^del_banque/$', views.del_banque, name='del-banque'),
url(r'^$', views.index, name='index'), url(r'^$', views.index, name='index'),
] ]

View file

@ -6,9 +6,10 @@ from django.shortcuts import render_to_response, get_object_or_404
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.template import Context, RequestContext, loader from django.template import Context, RequestContext, loader
from django.contrib import messages from django.contrib import messages
from django.db.models import Max from django.db.models import Max, ProtectedError
from cotisations.models import NewFactureForm, EditFactureForm, Facture, Article, Cotisation from .models import Facture, Article, Cotisation, Article
from .forms import NewFactureForm, EditFactureForm, ArticleForm, DelArticleForm, PaiementForm, DelPaiementForm, BanqueForm, DelBanqueForm
from users.models import User from users.models import User
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
@ -34,14 +35,14 @@ def is_adherent(user):
else: else:
return True return True
def create_cotis(facture, user, article): def create_cotis(facture, user, duration):
""" Update et crée l'objet cotisation associé à une facture, prend en argument l'user, la facture pour la quantitéi, et l'article pour la durée""" """ Update et crée l'objet cotisation associé à une facture, prend en argument l'user, la facture pour la quantitéi, et l'article pour la durée"""
cotisation=Cotisation(facture=facture) cotisation=Cotisation(facture=facture)
date_max = end_adhesion(user) or timezone.now() date_max = end_adhesion(user) or timezone.now()
if date_max < timezone.now(): if date_max < timezone.now():
datemax = timezone.now() datemax = timezone.now()
cotisation.date_start=date_max cotisation.date_start=date_max
cotisation.date_end = cotisation.date_start + relativedelta(months=article[0].duration*facture.number) cotisation.date_end = cotisation.date_start + relativedelta(months=duration)
cotisation.save() cotisation.save()
return return
@ -56,11 +57,12 @@ def new_facture(request, userid):
if facture_form.is_valid(): if facture_form.is_valid():
new_facture = facture_form.save(commit=False) new_facture = facture_form.save(commit=False)
article = facture_form.cleaned_data['article'] article = facture_form.cleaned_data['article']
new_facture.prix = article[0].prix new_facture.prix = sum(art.prix for art in article)
new_facture.name = article[0].name new_facture.name = ' - '.join(art.name for art in article)
new_facture.save() new_facture.save()
if article[0].cotisation == True: if any(art.cotisation for art in article):
create_cotis(new_facture, user, article) duration = sum(art.duration*facture.number for art in article if art.cotisation)
create_cotis(new_facture, user, duration)
messages.success(request, "La cotisation a été prolongée pour l'adhérent %s " % user.name ) messages.success(request, "La cotisation a été prolongée pour l'adhérent %s " % user.name )
else: else:
messages.success(request, "La facture a été crée") messages.success(request, "La facture a été crée")
@ -80,6 +82,65 @@ def edit_facture(request, factureid):
return redirect("/cotisations/") return redirect("/cotisations/")
return form({'factureform': facture_form}, 'cotisations/facture.html', request) return form({'factureform': facture_form}, 'cotisations/facture.html', request)
def add_article(request):
article = ArticleForm(request.POST or None)
if article.is_valid():
article.save()
messages.success(request, "L'article a été ajouté")
return redirect("/cotisations/")
return form({'factureform': article}, 'cotisations/facture.html', request)
def del_article(request):
article = DelArticleForm(request.POST or None)
if article.is_valid():
article_del = article.cleaned_data['articles']
article_del.delete()
messages.success(request, "Le/les articles ont été supprimé")
return redirect("/cotisations/")
return form({'factureform': article}, 'cotisations/facture.html', request)
def add_paiement(request):
paiement = PaiementForm(request.POST or None)
if paiement.is_valid():
paiement.save()
messages.success(request, "Le moyen de paiement a été ajouté")
return redirect("/cotisations/")
return form({'factureform': paiement}, 'cotisations/facture.html', request)
def del_paiement(request):
paiement = DelPaiementForm(request.POST or None)
if paiement.is_valid():
paiement_dels = paiement.cleaned_data['paiements']
for paiement_del in paiement_dels:
try:
paiement_del.delete()
messages.success(request, "Le moyen de paiement a été supprimé")
except ProtectedError:
messages.error(request, "Le moyen de paiement %s est affecté à au moins une facture, vous ne pouvez pas le supprimer" % paiement_del)
return redirect("/cotisations/")
return form({'factureform': paiement}, 'cotisations/facture.html', request)
def add_banque(request):
banque = BanqueForm(request.POST or None)
if banque.is_valid():
banque.save()
messages.success(request, "La banque a été ajoutée")
return redirect("/cotisations/")
return form({'factureform': banque}, 'cotisations/facture.html', request)
def del_banque(request):
banque = DelBanqueForm(request.POST or None)
if banque.is_valid():
banque_dels = banque.cleaned_data['banques']
for banque_del in banque_dels:
try:
banque_del.delete()
messages.success(request, "La banque a été supprimée")
except ProtectedError:
messages.error(request, "La banque %s est affectée à au moins une facture, vous ne pouvez pas la supprimer" % banque_del)
return redirect("/cotisations/")
return form({'factureform': banque}, 'cotisations/facture.html', request)
def index(request): def index(request):
facture_list = Facture.objects.order_by('pk') facture_list = Facture.objects.order_by('date').reverse()
return render(request, 'cotisations/index.html', {'facture_list': facture_list}) return render(request, 'cotisations/index.html', {'facture_list': facture_list})

View file

@ -3,7 +3,7 @@ from django.contrib import admin
from .models import Machine, MachineType, IpList, Interface from .models import Machine, MachineType, IpList, Interface
class MachineAdmin(admin.ModelAdmin): class MachineAdmin(admin.ModelAdmin):
list_display = ('user','name','type') list_display = ('user','name','type','active')
class MachineTypeAdmin(admin.ModelAdmin): class MachineTypeAdmin(admin.ModelAdmin):
list_display = ('type',) list_display = ('type',)

View file

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('machines', '0012_auto_20160704_0118'),
]
operations = [
migrations.AddField(
model_name='machine',
name='active',
field=models.BooleanField(default=True),
),
migrations.AlterField(
model_name='interface',
name='dns',
field=models.CharField(max_length=255, unique=True, help_text='Obligatoire et unique, doit se terminer en .rez et ne pas comporter de points'),
),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import machines.models
class Migration(migrations.Migration):
dependencies = [
('machines', '0013_auto_20160705_1014'),
]
operations = [
migrations.AlterField(
model_name='interface',
name='dns',
field=models.CharField(unique=True, validators=[machines.models.full_domain_validator], max_length=255, help_text="Obligatoire et unique, doit se terminer en .rez et ne pas comporter d'autres points"),
),
]

View file

@ -1,13 +1,38 @@
from django.db import models from django.db import models
from django.forms import ModelForm, Form from django.forms import ModelForm, Form, ValidationError
from macaddress.fields import MACAddressField from macaddress.fields import MACAddressField
from users.models import User from django.conf import settings
import re
def full_domain_validator(hostname):
""" Validation du nom de domaine, extensions dans settings, prefixe pas plus long que 63 caractères """
HOSTNAME_LABEL_PATTERN = re.compile("(?!-)[A-Z\d-]+(?<!-)$", re.IGNORECASE)
if not any(ext in hostname for ext in settings.ALLOWED_EXTENSIONS):
raise ValidationError(
", le nom de domaine '%(label)s' doit comporter une extension valide",
params={'label': hostname},
)
for extension in settings.ALLOWED_EXTENSIONS:
if hostname.endswith(extension):
hostname=re.sub('%s$' % extension, '', hostname)
break
if len(hostname) > 63:
raise ValidationError(
", le nom de domaine '%(label)s' est trop long (maximum de 63 caractères).",
params={'label': hostname},
)
if not HOSTNAME_LABEL_PATTERN.match(hostname):
raise ValidationError(
", ce nom de domaine '%(label)s' contient des carractères interdits.",
params={'label': hostname},
)
class Machine(models.Model): class Machine(models.Model):
user = models.ForeignKey('users.User', on_delete=models.PROTECT) user = models.ForeignKey('users.User', on_delete=models.PROTECT)
type = models.ForeignKey('MachineType', on_delete=models.PROTECT) type = models.ForeignKey('MachineType', on_delete=models.PROTECT)
name = models.CharField(max_length=255, help_text="Optionnel", blank=True, null=True) name = models.CharField(max_length=255, help_text="Optionnel", blank=True, null=True)
active = models.BooleanField(default=True)
def __str__(self): def __str__(self):
return str(self.user) + ' - ' + str(self.id) + ' - ' + str(self.name) return str(self.user) + ' - ' + str(self.id) + ' - ' + str(self.name)
@ -25,11 +50,14 @@ class Interface(models.Model):
mac_address = MACAddressField(integer=False, unique=True) mac_address = MACAddressField(integer=False, unique=True)
machine = models.ForeignKey('Machine', on_delete=models.PROTECT) machine = models.ForeignKey('Machine', on_delete=models.PROTECT)
details = models.CharField(max_length=255, blank=True) details = models.CharField(max_length=255, blank=True)
dns = models.CharField(help_text="Obligatoire et unique", max_length=255, unique=True) dns = models.CharField(help_text="Obligatoire et unique, doit se terminer en %s et ne pas comporter d'autres points" % ", ".join(settings.ALLOWED_EXTENSIONS), max_length=255, unique=True, validators=[full_domain_validator])
def __str__(self): def __str__(self):
return self.dns return self.dns
def clean(self):
self.dns=self.dns.lower()
class IpList(models.Model): class IpList(models.Model):
ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True) ipv4 = models.GenericIPAddressField(protocol='IPv4', unique=True)
@ -45,6 +73,7 @@ class EditMachineForm(ModelForm):
super(EditMachineForm, self).__init__(*args, **kwargs) super(EditMachineForm, self).__init__(*args, **kwargs)
self.fields['name'].label = 'Nom de la machine' self.fields['name'].label = 'Nom de la machine'
self.fields['type'].label = 'Type de machine' self.fields['type'].label = 'Type de machine'
self.fields['type'].empty_label = "Séléctionner un type de machine"
class NewMachineForm(EditMachineForm): class NewMachineForm(EditMachineForm):
class Meta(EditMachineForm.Meta): class Meta(EditMachineForm.Meta):

View file

@ -16,7 +16,7 @@
<td>{{ machine.machine.type }}</td> <td>{{ machine.machine.type }}</td>
<td>{{ machine.mac_address }}</td> <td>{{ machine.mac_address }}</td>
<td>{{ machine.ipv4 }}</td> <td>{{ machine.ipv4 }}</td>
<td><a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:edit-machine' machine.id %}"><i class="glyphicon glyphicon-tree-conifer"></i> Editer</a></td> <td><a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:edit-machine' machine.id %}"><i class="glyphicon glyphicon-hdd"></i> Editer</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View file

@ -1,5 +1,4 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block sidebar %} {% block sidebar %}
<p><a href="{% url "search:search" %}">Nouvelle machine</a></p>
{% endblock %} {% endblock %}

108
re2o/settings.py Normal file
View file

@ -0,0 +1,108 @@
"""
Django settings for re2o project.
Generated by 'django-admin startproject' using Django 1.8.13.
For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
from .settings_local import SECRET_KEY, DATABASES, DEBUG, ALLOWED_HOSTS, ALLOWED_EXTENSIONS
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/
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bootstrap3',
'users',
'machines',
'cotisations',
'topologie',
'search',
'logs',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)
ROOT_URLCONF = 're2o.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates').replace('\\', '/'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 're2o.wsgi.application'
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'fr-fr'
TIME_ZONE = 'Europe/Paris'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# django-bootstrap3 config dictionnary
BOOTSTRAP3 = {
'jquery_url': '/static/js/jquery-2.2.4.min.js',
'base_url': '/static/bootstrap/',
'include_jquery': True,
}
BOOTSTRAP_BASE_URL = '/static/bootstrap/'
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',
),
)
STATIC_URL = '/static/'

View file

@ -0,0 +1,20 @@
SECRET_KEY = 'SUPER_SECRET'
DB_PASSWORD = 'SUPER_SECRET'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = []
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 're2o',
'USER': 're2o',
'PASSWORD': DB_PASSWORD,
'HOST': 'localhost',
}
}
ALLOWED_EXTENSIONS = ['.example']

View file

@ -24,5 +24,6 @@ urlpatterns = [
url(r'^search/', include('search.urls', namespace='search')), url(r'^search/', include('search.urls', namespace='search')),
url(r'^cotisations/', include('cotisations.urls', namespace='cotisations')), url(r'^cotisations/', include('cotisations.urls', namespace='cotisations')),
url(r'^machines/', include('machines.urls', namespace='machines')), url(r'^machines/', include('machines.urls', namespace='machines')),
url(r'^topologie/', include('topologie.urls', namespace='topologie')),
#url(r'^logs/', include('logs.urls', namespace='logs')), #url(r'^logs/', include('logs.urls', namespace='logs')),
] ]

View file

@ -3,9 +3,6 @@ from django import forms
from django.forms import Form from django.forms import Form
from django.forms import ModelForm from django.forms import ModelForm
from users.models import User
# Create your models here.
CHOICES = ( CHOICES = (
('0', 'Actifs'), ('0', 'Actifs'),
('1', 'Désactivés'), ('1', 'Désactivés'),

View file

@ -12,6 +12,7 @@ from machines.models import Machine, Interface
from cotisations.models import Facture from cotisations.models import Facture
from search.models import SearchForm, SearchFormPlus from search.models import SearchForm, SearchFormPlus
from users.views import has_access from users.views import has_access
from cotisations.views import end_adhesion
def form(ctx, template, request): def form(ctx, template, request):
c = ctx c = ctx
@ -23,7 +24,7 @@ def search_result(search, type):
date_fin = None date_fin = None
states=[] states=[]
co=[] co=[]
aff=[0,1,2,3,4] aff=['0','1','2','3','4']
if(type): if(type):
aff = search.cleaned_data['affichage'] aff = search.cleaned_data['affichage']
co = search.cleaned_data['connexion'] co = search.cleaned_data['connexion']
@ -32,7 +33,7 @@ def search_result(search, type):
date_fin = search.cleaned_data['date_fin'] date_fin = search.cleaned_data['date_fin']
date_query = Q() date_query = Q()
if aff==[]: if aff==[]:
aff = [0,1,2,3,4] aff = ['0','1','2','3','4']
if date_deb != None: if date_deb != None:
date_query = date_query & Q(date__gte=date_deb) date_query = date_query & Q(date__gte=date_deb)
if date_fin != None: if date_fin != None:
@ -54,9 +55,13 @@ def search_result(search, type):
users = User.objects.filter((Q(pseudo__icontains = search) | Q(name__icontains = search) | Q(surname__icontains = search)) & query) users = User.objects.filter((Q(pseudo__icontains = search) | Q(name__icontains = search) | Q(surname__icontains = search)) & query)
connexion = [] connexion = []
for user in users: for user in users:
end=end_adhesion(user)
access=has_access(user) access=has_access(user)
if(len(co)==0 or (len(co)==1 and bool(co[0])==access) or (len(co)==2 and (bool(co[0])==access or bool(co[1])==access))): if(len(co)==0 or (len(co)==1 and bool(co[0])==access) or (len(co)==2 and (bool(co[0])==access or bool(co[1])==access))):
connexion.append([user, access]) if(end!=None):
connexion.append([user, access, end])
else:
connexion.append([user, access, "Non adhérent"])
query = Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search) query = Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search)
if i == '1': if i == '1':
machines = Interface.objects.filter(machine=Machine.objects.filter(query)) | Interface.objects.filter(Q(dns__icontains = search)) machines = Interface.objects.filter(machine=Machine.objects.filter(query)) | Interface.objects.filter(Q(dns__icontains = search))

View file

@ -30,7 +30,7 @@
<li><a href="{% url "users:index" %}">Adhérents</a></li> <li><a href="{% url "users:index" %}">Adhérents</a></li>
<li><a href="{% url "machines:index" %}">Machines</a></li> <li><a href="{% url "machines:index" %}">Machines</a></li>
<li><a href="{% url "cotisations:index" %}">Cotisations</a></li> <li><a href="{% url "cotisations:index" %}">Cotisations</a></li>
<li><a href="#">Topologie</a></li> <li><a href="{% url "topologie:index" %}">Topologie</a></li>
<li><a href="#">Statistiques</a></li> <li><a href="#">Statistiques</a></li>
</ul> </ul>
<div class="col-sm-3 col-md-3 navbar-right"> <div class="col-sm-3 col-md-3 navbar-right">

View file

@ -7,7 +7,7 @@ class SwitchAdmin(admin.ModelAdmin):
list_display = ('building','number','details') list_display = ('building','number','details')
class PortAdmin(admin.ModelAdmin): class PortAdmin(admin.ModelAdmin):
list_display = ('switch', 'port','room','details') list_display = ('switch', 'port','room','machine_interface','details')
class RoomAdmin(admin.ModelAdmin): class RoomAdmin(admin.ModelAdmin):
list_display = ('name',) list_display = ('name',)

11
topologie/forms.py Normal file
View file

@ -0,0 +1,11 @@
from .models import Port
from django.forms import ModelForm, Form
class PortForm(ModelForm):
class Meta:
model = Port
fields = '__all__'
class EditPortForm(ModelForm):
class Meta(PortForm.Meta):
fields = ['room', 'machine_interface', 'related', 'details']

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('machines', '0014_auto_20160706_1220'),
('topologie', '0011_auto_20160704_2153'),
]
operations = [
migrations.AddField(
model_name='port',
name='machine_interface',
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, null=True, blank=True, to='machines.Interface'),
),
]

View file

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('topologie', '0012_port_machine_interface'),
]
operations = [
migrations.AddField(
model_name='port',
name='related',
field=models.OneToOneField(null=True, to='topologie.Port', blank=True, related_name='related_port'),
),
]

View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('topologie', '0013_port_related'),
]
operations = [
migrations.AlterUniqueTogether(
name='port',
unique_together=set([('switch', 'port')]),
),
migrations.RemoveField(
model_name='port',
name='_content_type',
),
migrations.RemoveField(
model_name='port',
name='_object_id',
),
]

View file

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('topologie', '0014_auto_20160706_1238'),
]
operations = [
migrations.RemoveField(
model_name='port',
name='related',
),
migrations.AddField(
model_name='port',
name='related',
field=models.ManyToManyField(related_name='_port_related_+', to='topologie.Port', blank=True),
),
]

View file

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('topologie', '0015_auto_20160706_1452'),
]
operations = [
migrations.RemoveField(
model_name='port',
name='related',
),
migrations.AddField(
model_name='port',
name='related',
field=models.OneToOneField(blank=True, to='topologie.Port', related_name='related_port', null=True),
),
]

View file

@ -1,7 +1,18 @@
from django.db import models from django.db import models
from django.forms import ModelForm, Form
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.core.exceptions import ValidationError
def make_port_related(port):
related_port = port.related
related_port.related = port
related_port.save()
def clean_port_related(port):
related_port = port.related_port
related_port.related = None
related_port.save()
class Switch(models.Model): class Switch(models.Model):
building = models.CharField(max_length=10) building = models.CharField(max_length=10)
@ -17,25 +28,26 @@ class Switch(models.Model):
class Port(models.Model): class Port(models.Model):
switch = models.ForeignKey(Switch, related_name="ports") switch = models.ForeignKey(Switch, related_name="ports")
port = models.IntegerField() port = models.IntegerField()
details = models.CharField(max_length=255, blank=True)
room = models.ForeignKey('Room', on_delete=models.PROTECT, blank=True, null=True) room = models.ForeignKey('Room', on_delete=models.PROTECT, blank=True, null=True)
# machine_interface = models.OneToOneField('machines.Interface', on_delete=models.PROTECT, blank=True, null=True) machine_interface = models.OneToOneField('machines.Interface', on_delete=models.PROTECT, blank=True, null=True)
related = models.OneToOneField('self', null=True, blank=True, related_name='related_port')
details = models.CharField(max_length=255, blank=True)
class Meta: class Meta:
unique_together = ('_content_type', '_object_id') unique_together = ('switch', 'port')
_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, blank=True, null=True) def clean(self):
_object_id = models.PositiveIntegerField(blank=True, null=True) if self.room and self.machine_interface or self.room and self.related or self.machine_interface and self.related:
goto = GenericForeignKey('_content_type', '_object_id') raise ValidationError("Chambre, interface et related_port sont mutuellement exclusifs")
if self.related==self:
@property raise ValidationError("On ne peut relier un port à lui même")
def comefrom(self): if self.related and not self.related.related:
ctype = ContentType.objects.get_for_model(self.__class__) if self.related.machine_interface or self.related.room:
try: raise ValidationError("Le port relié est déjà occupé, veuillez le libérer avant de créer une relation")
event = Port.objects.get(_content_type__pk=ctype.id, _object_id=self.id) else:
except: make_port_related(self)
return None elif hasattr(self, 'related_port'):
return event clean_port_related(self)
def __str__(self): def __str__(self):
return str(self.switch) + " - " + str(self.port) return str(self.switch) + " - " + str(self.port)

View file

@ -0,0 +1,23 @@
<h2>Switch {% if port_list.0 %}{{ port_list.0.switch }}{% endif %}</h2>
<table class="table table-striped">
<thead>
<tr>
<th>Port</th>
<th>Room</th>
<th>Interface machine</th>
<th>Related</th>
<th>Détails</th>
<th></th>
</tr>
</thead>
{% for port in port_list %}
<tr>
<td>{{ port.port }}</td>
<td>{{ port.room }}</td>
<td>{{ port.machine_interface }}</td>
<td>{{ port.related }}</td>
<td>{{ port.details }}</td>
<td><a class="btn btn-primary btn-sm" role="button" href="{% url 'topologie:edit-port' port.id %}"><i class="glyphicon glyphicon-random"></i> Editer</a></td>
</tr>
{% endfor %}
</table>

View file

@ -0,0 +1,18 @@
<table class="table table-striped">
<thead>
<tr>
<th>Bâtiment</th>
<th>Numero</th>
<th>Détails</th>
<th></th>
</tr>
</thead>
{% for switch in switch_list %}
<tr>
<td>{{switch.building}}</td>
<td>{{switch.number}}</td>
<td>{{switch.details}}</td>
<td><a class="btn btn-primary btn-sm" role="button" href="{% url 'topologie:index-port' switch.pk %}"><i class="glyphicon glyphicon-list-alt"></i> Editer</a></td>
</tr>
{% endfor %}
</table>

View file

@ -0,0 +1,11 @@
{% extends "topologie/sidebar.html" %}
{% load bootstrap3 %}
{% block title %}Switchs{% endblock %}
{% block content %}
{% include "topologie/aff_switch.html" with switch_list=switch_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -0,0 +1,11 @@
{% extends "topologie/sidebar.html" %}
{% load bootstrap3 %}
{% block title %}Ports du switch{% endblock %}
{% block content %}
{% include "topologie/aff_port.html" with port_list=port_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -0,0 +1,17 @@
{% extends "topologie/sidebar.html" %}
{% load bootstrap3 %}
{% block title %}Création et modificationd 'utilisateur{% endblock %}
{% block content %}
{% bootstrap_form_errors topoform %}
<form class="form" method="post">
{% csrf_token %}
{% bootstrap_form topoform %}
{%bootstrap_button "Créer ou modifier" button_type="submit" icon="ok" %}
</form>
<br />
<br />
<br />
{% endblock %}

View file

@ -0,0 +1,5 @@
{% extends "base.html" %}
{% block sidebar %}
<p><a href="{% url "topologie:index" %}">Liste des switchs</a></p>
{% endblock %}

10
topologie/urls.py Normal file
View file

@ -0,0 +1,10 @@
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^switch/(?P<switch_id>[0-9]+)$', views.index_port, name='index-port'),
url(r'^edit_port/(?P<port_id>[0-9]+)$', views.edit_port, name='edit-port'),
]

View file

@ -1,3 +1,35 @@
from django.shortcuts import render from django.shortcuts import render, redirect
from django.contrib import messages
# Create your views here.
from topologie.models import Switch, Port
from topologie.forms import EditPortForm
from users.views import form
def index(request):
switch_list = Switch.objects.order_by('building', 'number')
return render(request, 'topologie/index.html', {'switch_list': switch_list})
def index_port(request, switch_id):
try:
switch = Switch.objects.get(pk=switch_id)
except Switch.DoesNotExist:
messages.error(request, u"Switch inexistant")
return redirect("/topologie/")
port_list = Port.objects.filter(switch = switch).order_by('port')
return render(request, 'topologie/index_p.html', {'port_list':port_list})
def edit_port(request, port_id):
try:
port = Port.objects.get(pk=port_id)
except Port.DoesNotExist:
messages.error(request, u"Port inexistant")
return redirect("/topologie/")
port = EditPortForm(request.POST or None, instance=port)
if port.is_valid():
port.save()
messages.success(request, "Le port a bien été modifié")
return redirect("/topologie")
return form({'topoform':port}, 'topologie/port.html', request)

View file

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import users.models
class Migration(migrations.Migration):
dependencies = [
('users', '0015_whitelist'),
]
operations = [
migrations.AlterField(
model_name='ban',
name='date_end',
field=models.DateTimeField(help_text='%d/%m/%y %H:%M:%S'),
),
migrations.AlterField(
model_name='user',
name='pseudo',
field=models.CharField(unique=True, validators=[users.models.linux_user_validator], max_length=32, help_text='Doit contenir uniquement des lettres, chiffres, ou tirets'),
),
migrations.AlterField(
model_name='whitelist',
name='date_end',
field=models.DateTimeField(help_text='%d/%m/%y %H:%M:%S'),
),
]

View file

@ -1,6 +1,7 @@
from django.db import models from django.db import models
from django.forms import ModelForm, Form from django.forms import ModelForm, Form
from django import forms from django import forms
import re
from django.utils import timezone from django.utils import timezone
@ -15,6 +16,15 @@ def remove_user_room(room):
user.room = None user.room = None
user.save() user.save()
def linux_user_validator(login):
""" Validation du pseudo pour respecter les contraintes unix"""
UNIX_LOGIN_PATTERN = re.compile("^[a-z_][a-z0-9_-]*[$]?$")
if not UNIX_LOGIN_PATTERN.match(login):
raise forms.ValidationError(
", ce pseudo ('%(label)s') contient des carractères interdits",
params={'label': login},
)
class User(models.Model): class User(models.Model):
STATE_ACTIVE = 0 STATE_ACTIVE = 0
STATE_DEACTIVATED = 1 STATE_DEACTIVATED = 1
@ -27,9 +37,9 @@ class User(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
surname = models.CharField(max_length=255) surname = models.CharField(max_length=255)
pseudo = models.CharField(max_length=255, unique=True) pseudo = models.CharField(max_length=32, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator])
email = models.EmailField() email = models.EmailField()
school = models.ForeignKey('School', on_delete=models.PROTECT) school = models.ForeignKey('School', on_delete=models.PROTECT, null=False, blank=False)
comment = models.CharField(help_text="Commentaire, promo", max_length=255, blank=True) comment = models.CharField(help_text="Commentaire, promo", max_length=255, blank=True)
room = models.OneToOneField('topologie.Room', on_delete=models.PROTECT, blank=True, null=True) room = models.OneToOneField('topologie.Room', on_delete=models.PROTECT, blank=True, null=True)
pwd_ssha = models.CharField(max_length=255) pwd_ssha = models.CharField(max_length=255)
@ -66,7 +76,7 @@ class Ban(models.Model):
user = models.ForeignKey('User', on_delete=models.PROTECT) user = models.ForeignKey('User', on_delete=models.PROTECT)
raison = models.CharField(max_length=255) raison = models.CharField(max_length=255)
date_start = models.DateTimeField(auto_now_add=True) date_start = models.DateTimeField(auto_now_add=True)
date_end = models.DateTimeField(help_text='%m/%d/%y %H:%M:%S') date_end = models.DateTimeField(help_text='%d/%m/%y %H:%M:%S')
def __str__(self): def __str__(self):
return str(self.user) + ' ' + str(self.raison) return str(self.user) + ' ' + str(self.raison)
@ -75,24 +85,11 @@ class Whitelist(models.Model):
user = models.ForeignKey('User', on_delete=models.PROTECT) user = models.ForeignKey('User', on_delete=models.PROTECT)
raison = models.CharField(max_length=255) raison = models.CharField(max_length=255)
date_start = models.DateTimeField(auto_now_add=True) date_start = models.DateTimeField(auto_now_add=True)
date_end = models.DateTimeField(help_text='%m/%d/%y %H:%M:%S') date_end = models.DateTimeField(help_text='%d/%m/%y %H:%M:%S')
def __str__(self): def __str__(self):
return str(self.user) + ' ' + str(self.raison) return str(self.user) + ' ' + str(self.raison)
class UserForm(ModelForm):
def __init__(self, *args, **kwargs):
super(InfoForm, self).__init__(*args, **kwargs)
self.fields['name'].label = 'Nom'
self.fields['surname'].label = 'Prénom'
self.fields['school'].label = 'Établissement'
self.fields['comment'].label = 'Commentaire'
self.fields['room'].label = 'Chambre'
class Meta:
model = User
fields = '__all__'
class InfoForm(ModelForm): class InfoForm(ModelForm):
force = forms.BooleanField(label="Forcer le déménagement ?", initial=False, required=False) force = forms.BooleanField(label="Forcer le déménagement ?", initial=False, required=False)
@ -103,6 +100,8 @@ class InfoForm(ModelForm):
self.fields['school'].label = 'Établissement' self.fields['school'].label = 'Établissement'
self.fields['comment'].label = 'Commentaire' self.fields['comment'].label = 'Commentaire'
self.fields['room'].label = 'Chambre' self.fields['room'].label = 'Chambre'
self.fields['room'].empty_label = "Pas de chambre"
self.fields['school'].empty_label = "Séléctionner un établissement"
def clean_force(self): def clean_force(self):
if self.cleaned_data.get('force', False): if self.cleaned_data.get('force', False):
@ -113,6 +112,10 @@ class InfoForm(ModelForm):
model = User model = User
fields = ['name','surname','pseudo','email', 'school', 'comment', 'room'] fields = ['name','surname','pseudo','email', 'school', 'comment', 'room']
class UserForm(InfoForm):
class Meta(InfoForm.Meta):
fields = '__all__'
class PasswordForm(ModelForm): class PasswordForm(ModelForm):
class Meta: class Meta:
model = User model = User
@ -128,10 +131,22 @@ class SchoolForm(ModelForm):
model = School model = School
fields = ['name'] fields = ['name']
def __init__(self, *args, **kwargs):
super(SchoolForm, self).__init__(*args, **kwargs)
self.fields['name'].label = 'Établissement à ajouter'
class DelSchoolForm(ModelForm):
schools = forms.ModelMultipleChoiceField(queryset=School.objects.all(), label="Etablissements actuels", widget=forms.CheckboxSelectMultiple)
class Meta:
exclude = ['name']
model = School
class RightForm(ModelForm): class RightForm(ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(RightForm, self).__init__(*args, **kwargs) super(RightForm, self).__init__(*args, **kwargs)
self.fields['right'].label = 'Droit' self.fields['right'].label = 'Droit'
self.fields['right'].empty_label = "Choisir un nouveau droit"
class Meta: class Meta:
model = Right model = Right

View file

@ -14,7 +14,7 @@
<td>{{ ban.raison }}</td> <td>{{ ban.raison }}</td>
<td>{{ ban.date_start }}</td> <td>{{ ban.date_start }}</td>
<td>{{ ban.date_end }}</td> <td>{{ ban.date_end }}</td>
<td><a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-ban' ban.id %}"><i class="glyphicon glyphicon-grain"></i> Editer</a></td> <td><a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-ban' ban.id %}"><i class="glyphicon glyphicon-pushpin"></i> Editer</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View file

@ -4,7 +4,7 @@
<th>Prénom</th> <th>Prénom</th>
<th>Nom</th> <th>Nom</th>
<th>Pseudo</th> <th>Pseudo</th>
<th>Inscrit le</th> <th>Fin de cotisation le</th>
<th>Connexion</th> <th>Connexion</th>
<th>Profil</th> <th>Profil</th>
</tr> </tr>
@ -14,19 +14,15 @@
<td>{{ donnee.0.name }}</td> <td>{{ donnee.0.name }}</td>
<td>{{ donnee.0.surname }}</td> <td>{{ donnee.0.surname }}</td>
<td>{{ donnee.0.pseudo }}</td> <td>{{ donnee.0.pseudo }}</td>
<td>{{ donnee.0.registered }}</td> <td>{{ donnee.2 }}</td>
<td>{% if donnee.1 == True %} <td>{% if donnee.1 == True %}
<font color="green">Active</font> <font color="green">Active</font>
{% else %} {% else %}
<font color="red">Désactivée</font> <font color="red">Désactivée</font>
{% endif %} {% endif %}
</td> </td>
<td><form method="POST" action="{% url "users:profil"%}"> <td><a href="{% url "users:profil" donnee.0.id%}" class="btn btn-primary btn-sm" role="button"><i class="glyphicon glyphicon-user"></i></a>
{% csrf_token %} </td>
<input type="hidden" name="user" id="user" value="{{ donnee.0.pseudo }}"></input>
<button class="btn btn-primary btn-sm" type="submit"><i class="glyphicon glyphicon-tree-deciduous"></i></button>
</form>
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View file

@ -14,7 +14,7 @@
<td>{{ whitelist.raison }}</td> <td>{{ whitelist.raison }}</td>
<td>{{ whitelist.date_start }}</td> <td>{{ whitelist.date_start }}</td>
<td>{{ whitelist.date_end }}</td> <td>{{ whitelist.date_end }}</td>
<td><a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-whitelist' whitelist.id %}"><i class="glyphicon glyphicon-grain"></i> Editer</a></td> <td><a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-whitelist' whitelist.id %}"><i class="glyphicon glyphicon-flag"></i> Editer</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View file

@ -4,6 +4,7 @@
{% block title %}Utilisateurs{% endblock %} {% block title %}Utilisateurs{% endblock %}
{% block content %} {% block content %}
<h2>Adhérents</h2>
{% include "users/aff_users.html" with users_list=users_list %} {% include "users/aff_users.html" with users_list=users_list %}
<br /> <br />
<br /> <br />

View file

@ -0,0 +1,13 @@
{% extends "users/sidebar.html" %}
{% load bootstrap3 %}
{% block title %}Utilisateurs{% endblock %}
{% block content %}
<h2>Bannissements</h2>
{% include "users/aff_bans.html" with ban_list=ban_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -0,0 +1,13 @@
{% extends "users/sidebar.html" %}
{% load bootstrap3 %}
{% block title %}Utilisateurs{% endblock %}
{% block content %}
<h2>Accès à titre gracieux</h2>
{% include "users/aff_whitelists.html" with white_list=white_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -5,7 +5,7 @@
{% block content %} {% block content %}
<h2>Adhérent</h2> <h2>Adhérent</h2>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-info' user.id %}"><i class="glyphicon glyphicon-fire"></i> Editer</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-info' user.id %}"><i class="glyphicon glyphicon-edit"></i> Editer</a>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:password' user.id %}"><i class="glyphicon glyphicon-lock"></i> Changer le mot de passe</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'users:password' user.id %}"><i class="glyphicon glyphicon-lock"></i> Changer le mot de passe</a>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:state' user.id %}"><i class="glyphicon glyphicon-flash"></i> Changer le statut</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'users:state' user.id %}"><i class="glyphicon glyphicon-flash"></i> Changer le statut</a>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-right' user.id %}"><i class="glyphicon glyphicon-ok"></i> Ajouter un droit</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-right' user.id %}"><i class="glyphicon glyphicon-ok"></i> Ajouter un droit</a>
@ -74,7 +74,7 @@
{% endif %} {% endif %}
<th>Droits</th> <th>Droits</th>
{% if list_droits %} {% if list_droits %}
<td>{% for droit in list_droits %}{{ droit.right }} - {% endfor %}</td> <td>{% for droit in list_droits %}{{ droit.right }}{% if list_droits|length != forloop.counter %} - {% endif %} {% endfor %}</td>
{% else %} {% else %}
<td>Aucun</td> <td>Aucun</td>
{% endif %} {% endif %}
@ -101,7 +101,7 @@
<p>Aucun bannissement</p> <p>Aucun bannissement</p>
{% endif %} {% endif %}
<h2>Accès à titre gracieux :</h2> <h2>Accès à titre gracieux :</h2>
<h4><a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-whitelist' user.id %}"><i class="glyphicon glyphicon-pushpin"></i> Accorder un accès à titre gracieux</a></h4> <h4><a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-whitelist' user.id %}"><i class="glyphicon glyphicon-flag"></i> Accorder un accès à titre gracieux</a></h4>
{% if white_list %} {% if white_list %}
{% include "users/aff_whitelists.html" with white_list=white_list %} {% include "users/aff_whitelists.html" with white_list=white_list %}
{% else %} {% else %}

View file

@ -2,9 +2,10 @@
{% block sidebar %} {% block sidebar %}
<p><a href="{% url "users:new-user" %}">Créer un adhérent</a></p> <p><a href="{% url "users:new-user" %}">Créer un adhérent</a></p>
<p><a href="{% url "search:search" %}">Editer un adhérent</a></p>
<p><a href="{% url "users:index" %}">Liste des adhérents</a></p> <p><a href="{% url "users:index" %}">Liste des adhérents</a></p>
<p><a href="{% url "search:search" %}">Ajouter un bannissement</a></p> <p><a href="{% url "users:index-ban" %}">Liste des bannissements</a></p>
<p><a href="{% url "search:search" %}">Gérer les bannissements</a></p> <p><a href="{% url "users:index-white" %}">Liste des accès à titre gracieux</a></p>
<p><a href="{% url "users:add-school" %}">Ajouter un établissement</a></p>
<p><a href="{% url "users:del-school" %}">Supprimer un établissement</a></p>
<p><a href="{% url "users:del-right" %}">Retirer un droit rezo</a></p> <p><a href="{% url "users:del-right" %}">Retirer un droit rezo</a></p>
{% endblock %} {% endblock %}

View file

@ -13,7 +13,11 @@ urlpatterns = [
url(r'^edit_whitelist/(?P<whitelistid>[0-9]+)$', views.edit_whitelist, name='edit-whitelist'), url(r'^edit_whitelist/(?P<whitelistid>[0-9]+)$', views.edit_whitelist, name='edit-whitelist'),
url(r'^add_right/(?P<userid>[0-9]+)$', views.add_right, name='add-right'), url(r'^add_right/(?P<userid>[0-9]+)$', views.add_right, name='add-right'),
url(r'^del_right/$', views.del_right, name='del-right'), url(r'^del_right/$', views.del_right, name='del-right'),
url(r'^profil/$', views.profil, name='profil'), url(r'^add_school/$', views.add_school, name='add-school'),
url(r'^del_school/$', views.del_school, name='del-school'),
url(r'^profil/(?P<userid>[0-9]+)$', views.profil, name='profil'),
url(r'^index_ban/$', views.index_ban, name='index-ban'),
url(r'^index_white/$', views.index_white, name='index-white'),
url(r'^$', views.index, name='index'), url(r'^$', views.index, name='index'),
] ]

View file

@ -6,11 +6,11 @@ from django.shortcuts import render_to_response, get_object_or_404
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.template import Context, RequestContext, loader from django.template import Context, RequestContext, loader
from django.contrib import messages from django.contrib import messages
from django.db.models import Max from django.db.models import Max, ProtectedError
from django.db import IntegrityError from django.db import IntegrityError
from django.utils import timezone from django.utils import timezone
from users.models import User, Right, Ban, DelRightForm, UserForm, InfoForm, PasswordForm, StateForm, RightForm, BanForm, ProfilForm, Whitelist, WhitelistForm from users.models import User, Right, Ban, DelRightForm, UserForm, InfoForm, PasswordForm, StateForm, RightForm, BanForm, ProfilForm, Whitelist, WhitelistForm, DelSchoolForm, SchoolForm
from cotisations.models import Facture from cotisations.models import Facture
from machines.models import Machine, Interface from machines.models import Machine, Interface
from users.forms import PassForm from users.forms import PassForm
@ -62,10 +62,13 @@ def is_whitelisted(user):
def has_access(user): def has_access(user):
""" Renvoie si un utilisateur a accès à internet""" """ Renvoie si un utilisateur a accès à internet"""
if user.state == User.STATE_ACTIVE and not is_ban(user) and ( is_adherent(user) or is_whitelisted(user)): return user.state == User.STATE_ACTIVE and not is_ban(user) and ( is_adherent(user) or is_whitelisted(user))
return True
else: def is_active(interface):
return False """ Renvoie si une interface doit avoir accès ou non """
machine = interface.machine
user = machine.user
return machine.active and has_access(user)
def form(ctx, template, request): def form(ctx, template, request):
c = ctx c = ctx
@ -214,31 +217,63 @@ def edit_whitelist(request, whitelistid):
return redirect("/users/") return redirect("/users/")
return form({'userform': whitelist}, 'users/user.html', request) return form({'userform': whitelist}, 'users/user.html', request)
def add_school(request):
school = SchoolForm(request.POST or None)
if school.is_valid():
school.save()
messages.success(request, "L'établissement a été ajouté")
return redirect("/users/")
return form({'userform': school}, 'users/user.html', request)
def del_school(request):
school = DelSchoolForm(request.POST or None)
if school.is_valid():
school_dels = school.cleaned_data['schools']
for school_del in school_dels:
try:
school_del.delete()
messages.success(request, "L'établissement a été supprimé")
except ProtectedError:
messages.error(request, "L'établissement %s est affecté à au moins un user, vous ne pouvez pas le supprimer" % school_del)
return redirect("/users/")
return form({'userform': school}, 'users/user.html', request)
def index(request): def index(request):
users_list = User.objects.order_by('pk') users_list = User.objects.order_by('pk')
connexion = [] connexion = []
for user in users_list: for user in users_list:
connexion.append([user, has_access(user)]) end = end_adhesion(user)
access = has_access(user)
if(end!=None):
connexion.append([user, access, end])
else:
connexion.append([user, access, "Non adhérent"])
return render(request, 'users/index.html', {'users_list': connexion}) return render(request, 'users/index.html', {'users_list': connexion})
def profil(request): def index_ban(request):
if request.method == 'POST': ban_list = Ban.objects.order_by('date_start')
profil = ProfilForm(request.POST or None) return render(request, 'users/index_ban.html', {'ban_list':ban_list})
if profil.is_valid():
profils = profil.cleaned_data['user'] def index_white(request):
users = User.objects.get(pseudo = profils) white_list = Whitelist.objects.order_by('date_start')
machines = Interface.objects.filter(machine=Machine.objects.filter(user__pseudo = users)) return render(request, 'users/index_whitelist.html', {'white_list':white_list})
factures = Facture.objects.filter(user__pseudo = users)
bans = Ban.objects.filter(user__pseudo = users) def profil(request, userid):
whitelists = Whitelist.objects.filter(user__pseudo = users) try:
end_bans = None users = User.objects.get(pk=userid)
end_whitelists = None except User.DoesNotExist:
if(is_ban(users)): messages.error(request, u"Utilisateur inexistant" )
end_bans=end_ban(users) return redirect("/users/")
if(is_whitelisted(users)): machines = Interface.objects.filter(machine=Machine.objects.filter(user__pseudo = users))
end_whitelists=end_whitelist(users) factures = Facture.objects.filter(user__pseudo = users)
list_droits = Right.objects.filter(user=users) bans = Ban.objects.filter(user__pseudo = users)
return render(request, 'users/profil.html', {'user': users, 'machine_list' :machines, 'facture_list':factures, 'ban_list':bans, 'white_list':whitelists,'end_ban':end_bans,'end_whitelist':end_whitelists, 'end_adhesion':end_adhesion(users), 'actif':has_access(users), 'list_droits': list_droits}) whitelists = Whitelist.objects.filter(user__pseudo = users)
return redirect("/users/") end_bans = None
return redirect("/users/") end_whitelists = None
if(is_ban(users)):
end_bans=end_ban(users)
if(is_whitelisted(users)):
end_whitelists=end_whitelist(users)
list_droits = Right.objects.filter(user=users)
return render(request, 'users/profil.html', {'user': users, 'machine_list' :machines, 'facture_list':factures, 'ban_list':bans, 'white_list':whitelists,'end_ban':end_bans,'end_whitelist':end_whitelists, 'end_adhesion':end_adhesion(users), 'actif':has_access(users), 'list_droits': list_droits})