mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-22 19:33:11 +00:00
Merge branch 'asso_users' into 'master'
Asso users See merge request federez/re2o!41
This commit is contained in:
commit
4ac51db31a
11 changed files with 249 additions and 39 deletions
20
preferences/migrations/0024_optionaluser_all_can_create.py
Normal file
20
preferences/migrations/0024_optionaluser_all_can_create.py
Normal 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"),
|
||||
),
|
||||
]
|
|
@ -42,6 +42,10 @@ class OptionalUser(models.Model):
|
|||
default=0
|
||||
)
|
||||
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):
|
||||
"""Creation du mode de paiement par solde"""
|
||||
|
|
|
@ -52,6 +52,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
<td>{{ useroptions.solde_negatif }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Creations d'users par tous</th>
|
||||
<td>{{ useroptions.all_can_create }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h4>Préférences machines</h4>
|
||||
{% if is_bureau %}
|
||||
|
|
|
@ -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):
|
||||
""" Formulaire de changement brut de mot de passe.
|
||||
Ne pas utiliser sans traitement"""
|
||||
|
|
25
users/migrations/0060_auto_20171120_0317.py
Normal file
25
users/migrations/0060_auto_20171120_0317.py
Normal 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'),
|
||||
),
|
||||
]
|
|
@ -60,7 +60,10 @@ from django.core.mail import send_mail
|
|||
from django.core.urlresolvers import reverse
|
||||
from django.db import transaction
|
||||
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 reversion import revisions as reversion
|
||||
|
@ -755,6 +758,28 @@ class User(AbstractBaseUser):
|
|||
num += 1
|
||||
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):
|
||||
return self.pseudo
|
||||
|
||||
|
@ -771,6 +796,7 @@ class Adherent(User):
|
|||
pass
|
||||
|
||||
|
||||
|
||||
class Club(User):
|
||||
PRETTY_NAME = "Clubs"
|
||||
room = models.ForeignKey(
|
||||
|
@ -779,6 +805,17 @@ class Club(User):
|
|||
blank=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
|
||||
|
||||
|
||||
|
|
|
@ -141,21 +141,61 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
<td>{{ user.shell }}</td>
|
||||
{% endif %}
|
||||
</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>
|
||||
{% if machines_list %}
|
||||
{% include "machines/aff_machines.html" with machines_list=machines_list %}
|
||||
{% else %}
|
||||
<p>Aucune machine</p>
|
||||
{% 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 facture_list %}
|
||||
{% include "cotisations/aff_cotisations.html" with facture_list=facture_list %}
|
||||
{% else %}
|
||||
<p>Aucune facture</p>
|
||||
{% 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 ban_list %}
|
||||
{% include "users/aff_bans.html" with ban_list=ban_list %}
|
||||
|
|
|
@ -26,21 +26,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
{% block sidebar %}
|
||||
{% 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" %}">
|
||||
<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" %}">
|
||||
<i class="glyphicon glyphicon-list"></i>
|
||||
Adherents
|
||||
{% endif %}
|
||||
<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-info" href="{% url "users:index-clubs" %}">
|
||||
<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 class="list-group-item list-group-item-info" href="{% url "users:index-ban" %}">
|
||||
<i class="glyphicon glyphicon-list"></i>
|
||||
|
|
|
@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
<form class="form" method="post">
|
||||
{% 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" %}
|
||||
</form>
|
||||
<br />
|
||||
|
|
|
@ -33,6 +33,11 @@ urlpatterns = [
|
|||
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_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'^password/(?P<userid>[0-9]+)$', views.password, name='password'),
|
||||
url(r'^new_serviceuser/$', views.new_serviceuser, name='new-serviceuser'),
|
||||
|
|
109
users/views.py
109
users/views.py
|
@ -40,7 +40,7 @@ from django.shortcuts import get_object_or_404, render, redirect
|
|||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
from django.contrib import messages
|
||||
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.utils import timezone
|
||||
from django.db import transaction
|
||||
|
@ -53,14 +53,40 @@ from rest_framework.renderers import JSONRenderer
|
|||
from reversion.models import Version
|
||||
from reversion import revisions as reversion
|
||||
from users.serializers import MailSerializer
|
||||
from users.models import User, Right, Ban, Whitelist, School, ListRight
|
||||
from users.models import Request, ServiceUser, Adherent, Club
|
||||
from users.forms import DelRightForm, BanForm, WhitelistForm, DelSchoolForm
|
||||
from users.forms import DelListRightForm, NewListRightForm, FullAdherentForm
|
||||
from users.forms import StateForm, FullClubForm
|
||||
from users.forms import RightForm, SchoolForm, EditServiceUserForm
|
||||
from users.forms import ServiceUserForm, ListRightForm, AdherentForm, ClubForm
|
||||
from users.forms import MassArchiveForm, PassForm, ResetPasswordForm
|
||||
from users.models import (
|
||||
User,
|
||||
Right,
|
||||
Ban,
|
||||
Whitelist,
|
||||
School,
|
||||
ListRight,
|
||||
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 machines.models import Machine
|
||||
from preferences.models import OptionalUser, GeneralOption
|
||||
|
@ -85,10 +111,15 @@ def password_change_action(u_form, user, request, req=False):
|
|||
|
||||
|
||||
@login_required
|
||||
@permission_required('cableur')
|
||||
def new_user(request):
|
||||
""" Vue de création d'un nouvel utilisateur,
|
||||
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)
|
||||
if user.is_valid():
|
||||
user = user.save(commit=False)
|
||||
|
@ -128,6 +159,37 @@ def new_club(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):
|
||||
"""Fonction de choix du bon formulaire, en fonction de:
|
||||
- droit
|
||||
|
@ -156,9 +218,8 @@ def edit_info(request, userid):
|
|||
except User.DoesNotExist:
|
||||
messages.error(request, "Utilisateur inexistant")
|
||||
return redirect(reverse('users:index'))
|
||||
if not request.user.has_perms(('cableur',)) and user != request.user:
|
||||
messages.error(request, "Vous ne pouvez pas modifier un autre\
|
||||
user que vous sans droit cableur")
|
||||
if not user.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)}
|
||||
|
@ -221,9 +282,8 @@ def password(request, userid):
|
|||
except User.DoesNotExist:
|
||||
messages.error(request, "Utilisateur inexistant")
|
||||
return redirect(reverse('users'))
|
||||
if not request.user.has_perms(('cableur',)) and user != request.user:
|
||||
messages.error(request, "Vous ne pouvez pas modifier un\
|
||||
autre user que vous sans droit cableur")
|
||||
if not user.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)}
|
||||
|
@ -664,11 +724,15 @@ def index(request):
|
|||
|
||||
|
||||
@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
|
||||
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 = SortTable.sort(
|
||||
clubs_list,
|
||||
|
@ -795,10 +859,8 @@ def history(request, object_name, object_id):
|
|||
except User.DoesNotExist:
|
||||
messages.error(request, "Utilisateur inexistant")
|
||||
return redirect(reverse('users:index'))
|
||||
if not request.user.has_perms(('cableur',)) and\
|
||||
object_instance != request.user:
|
||||
messages.error(request, "Vous ne pouvez pas afficher\
|
||||
l'historique d'un autre user que vous sans droit cableur")
|
||||
if not object_instance.can_view(request.user):
|
||||
messages.error(request, "Vous ne pouvez pas afficher ce menu")
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid':str(request.user.id)}
|
||||
|
@ -889,9 +951,8 @@ def profil(request, userid):
|
|||
except User.DoesNotExist:
|
||||
messages.error(request, "Utilisateur inexistant")
|
||||
return redirect(reverse('users:index'))
|
||||
if not request.user.has_perms(('cableur',)) and users != request.user:
|
||||
messages.error(request, "Vous ne pouvez pas afficher un autre user\
|
||||
que vous sans droit cableur")
|
||||
if not users.can_view(request.user):
|
||||
messages.error(request, "Vous ne pouvez pas accéder à ce menu")
|
||||
return redirect(reverse(
|
||||
'users:profil',
|
||||
kwargs={'userid':str(request.user.id)}
|
||||
|
|
Loading…
Reference in a new issue