8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-25 16:33:47 +00:00

Merge branch 'asso_users' into 'master'

Asso users

See merge request federez/re2o!41
This commit is contained in:
Gabriel Detraz 2017-11-24 19:43:26 +01:00
commit 4ac51db31a
11 changed files with 249 additions and 39 deletions

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-11-21 04:42
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('preferences', '0023_auto_20171015_2033'),
]
operations = [
migrations.AddField(
model_name='optionaluser',
name='all_can_create',
field=models.BooleanField(default=False, help_text="Tous les users peuvent en créer d'autres"),
),
]

View file

@ -42,6 +42,10 @@ class OptionalUser(models.Model):
default=0 default=0
) )
gpg_fingerprint = models.BooleanField(default=True) gpg_fingerprint = models.BooleanField(default=True)
all_can_create = models.BooleanField(
default=False,
help_text="Tous les users peuvent en créer d'autres",
)
def clean(self): def clean(self):
"""Creation du mode de paiement par solde""" """Creation du mode de paiement par solde"""

View file

@ -52,6 +52,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td>{{ useroptions.solde_negatif }}</td> <td>{{ useroptions.solde_negatif }}</td>
{% endif %} {% endif %}
</tr> </tr>
<tr>
<th>Creations d'users par tous</th>
<td>{{ useroptions.all_can_create }}</td>
</tr>
</table> </table>
<h4>Préférences machines</h4> <h4>Préférences machines</h4>
{% if is_bureau %} {% if is_bureau %}

View file

@ -379,6 +379,18 @@ class FullClubForm(ClubForm):
] ]
class ClubAdminandMembersForm(ModelForm):
"""Permet d'éditer la liste des membres et des administrateurs
d'un club"""
class Meta:
model = Club
fields = ['administrators', 'members']
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(ClubAdminandMembersForm, self).__init__(*args, prefix=prefix, **kwargs)
class PasswordForm(ModelForm): class PasswordForm(ModelForm):
""" Formulaire de changement brut de mot de passe. """ Formulaire de changement brut de mot de passe.
Ne pas utiliser sans traitement""" Ne pas utiliser sans traitement"""

View file

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-11-20 02:17
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0059_auto_20171025_1854'),
]
operations = [
migrations.AddField(
model_name='club',
name='administrators',
field=models.ManyToManyField(blank=True, related_name='club_administrator', to='users.Adherent'),
),
migrations.AddField(
model_name='club',
name='members',
field=models.ManyToManyField(blank=True, related_name='club_members', to='users.Adherent'),
),
]

View file

@ -60,7 +60,10 @@ from django.core.mail import send_mail
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import transaction from django.db import transaction
from django.utils import timezone from django.utils import timezone
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager
)
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from reversion import revisions as reversion from reversion import revisions as reversion
@ -755,6 +758,28 @@ class User(AbstractBaseUser):
num += 1 num += 1
return composed_pseudo(num) return composed_pseudo(num)
def can_create(user):
options, _created = OptionalUser.objects.get_or_create()
if options.all_can_create:
return True
else:
return user.has_perms(('cableur',))
def can_edit(self, user):
if self.is_class_club and user.is_class_adherent:
return self == user or user.has_perms(('cableur',)) or\
user.adherent in self.club.administrators.all()
else:
return self == user or user.has_perms(('cableur',))
def can_view(self, user):
if self.is_class_club and user.is_class_adherent:
return self == user or user.has_perms(('cableur',)) or\
user.adherent in self.club.administrators.all() or\
user.adherent in self.club.members.all()
else:
return self == user or user.has_perms(('cableur',))
def __str__(self): def __str__(self):
return self.pseudo return self.pseudo
@ -771,6 +796,7 @@ class Adherent(User):
pass pass
class Club(User): class Club(User):
PRETTY_NAME = "Clubs" PRETTY_NAME = "Clubs"
room = models.ForeignKey( room = models.ForeignKey(
@ -779,6 +805,17 @@ class Club(User):
blank=True, blank=True,
null=True null=True
) )
administrators = models.ManyToManyField(
blank=True,
to='users.Adherent',
related_name='club_administrator'
)
members = models.ManyToManyField(
blank=True,
to='users.Adherent',
related_name='club_members'
)
pass pass

View file

