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

Gestion, affichage des clubs, gestion de la recherche

This commit is contained in:
chirac 2017-10-23 05:02:55 +02:00
parent 054016a1d1
commit 3638c67f3a
9 changed files with 283 additions and 30 deletions

View file

@ -74,20 +74,20 @@ def search_result(search, type, request):
recherche = {'users_list': None, 'machines_list' : [], 'facture_list' : None, 'ban_list' : None, 'white_list': None, 'port_list': None, 'switch_list': None} recherche = {'users_list': None, 'machines_list' : [], 'facture_list' : None, 'ban_list' : None, 'white_list': None, 'port_list': None, 'switch_list': None}
if request.user.has_perms(('cableur',)): if request.user.has_perms(('cableur',)):
query = Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search) query = Q(user__pseudo__icontains = search) | Q(user__adherent__name__icontains = search) | Q(user__surname__icontains = search)
else: else:
query = (Q(user__pseudo__icontains = search) | Q(user__name__icontains = search) | Q(user__surname__icontains = search)) & Q(user = request.user) query = (Q(user__pseudo__icontains = search) | Q(user__adherent__name__icontains = search) | Q(user__surname__icontains = search)) & Q(user = request.user)
for i in aff: for i in aff:
if i == '0': if i == '0':
query_user_list = Q(room__name__icontains = search) | Q(pseudo__icontains = search) | Q(name__icontains = search) | Q(surname__icontains = search) & query1 query_user_list = Q(room__name__icontains = search) | Q(pseudo__icontains = search) | Q(adherent__name__icontains = search) | Q(surname__icontains = search) & query1
if request.user.has_perms(('cableur',)): if request.user.has_perms(('cableur',)):
recherche['users_list'] = User.objects.filter(query_user_list).order_by('state', 'surname').distinct() recherche['users_list'] = User.objects.filter(query_user_list).order_by('state', 'surname').distinct()
else : else :
recherche['users_list'] = User.objects.filter(query_user_list & Q(id=request.user.id)).order_by('state', 'surname').distinct() recherche['users_list'] = User.objects.filter(query_user_list & Q(id=request.user.id)).order_by('state', 'surname').distinct()
if i == '1': if i == '1':
query_machine_list = Q(machine__user__pseudo__icontains = search) | Q(machine__user__name__icontains = search) | Q(machine__user__surname__icontains = search) | Q(mac_address__icontains = search) | Q(ipv4__ipv4__icontains = search) | Q(domain__name__icontains = search) | Q(domain__related_domain__name__icontains = search) query_machine_list = Q(machine__user__pseudo__icontains = search) | Q(machine__user__adherent__name__icontains = search) | Q(machine__user__surname__icontains = search) | Q(mac_address__icontains = search) | Q(ipv4__ipv4__icontains = search) | Q(domain__name__icontains = search) | Q(domain__related_domain__name__icontains = search)
if request.user.has_perms(('cableur',)): if request.user.has_perms(('cableur',)):
data = Interface.objects.filter(query_machine_list).distinct() data = Interface.objects.filter(query_machine_list).distinct()
else: else:

View file