@ -141,21 +141,61 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td>{{ user.shell }}</td> <td>{{ user.shell }}</td>
{% endif %} {% endif %}
</table> </table>
<h2>Machines :</h2> {% if user.is_class_club %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'users:edit-club-admin-members' user.club.id %}">
<i class="glyphicon glyphicon-lock"></i>
Gérer admin et membres
</a>
<h3>Administrateurs du club</h3>
<table class="table table-striped">
<thead>
<tr>
<th>Nom</th>
<th>Prenom</th>
<th>Pseudo</th>
</tr>
</thead>
{% for admin in user.club.administrators.all %}
<tr>
<td>{{ admin.surname }}</td>
<td>{{ admin.name }}</td>
<td>{{ admin.pseudo }}</td>
</tr>
{% endfor %}
</table>
<h3>Membres</h3>
<table class="table table-striped">
<thead>
<tr>
<th>Nom</th>
<th>Prenom</th>
<th>Pseudo</th>
</tr>
</thead>
{% for admin in user.club.members.all %}
<tr>
<td>{{ admin.surname }}</td>
<td>{{ admin.name }}</td>
<td>{{ admin.pseudo }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
<h2>Machines</h2>
<h4><a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:new-machine' user.id %}"><i class="glyphicon glyphicon-phone"></i> Ajouter une machine</a></h4> <h4><a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:new-machine' user.id %}"><i class="glyphicon glyphicon-phone"></i> Ajouter une machine</a></h4>
{% if machines_list %} {% if machines_list %}
{% include "machines/aff_machines.html" with machines_list=machines_list %} {% include "machines/aff_machines.html" with machines_list=machines_list %}
{% else %} {% else %}
<p>Aucune machine</p> <p>Aucune machine</p>
{% endif %} {% endif %}
<h2>Cotisations :</h2> <h2>Cotisations</h2>
{% if is_cableur %}<h4><a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:new-facture' user.id %}"><i class="glyphicon glyphicon-piggy-bank"></i> Ajouter une cotisation</a> {% if user_solde %}<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:credit-solde' user.id %}"><i class="glyphicon glyphicon-piggy-bank"></i> Modifier le solde</a>{% endif%}</h4>{% endif%} {% if is_cableur %}<h4><a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:new-facture' user.id %}"><i class="glyphicon glyphicon-piggy-bank"></i> Ajouter une cotisation</a> {% if user_solde %}<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:credit-solde' user.id %}"><i class="glyphicon glyphicon-piggy-bank"></i> Modifier le solde</a>{% endif%}</h4>{% endif%}
{% if facture_list %} {% if facture_list %}
{% include "cotisations/aff_cotisations.html" with facture_list=facture_list %} {% include "cotisations/aff_cotisations.html" with facture_list=facture_list %}
{% else %} {% else %}
<p>Aucune facture</p> <p>Aucune facture</p>
{% endif %} {% endif %}
<h2>Bannissements :</h2> <h2>Bannissements</h2>
{% if is_bofh %}<h4><a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-ban' user.id %}"><i class="glyphicon glyphicon-pushpin"></i> Ajouter un bannissement</a></h4>{% endif %} {% if is_bofh %}<h4><a class="btn btn-primary btn-sm" role="button" href="{% url 'users:add-ban' user.id %}"><i class="glyphicon glyphicon-pushpin"></i> Ajouter un bannissement</a></h4>{% endif %}
{% if ban_list %} {% if ban_list %}
{% include "users/aff_bans.html" with ban_list=ban_list %} {% include "users/aff_bans.html" with ban_list=ban_list %}

View file

@ -26,21 +26,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% block sidebar %} {% block sidebar %}
{% if is_cableur %} {% if is_cableur %}
<a class="list-group-item list-group-item-success" href="{% url "users:new-user" %}">
<i class="glyphicon glyphicon-plus"></i>
Créer un adhérent
</a>
<a class="list-group-item list-group-item-success" href="{% url "users:new-club" %}"> <a class="list-group-item list-group-item-success" href="{% url "users:new-club" %}">
<i class="glyphicon glyphicon-plus"></i> <i class="glyphicon glyphicon-plus"></i>
Créer un club/association Créer un club/association
</a> </a>
<a class="list-group-item list-group-item-info" href="{% url "users:index" %}"> {% endif %}
<i class="glyphicon glyphicon-list"></i> <a class="list-group-item list-group-item-success" href="{% url "users:new-user" %}">
Adherents <i class="glyphicon glyphicon-plus"></i>
Créer un adhérent
</a> </a>
<a class="list-group-item list-group-item-info" href="{% url "users:index-clubs" %}"> <a class="list-group-item list-group-item-info" href="{% url "users:index-clubs" %}">
<i class="glyphicon glyphicon-list"></i> <i class="glyphicon glyphicon-list"></i>
Clubs Clubs et assos
</a>
{% if is_cableur %}
<a class="list-group-item list-group-item-info" href="{% url "users:index" %}">
<i class="glyphicon glyphicon-list"></i>
Adherents
</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

@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<form class="form" method="post"> <form class="form" method="post">
{% csrf_token %} {% csrf_token %}
{% massive_bootstrap_form userform 'room,school' %} {% massive_bootstrap_form userform 'room,school,administrators,members' %}
{% bootstrap_button "Créer ou modifier" button_type="submit" icon="star" %} {% bootstrap_button "Créer ou modifier" button_type="submit" icon="star" %}
</form> </form>
<br /> <br />

View file

@ -33,6 +33,11 @@ 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'^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'^edit_club_admin_members/(?P<clubid>[0-9]+)$',
views.edit_club_admin_members,
name='edit-club-admin-members'
),
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'),
url(r'^new_serviceuser/$', views.new_serviceuser, name='new-serviceuser'), url(r'^new_serviceuser/$', views.new_serviceuser, name='new-serviceuser'),

View file

@ -40,7 +40,7 @@ from django.shortcuts import get_object_or_404, render, redirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import ProtectedError from django.db.models import ProtectedError, Q
from django.db import IntegrityError from django.db import IntegrityError
from django.utils import timezone from django.utils import timezone
from django.db import transaction from django.db import transaction
@ -53,14 +53,40 @@ from rest_framework.renderers import JSONRenderer
from reversion.models import Version from reversion.models import Version
from reversion import revisions as reversion from reversion import revisions as reversion
from users.serializers import MailSerializer from users.serializers import MailSerializer
from users.models import User, Right, Ban, Whitelist, School, ListRight from users.models import (
from users.models import Request, ServiceUser, Adherent, Club User,
from users.forms import DelRightForm, BanForm, WhitelistForm, DelSchoolForm Right,
from users.forms import DelListRightForm, NewListRightForm, FullAdherentForm Ban,
from users.forms import StateForm, FullClubForm Whitelist,
from users.forms import RightForm, SchoolForm, EditServiceUserForm School,
from users.forms import ServiceUserForm, ListRightForm, AdherentForm, ClubForm ListRight,
from users.forms import MassArchiveForm, PassForm, ResetPasswordForm Request,
ServiceUser,
Adherent,
Club
)
from users.forms import (
DelRightForm,
BanForm,
WhitelistForm,
DelSchoolForm,
DelListRightForm,
NewListRightForm,
FullAdherentForm,
StateForm,
FullClubForm,
RightForm,
SchoolForm,
EditServiceUserForm,
ServiceUserForm,
ListRightForm,
AdherentForm,
ClubForm,
MassArchiveForm,
PassForm,
ResetPasswordForm,
ClubAdminandMembersForm
)
from cotisations.models import Facture from cotisations.models import Facture
from machines.models import Machine from machines.models import Machine
from preferences.models import OptionalUser, GeneralOption from preferences.models import OptionalUser, GeneralOption
@ -85,10 +111,15 @@ def password_change_action(u_form, user, request, req=False):
@login_required @login_required
@permission_required('cableur')
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"""
if not User.can_create(request.user):
messages.error(request, "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse(
'users:profil',
kwargs={'userid':str(request.user.id)}
))
user = AdherentForm(request.POST or None) user = AdherentForm(request.POST or None)
if user.is_valid(): if user.is_valid():
user = user.save(commit=False) user = user.save(commit=False)
@ -128,6 +159,37 @@ def new_club(request):
return form({'userform': club}, 'users/user.html', request) return form({'userform': club}, 'users/user.html', request)
@login_required
def edit_club_admin_members(request, clubid):
"""Vue d'edition de la liste des users administrateurs et
membres d'un club"""
try:
club_instance = Club.objects.get(pk=clubid)
except Club.DoesNotExist:
messages.error(request, "Club inexistant")
return redirect(reverse('users:index'))
if not club_instance.can_edit(request.user):
messages.error(request, "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse(
'users:profil',
kwargs={'userid':str(request.user.id)}
))
club = ClubAdminandMembersForm(request.POST or None, instance=club_instance)
if club.is_valid():
with transaction.atomic(), reversion.create_revision():
club.save()
reversion.set_user(request.user)
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
field for field in club.changed_data
))
messages.success(request, "Le club a bien été modifié")
return redirect(reverse(
'users:profil',
kwargs={'userid':str(club_instance.id)}
))
return form({'userform': club}, 'users/user.html', request)
def select_user_edit_form(request, user): def select_user_edit_form(request, user):
"""Fonction de choix du bon formulaire, en fonction de: """Fonction de choix du bon formulaire, en fonction de:
- droit - droit
@ -156,9 +218,8 @@ def edit_info(request, userid):
except User.DoesNotExist: except User.DoesNotExist:
messages.error(request, "Utilisateur inexistant") messages.error(request, "Utilisateur inexistant")
return redirect(reverse('users:index')) return redirect(reverse('users:index'))
if not request.user.has_perms(('cableur',)) and user != request.user: if not user.can_edit(request.user):
messages.error(request, "Vous ne pouvez pas modifier un autre\ messages.error(request, "Vous ne pouvez pas accéder à ce menu")
user que vous sans droit cableur")
return redirect(reverse( return redirect(reverse(
'users:profil', 'users:profil',
kwargs={'userid':str(request.user.id)} kwargs={'userid':str(request.user.id)}
@ -221,9 +282,8 @@ def password(request, userid):
except User.DoesNotExist: except User.DoesNotExist:
messages.error(request, "Utilisateur inexistant") messages.error(request, "Utilisateur inexistant")
return redirect(reverse('users')) return redirect(reverse('users'))
if not request.user.has_perms(('cableur',)) and user != request.user: if not user.can_edit(request.user):
messages.error(request, "Vous ne pouvez pas modifier un\ messages.error(request, "Vous ne pouvez pas accéder à ce menu")
autre user que vous sans droit cableur")
return redirect(reverse( return redirect(reverse(
'users:profil', 'users:profil',
kwargs={'userid':str(request.user.id)} kwargs={'userid':str(request.user.id)}
@ -664,11 +724,15 @@ def index(request):
@login_required @login_required
@permission_required('cableur')
def index_clubs(request): def index_clubs(request):
""" Affiche l'ensemble des clubs, need droit cableur """ """ Affiche l'ensemble des clubs, 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
if not request.user.has_perms(('cableur',)):
clubs_list = Club.objects.filter(
Q(administrators=request.user.adherent) | Q(members=request.user.adherent)
).distinct().select_related('room')
else:
clubs_list = Club.objects.select_related('room') clubs_list = Club.objects.select_related('room')
clubs_list = SortTable.sort( clubs_list = SortTable.sort(
clubs_list, clubs_list,
@ -795,10 +859,8 @@ def history(request, object_name, object_id):
except User.DoesNotExist: except User.DoesNotExist:
messages.error(request, "Utilisateur inexistant") messages.error(request, "Utilisateur inexistant")
return redirect(reverse('users:index')) return redirect(reverse('users:index'))
if not request.user.has_perms(('cableur',)) and\ if not object_instance.can_view(request.user):
object_instance != request.user: messages.error(request, "Vous ne pouvez pas afficher ce menu")
messages.error(request, "Vous ne pouvez pas afficher\
l'historique d'un autre user que vous sans droit cableur")
return redirect(reverse( return redirect(reverse(
'users:profil', 'users:profil',
kwargs={'userid':str(request.user.id)} kwargs={'userid':str(request.user.id)}
@ -889,9 +951,8 @@ def profil(request, userid):
except User.DoesNotExist: except User.DoesNotExist:
messages.error(request, "Utilisateur inexistant") messages.error(request, "Utilisateur inexistant")
return redirect(reverse('users:index')) return redirect(reverse('users:index'))
if not request.user.has_perms(('cableur',)) and users != request.user: if not users.can_view(request.user):
messages.error(request, "Vous ne pouvez pas afficher un autre user\ messages.error(request, "Vous ne pouvez pas accéder à ce menu")
que vous sans droit cableur")
return redirect(reverse( return redirect(reverse(
'users:profil', 'users:profil',
kwargs={'userid':str(request.user.id)} kwargs={'userid':str(request.user.id)}