@ -99,7 +99,7 @@ class UserCreationForm(forms.ModelForm):
super(UserCreationForm, self).__init__(*args, prefix=prefix, **kwargs) super(UserCreationForm, self).__init__(*args, prefix=prefix, **kwargs)
class Meta: class Meta:
model = User model = Adherent
fields = ('pseudo', 'surname', 'email') fields = ('pseudo', 'surname', 'email')
def clean_password2(self): def clean_password2(self):
@ -179,7 +179,7 @@ class UserChangeForm(forms.ModelForm):
is_admin = forms.BooleanField(label='is admin', required=False) is_admin = forms.BooleanField(label='is admin', required=False)
class Meta: class Meta:
model = User model = Adherent
fields = ('pseudo', 'password', 'surname', 'email') fields = ('pseudo', 'password', 'surname', 'email')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -252,13 +252,13 @@ class MassArchiveForm(forms.Form):
utilisateurs dont la fin d'accès se situe dans le futur !") utilisateurs dont la fin d'accès se situe dans le futur !")
class BaseInfoForm(ModelForm): class NewUserForm(ModelForm):
"""Formulaire de base d'edition d'un user. Formulaire de base, utilisé """Formulaire de base d'edition d'un user. Formulaire de base, utilisé
pour l'edition de self par self ou un cableur. On formate les champs pour l'edition de self par self ou un cableur. On formate les champs
avec des label plus jolis""" avec des label plus jolis"""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__) prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(BaseInfoForm, self).__init__(*args, prefix=prefix, **kwargs) super(NewUserForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['name'].label = 'Prénom' self.fields['name'].label = 'Prénom'
self.fields['surname'].label = 'Nom' self.fields['surname'].label = 'Nom'
self.fields['school'].label = 'Établissement' self.fields['school'].label = 'Établissement'
@ -292,13 +292,89 @@ class BaseInfoForm(ModelForm):
return telephone return telephone
class NewClubForm(ModelForm):
"""Formulaire de base d'edition d'un user. Formulaire de base, utilisé
pour l'edition de self par self ou un cableur. On formate les champs
avec des label plus jolis"""
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(NewClubForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['surname'].label = 'Nom'
self.fields['school'].label = 'Établissement'
self.fields['comment'].label = 'Commentaire'
self.fields['room'].label = 'Chambre'
self.fields['room'].empty_label = "Pas de chambre"
self.fields['school'].empty_label = "Séléctionner un établissement"
class Meta:
model = Club
fields = [
'surname',
'pseudo',
'email',
'school',
'comment',
'room',
'telephone',
]
def clean_telephone(self):
"""Verifie que le tel est présent si 'option est validée
dans preferences"""
telephone = self.cleaned_data['telephone']
preferences, _created = OptionalUser.objects.get_or_create()
if not telephone and preferences.is_tel_mandatory:
raise forms.ValidationError(
"Un numéro de téléphone valide est requis"
)
return telephone
class BaseInfoForm(ModelForm):
"""Formulaire de base d'edition d'un user. Formulaire de base, utilisé
pour l'edition de self par self ou un cableur. On formate les champs
avec des label plus jolis"""
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(BaseInfoForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['surname'].label = 'Nom'
self.fields['school'].label = 'Établissement'
self.fields['comment'].label = 'Commentaire'
self.fields['room'].label = 'Chambre'
self.fields['room'].empty_label = "Pas de chambre"
self.fields['school'].empty_label = "Séléctionner un établissement"
class Meta:
model = User
fields = [
'surname',
'pseudo',
'email',
'school',
'comment',
'room',
'telephone',
]
def clean_telephone(self):
"""Verifie que le tel est présent si 'option est validée
dans preferences"""
telephone = self.cleaned_data['telephone']
preferences, _created = OptionalUser.objects.get_or_create()
if not telephone and preferences.is_tel_mandatory:
raise forms.ValidationError(
"Un numéro de téléphone valide est requis"
)
return telephone
class EditInfoForm(BaseInfoForm): class EditInfoForm(BaseInfoForm):
"""Edition complète d'un user. Utilisé par admin, """Edition complète d'un user. Utilisé par admin,
permet d'editer normalement la chambre, ou le shell permet d'editer normalement la chambre, ou le shell
Herite de la base""" Herite de la base"""
class Meta(BaseInfoForm.Meta): class Meta(BaseInfoForm.Meta):
fields = [ fields = [
'name',
'surname', 'surname',
'pseudo', 'pseudo',
'email', 'email',

View file

@ -149,7 +149,6 @@ class UserManager(BaseUserManager):
def _create_user( def _create_user(
self, self,
pseudo, pseudo,
name,
surname, surname,
email, email,
password=None, password=None,
@ -163,7 +162,6 @@ class UserManager(BaseUserManager):
user = self.model( user = self.model(
pseudo=pseudo, pseudo=pseudo,
name=name,
surname=surname, surname=surname,
email=self.normalize_email(email), email=self.normalize_email(email),
) )
@ -174,19 +172,19 @@ class UserManager(BaseUserManager):
user.make_admin() user.make_admin()
return user return user
def create_user(self, pseudo, name, surname, email, password=None): def create_user(self, pseudo, surname, email, password=None):
""" """
Creates and saves a User with the given pseudo, name, surname, email, Creates and saves a User with the given pseudo, name, surname, email,
and password. and password.
""" """
return self._create_user(pseudo, name, surname, email, password, False) return self._create_user(pseudo, surname, email, password, False)
def create_superuser(self, pseudo, name, surname, email, password): def create_superuser(self, pseudo, surname, email, password):
""" """
Creates and saves a superuser with the given pseudo, name, surname, Creates and saves a superuser with the given pseudo, name, surname,
email, and password. email, and password.
""" """
return self._create_user(pseudo, name, surname, email, password, True) return self._create_user(pseudo, surname, email, password, True)
class User(AbstractBaseUser): class User(AbstractBaseUser):
@ -246,10 +244,36 @@ class User(AbstractBaseUser):
rezo_rez_uid = models.PositiveIntegerField(unique=True, blank=True, null=True) rezo_rez_uid = models.PositiveIntegerField(unique=True, blank=True, null=True)
USERNAME_FIELD = 'pseudo' USERNAME_FIELD = 'pseudo'
REQUIRED_FIELDS = ['name', 'surname', 'email'] REQUIRED_FIELDS = ['surname', 'email']
objects = UserManager() objects = UserManager()
@cached_property
def name(self):
"""Si il s'agit d'un adhérent, on renvoie le prénom"""
if self.is_class_adherent:
return self.adherent.name
else:
return ''
@cached_property
def class_name(self):
"""Renvoie si il s'agit d'un adhérent ou d'un club"""
if hasattr(self, 'adherent'):
return "Adhérent"
elif hasattr(self, 'club'):
return "Club"
else:
raise NotImplementedError("Type inconnu")
@cached_property
def is_class_club(self):
return hasattr(self, 'club')
@cached_property
def is_class_adherent(self):
return hasattr(self, 'adherent')
@property @property
def is_active(self): def is_active(self):
""" Renvoie si l'user est à l'état actif""" """ Renvoie si l'user est à l'état actif"""
@ -280,11 +304,15 @@ class User(AbstractBaseUser):
def get_full_name(self): def get_full_name(self):
""" Renvoie le nom complet de l'user formaté nom/prénom""" """ Renvoie le nom complet de l'user formaté nom/prénom"""
return '%s %s' % (self.name, self.surname) name = self.name
if name:
return '%s %s' % (name, self.surname)
else:
return self.surname
def get_short_name(self): def get_short_name(self):
""" Renvoie seulement le nom""" """ Renvoie seulement le nom"""
return self.name return self.surname
def has_perms(self, perms, obj=None): def has_perms(self, perms, obj=None):
""" Renvoie true si l'user dispose de la permission. """ Renvoie true si l'user dispose de la permission.
@ -570,7 +598,7 @@ class User(AbstractBaseUser):
.objects.get_or_create() .objects.get_or_create()
general_options, _created = GeneralOption.objects.get_or_create() general_options, _created = GeneralOption.objects.get_or_create()
context = Context({ context = Context({
'nom': str(self.name) + ' ' + str(self.surname), 'nom': self.get_full_name(),
'asso_name': assooptions.name, 'asso_name': assooptions.name,
'asso_email': assooptions.contact, 'asso_email': assooptions.contact,
'welcome_mail_fr': mailmessageoptions.welcome_mail_fr, 'welcome_mail_fr': mailmessageoptions.welcome_mail_fr,
@ -599,7 +627,7 @@ class User(AbstractBaseUser):
options, _created = AssoOption.objects.get_or_create() options, _created = AssoOption.objects.get_or_create()
general_options, _created = GeneralOption.objects.get_or_create() general_options, _created = GeneralOption.objects.get_or_create()
context = { context = {
'name': str(req.user.name) + ' ' + str(req.user.surname), 'name': req.user.get_full_name(),
'asso': options.name, 'asso': options.name,
'asso_mail': options.contact, 'asso_mail': options.contact,
'site_name': general_options.site_name, 'site_name': general_options.site_name,
@ -929,7 +957,7 @@ class Ban(models.Model):
template = loader.get_template('users/email_ban_notif') template = loader.get_template('users/email_ban_notif')
options, _created = AssoOption.objects.get_or_create() options, _created = AssoOption.objects.get_or_create()
context = Context({ context = Context({
'name': str(self.user.name) + ' ' + str(self.user.surname), 'name': self.user.get_full_name(),
'raison': self.raison, 'raison': self.raison,
'date_end': self.date_end, 'date_end': self.date_end,
'asso_name': options.name, 'asso_name': options.name,

View file

@ -0,0 +1,57 @@
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
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.
{% endcomment %}
{% if clubs_list.paginator %}
{% include "pagination.html" with list=clubs_list %}
{% endif %}
<table class="table table-striped">
<thead>
<tr>
<th>{% include "buttons/sort.html" with prefix='club' col="surname" text="Nom" %}</th>
<th>{% include "buttons/sort.html" with prefix='club' col="pseudo" text="Pseudo" %}</th>
<th>{% include "buttons/sort.html" with prefix='club' col="room" text="Chambre" %}</th>
<th>Fin de cotisation le</th>
<th>Connexion</th>
<th>Profil</th>
</tr>
</thead>
{% for club in clubs_list %}
<tr>
<td>{{ club.surname }}</td>
<td>{{ club.pseudo }}</td>
<td>{{ club.room }}</td>
<td>{% if club.is_adherent %}{{ club.end_adhesion }}{% else %}Non adhérent{% endif %}</td>
<td>{% if club.has_access == True %}
<font color="green">Active</font>
{% else %}
<font color="red">Désactivée</font>
{% endif %}
</td>
<td><a href="{% url "users:profil" club.id%}" class="btn btn-primary btn-sm" role="button"><i class="glyphicon glyphicon-user"></i></a>
</td>
</tr>
{% endfor %}
</table>

View file

@ -0,0 +1,37 @@
{% extends "users/sidebar.html" %}
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
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.
{% endcomment %}
{% load bootstrap3 %}
{% block title %}Utilisateurs{% endblock %}
{% block content %}
<h2>Clubs</h2>
{% include "users/aff_clubs.html" with clubs_list=clubs_list %}
<br />
<br />
<br />
{% endblock %}

View file

@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% block title %}Profil{% endblock %} {% block title %}Profil{% endblock %}
{% block content %} {% block content %}
<h2>Adhérent</h2> <h2>{{ user.class_name }}</h2>
<div> <div>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-info' user.id %}"> <a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-info' user.id %}">
<i class="glyphicon glyphicon-edit"></i> <i class="glyphicon glyphicon-edit"></i>

View file

@ -30,9 +30,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<i class="glyphicon glyphicon-plus"></i> <i class="glyphicon glyphicon-plus"></i>
Créer un adhérent Créer un adhérent
</a> </a>
<a class="list-group-item list-group-item-success" href="{% url "users:new-club" %}">
<i class="glyphicon glyphicon-plus"></i>
Créer un club/association
</a>
<a class="list-group-item list-group-item-info" href="{% url "users:index" %}"> <a class="list-group-item list-group-item-info" href="{% url "users:index" %}">
<i class="glyphicon glyphicon-list"></i> <i class="glyphicon glyphicon-list"></i>
Adhérents Adherents
</a>
<a class="list-group-item list-group-item-info" href="{% url "users:index-clubs" %}">
<i class="glyphicon glyphicon-list"></i>
Clubs
</a> </a>
<a class="list-group-item list-group-item-info" href="{% url "users:index-ban" %}"> <a class="list-group-item list-group-item-info" href="{% url "users:index-ban" %}">
<i class="glyphicon glyphicon-list"></i> <i class="glyphicon glyphicon-list"></i>

View file

@ -31,6 +31,7 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^new_user/$', views.new_user, name='new-user'), url(r'^new_user/$', views.new_user, name='new-user'),
url(r'^new_club/$', views.new_club, name='new-club'),
url(r'^edit_info/(?P<userid>[0-9]+)$', views.edit_info, name='edit-info'), url(r'^edit_info/(?P<userid>[0-9]+)$', views.edit_info, name='edit-info'),
url(r'^state/(?P<userid>[0-9]+)$', views.state, name='state'), url(r'^state/(?P<userid>[0-9]+)$', views.state, name='state'),
url(r'^password/(?P<userid>[0-9]+)$', views.password, name='password'), url(r'^password/(?P<userid>[0-9]+)$', views.password, name='password'),
@ -118,5 +119,6 @@ urlpatterns = [
name='history' name='history'
), ),
url(r'^$', views.index, name='index'), url(r'^$', views.index, name='index'),
url(r'^index_clubs/$', views.index_clubs, name='index-clubs'),
url(r'^rest/mailing/$', views.mailing, name='mailing'), url(r'^rest/mailing/$', views.mailing, name='mailing'),
] ]

View file

@ -58,7 +58,7 @@ from users.forms import DelRightForm, BanForm, WhitelistForm, DelSchoolForm
from users.forms import DelListRightForm, NewListRightForm from users.forms import DelListRightForm, NewListRightForm
from users.forms import InfoForm, BaseInfoForm, StateForm from users.forms import InfoForm, BaseInfoForm, StateForm
from users.forms import RightForm, SchoolForm, EditServiceUserForm from users.forms import RightForm, SchoolForm, EditServiceUserForm
from users.forms import ServiceUserForm, ListRightForm from users.forms import ServiceUserForm, ListRightForm, NewUserForm, NewClubForm
from users.forms import MassArchiveForm, PassForm, ResetPasswordForm from users.forms import MassArchiveForm, PassForm, ResetPasswordForm
from cotisations.models import Facture from cotisations.models import Facture
from machines.models import Machine from machines.models import Machine
@ -85,7 +85,7 @@ def password_change_action(u_form, user, request, req=False):
def new_user(request): def new_user(request):
""" Vue de création d'un nouvel utilisateur, """ Vue de création d'un nouvel utilisateur,
envoie un mail pour le mot de passe""" envoie un mail pour le mot de passe"""
user = InfoForm(request.POST or None) user = NewUserForm(request.POST or None)
if user.is_valid(): if user.is_valid():
user = user.save(commit=False) user = user.save(commit=False)
with transaction.atomic(), reversion.create_revision(): with transaction.atomic(), reversion.create_revision():
@ -99,6 +99,25 @@ def new_user(request):
return form({'userform': user}, 'users/user.html', request) return form({'userform': user}, 'users/user.html', request)
@login_required
@permission_required('cableur')
def new_club(request):
""" Vue de création d'un nouveau club,
envoie un mail pour le mot de passe"""
club = NewClubForm(request.POST or None)
if club.is_valid():
club = club.save(commit=False)
with transaction.atomic(), reversion.create_revision():
club.save()
reversion.set_user(request.user)
reversion.set_comment("Création")
club.reset_passwd_mail(request)
messages.success(request, "L'utilisateur %s a été crée, un mail\
pour l'initialisation du mot de passe a été envoyé" % club.pseudo)
return redirect("/users/profil/" + str(club.id))
return form({'userform': club}, 'users/user.html', request)
@login_required @login_required
def edit_info(request, userid): def edit_info(request, userid):
""" Edite un utilisateur à partir de son id, """ Edite un utilisateur à partir de son id,
@ -572,10 +591,10 @@ def mass_archive(request):
@login_required @login_required
@permission_required('cableur') @permission_required('cableur')
def index(request): def index(request):
""" Affiche l'ensemble des users, need droit cableur """ """ Affiche l'ensemble des adherents, need droit cableur """
options, _created = GeneralOption.objects.get_or_create() options, _created = GeneralOption.objects.get_or_create()
pagination_number = options.pagination_number pagination_number = options.pagination_number
users_list = User.objects.select_related('room') users_list = Adherent.objects.select_related('room')
users_list = SortTable.sort( users_list = SortTable.sort(
users_list, users_list,
request.GET.get('col'), request.GET.get('col'),
@ -595,6 +614,32 @@ def index(request):
return render(request, 'users/index.html', {'users_list': users_list}) return render(request, 'users/index.html', {'users_list': users_list})
@login_required
@permission_required('cableur')
def index_clubs(request):
""" Affiche l'ensemble des clubs, need droit cableur """
options, _created = GeneralOption.objects.get_or_create()
pagination_number = options.pagination_number
clubs_list = Club.objects.select_related('room')
clubs_list = SortTable.sort(
clubs_list,
request.GET.get('col'),
request.GET.get('order'),
SortTable.USERS_INDEX
)
paginator = Paginator(clubs_list, pagination_number)
page = request.GET.get('page')
try:
clubs_list = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
clubs_list = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
clubs_list = paginator.page(paginator.num_pages)
return render(request, 'users/index_clubs.html', {'clubs_list': clubs_list})
@login_required @login_required
@permission_required('cableur') @permission_required('cableur')
def index_ban(request): def index_ban(request):