views.py 38.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# 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.

23
# App de gestion des users pour re2o
Dalahro's avatar
Dalahro committed
24
# Goulven Kermarec, Gabriel Détraz, Lemesle Augustin
25
# Gplv2
26 27 28 29 30 31 32 33 34
"""
Module des views.

On définit les vues pour l'ajout, l'edition des users : infos personnelles,
mot de passe, etc

Permet aussi l'ajout, edition et suppression des droits, des bannissements,
des whitelist, des services users et des écoles
"""
35 36 37

from __future__ import unicode_literals

38
from django.urls import reverse
39
from django.shortcuts import get_object_or_404, render, redirect
40
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
41
from django.contrib import messages
42
from django.contrib.auth.decorators import login_required, permission_required
43
from django.db.models import ProtectedError, Q
44
from django.db import IntegrityError
45
from django.utils import timezone
46
from django.db import transaction
47 48 49 50 51
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt

from rest_framework.renderers import JSONRenderer

lhark's avatar
lhark committed
52

root's avatar
root committed
53
from reversion.models import Version
54
from reversion import revisions as reversion
55
from users.serializers import MailSerializer
56 57 58 59 60 61 62 63 64 65
from users.models import (
    User,
    Right,
    Ban,
    Whitelist,
    School,
    ListRight,
    Request,
    ServiceUser,
    Adherent,
LEVY-FALK Hugo's avatar
LEVY-FALK Hugo committed
66
    Club,
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
)
from users.forms import (
    DelRightForm,
    BanForm,
    WhitelistForm,
    DelSchoolForm,
    DelListRightForm,
    NewListRightForm,
    FullAdherentForm,
    StateForm,
    FullClubForm,
    RightForm,
    SchoolForm,
    EditServiceUserForm,
    ServiceUserForm,
    ListRightForm,
    AdherentForm,
    ClubForm,
    MassArchiveForm,
    PassForm,
    ResetPasswordForm,
    ClubAdminandMembersForm
)
90 91 92
from cotisations.models import Facture
from machines.models import Machine
from preferences.models import OptionalUser, GeneralOption
chirac's avatar
chirac committed
93

94
from re2o.views import form
95
from re2o.utils import all_has_access, SortTable, can_create
96

97 98
def password_change_action(u_form, user, request, req=False):
    """ Fonction qui effectue le changeemnt de mdp bdd"""
99
    user.set_user_password(u_form.cleaned_data['passwd1'])
100 101 102
    with transaction.atomic(), reversion.create_revision():
        user.save()
        reversion.set_comment("Réinitialisation du mot de passe")
103 104 105 106
    messages.success(request, "Le mot de passe a changé")
    if req:
        req.delete()
        return redirect("/")
107 108 109 110
    return redirect(reverse(
        'users:profil',
        kwargs={'userid':str(user.id)}
        ))
111

chirac's avatar
chirac committed
112
@login_required
113
@can_create(Adherent)
114
def new_user(request):
115 116
    """ Vue de création d'un nouvel utilisateur,
    envoie un mail pour le mot de passe"""
117
    user = AdherentForm(request.POST or None)
118
    if user.is_valid():
119
        user = user.save(commit=False)
120 121 122 123
        with transaction.atomic(), reversion.create_revision():
            user.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
124
        user.reset_passwd_mail(request)
125 126
        messages.success(request, "L'utilisateur %s a été crée, un mail\
        pour l'initialisation du mot de passe a été envoyé" % user.pseudo)
127 128 129 130
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(user.id)}
            ))
131
    return form({'userform': user}, 'users/user.html', request)
132

133

134
@login_required
135
@can_create(Club)
136 137 138
def new_club(request):
    """ Vue de création d'un nouveau club,
    envoie un mail pour le mot de passe"""
139
    club = ClubForm(request.POST or None)
140 141 142 143 144 145 146 147 148
    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)
149 150 151 152
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(club.id)}
            ))
153 154 155
    return form({'userform': club}, 'users/user.html', request)


156 157 158 159 160 161 162 163 164
@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'))
165
    if not club_instance.can_edit(request.user):
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
        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)


187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
def select_user_edit_form(request, user):
    """Fonction de choix du bon formulaire, en fonction de:
        - droit
        - type d'object
    """
    if not request.user.has_perms(('cableur',)):
        if user.is_class_adherent:
            user = AdherentForm(request.POST or None, instance=user.adherent)
        elif user.is_class_club:
            user = ClubForm(request.POST or None, instance=user.club)
    else:
        if user.is_class_adherent:
            user = FullAdherentForm(request.POST or None, instance=user.adherent)
        elif user.is_class_club:
            user = FullClubForm(request.POST or None, instance=user.club)
    return user


chirac's avatar
chirac committed
205
@login_required
206
def edit_info(request, userid):
207 208 209
    """ Edite un utilisateur à partir de son id,
    si l'id est différent de request.user, vérifie la
    possession du droit cableur """
210 211 212
    try:
        user = User.objects.get(pk=userid)
    except User.DoesNotExist:
213
        messages.error(request, "Utilisateur inexistant")
214
        return redirect(reverse('users:index'))
215 216
    if not user.can_edit(request.user):
        messages.error(request, "Vous ne pouvez pas accéder à ce menu")
217 218 219 220
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(request.user.id)}
            ))
221
    user = select_user_edit_form(request, user)
222
    if user.is_valid():
223 224 225
        with transaction.atomic(), reversion.create_revision():
            user.save()
            reversion.set_user(request.user)
226 227 228
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in user.changed_data
            ))
229
        messages.success(request, "L'user a bien été modifié")
230 231 232 233
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(userid)}
            ))
234
    return form({'userform': user}, 'users/user.html', request)
235

236

chirac's avatar
chirac committed
237
@login_required
chirac's avatar
chirac committed
238
@permission_required('bureau')
239
def state(request, userid):
240 241
    """ Changer l'etat actif/desactivé/archivé d'un user,
    need droit bureau """
242 243 244
    try:
        user = User.objects.get(pk=userid)
    except User.DoesNotExist:
245
        messages.error(request, "Utilisateur inexistant")
246
        return redirect(reverse('users:index'))
247 248
    state = StateForm(request.POST or None, instance=user)
    if state.is_valid():
249
        with transaction.atomic(), reversion.create_revision():
250 251 252 253 254 255
            if state.cleaned_data['state'] == User.STATE_ARCHIVE:
                user.archive()
            elif state.cleaned_data['state'] == User.STATE_ACTIVE:
                user.unarchive()
            elif state.cleaned_data['state'] == User.STATE_DISABLED:
                user.state = User.STATE_DISABLED
256
            reversion.set_user(request.user)
257 258 259
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in state.changed_data
            ))
260
            user.save()
261
        messages.success(request, "Etat changé avec succès")
262 263 264 265
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(userid)}
            ))
266
    return form({'userform': state}, 'users/user.html', request)
267

268

chirac's avatar
chirac committed
269
@login_required
270
def password(request, userid):
271 272 273
    """ Reinitialisation d'un mot de passe à partir de l'userid,
    pour self par défaut, pour tous sans droit si droit cableur,
    pour tous si droit bureau """
274 275 276
    try:
        user = User.objects.get(pk=userid)
    except User.DoesNotExist:
277
        messages.error(request, "Utilisateur inexistant")
278
        return redirect(reverse('users'))
279 280
    if not user.can_edit(request.user):
        messages.error(request, "Vous ne pouvez pas accéder à ce menu")
281 282 283 284
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(request.user.id)}
        ))
285 286 287 288
    if not request.user.has_perms(('bureau',)) and user != request.user\
            and Right.objects.filter(user=user):
        messages.error(request, "Il faut les droits bureau pour modifier le\
        mot de passe d'un membre actif")
289 290 291 292
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(request.user.id)}
            ))
293 294
    u_form = PassForm(request.POST or None)
    if u_form.is_valid():
295
        return password_change_action(u_form, user, request)
296
    return form({'userform': u_form}, 'users/user.html', request)
chirac's avatar
chirac committed
297

298

299
@login_required
300
@can_create(ServiceUser)
301 302 303 304 305 306 307 308 309 310
def new_serviceuser(request):
    """ Vue de création d'un nouvel utilisateur service"""
    user = ServiceUserForm(request.POST or None)
    if user.is_valid():
        user_object = user.save(commit=False)
        with transaction.atomic(), reversion.create_revision():
            user_object.set_password(user.cleaned_data['password'])
            user_object.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
311 312 313 314
        messages.success(
            request,
            "L'utilisateur %s a été crée" % user_object.pseudo
        )
315
        return redirect(reverse('users:index-serviceusers'))
316 317
    return form({'userform': user}, 'users/user.html', request)

318

319 320 321
@login_required
@permission_required('infra')
def edit_serviceuser(request, userid):
322 323 324
    """ Edite un utilisateur à partir de son id,
    si l'id est différent de request.user,
    vérifie la possession du droit cableur """
325 326 327 328
    try:
        user = ServiceUser.objects.get(pk=userid)
    except ServiceUser.DoesNotExist:
        messages.error(request, "Utilisateur inexistant")
329
        return redirect(reverse('users:index'))
330 331 332 333 334 335 336 337
    user = EditServiceUserForm(request.POST or None, instance=user)
    if user.is_valid():
        user_object = user.save(commit=False)
        with transaction.atomic(), reversion.create_revision():
            if user.cleaned_data['password']:
                user_object.set_password(user.cleaned_data['password'])
            user_object.save()
            reversion.set_user(request.user)
338 339 340
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in user.changed_data
            ))
341
        messages.success(request, "L'user a bien été modifié")
342
        return redirect(reverse('users:index-serviceusers'))
343 344
    return form({'userform': user}, 'users/user.html', request)

345

346 347 348
@login_required
@permission_required('infra')
def del_serviceuser(request, userid):
349
    """Suppression d'un ou plusieurs serviceusers"""
350 351 352
    try:
        user = ServiceUser.objects.get(pk=userid)
    except ServiceUser.DoesNotExist:
353
        messages.error(request, u"Utilisateur inexistant")
354
        return redirect(reverse('users:index'))
355 356 357 358 359
    if request.method == "POST":
        with transaction.atomic(), reversion.create_revision():
            user.delete()
            reversion.set_user(request.user)
        messages.success(request, "L'user a été détruite")
360
        return redirect(reverse('users:index-serviceusers'))
361 362 363 364 365 366
    return form(
        {'objet': user, 'objet_name': 'serviceuser'},
        'users/delete.html',
        request
    )

367

chirac's avatar
chirac committed
368
@login_required
369
@permission_required('bureau')
370
def add_right(request, userid):
371
    """ Ajout d'un droit à un user, need droit bureau """
372 373 374
    try:
        user = User.objects.get(pk=userid)
    except User.DoesNotExist:
375
        messages.error(request, "Utilisateur inexistant")
376
        return redirect(reverse('users:index'))
lhark's avatar
lhark committed
377 378
    right = RightForm(request.POST or None)
    if right.is_valid():
379 380 381
        right = right.save(commit=False)
        right.user = user
        try:
382 383 384 385
            with transaction.atomic(), reversion.create_revision():
                reversion.set_user(request.user)
                reversion.set_comment("Ajout du droit %s" % right.right)
                right.save()
386 387 388
            messages.success(request, "Droit ajouté")
        except IntegrityError:
            pass
389 390 391 392
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(userid)}
            ))
lhark's avatar
lhark committed
393 394
    return form({'userform': right}, 'users/user.html', request)

395

chirac's avatar
chirac committed
396
@login_required
397
@permission_required('bureau')
398
def del_right(request):
399
    """ Supprimer un droit à un user, need droit bureau """
400 401
    user_right_list = dict()
    for right in ListRight.objects.all():
402 403
        user_right_list[right] = DelRightForm(right, request.POST or None)
    for _keys, right_item in user_right_list.items():
404 405 406 407
        if right_item.is_valid():
            right_del = right_item.cleaned_data['rights']
            with transaction.atomic(), reversion.create_revision():
                reversion.set_user(request.user)
408 409 410
                reversion.set_comment("Retrait des droit %s" % ','.join(
                    str(deleted_right) for deleted_right in right_del
                ))
411 412
                right_del.delete()
            messages.success(request, "Droit retiré avec succès")
413
            return redirect(reverse('users:index'))
414
    return form({'userform': user_right_list}, 'users/del_right.html', request)
415

416

chirac's avatar
chirac committed
417
@login_required
chirac's avatar
chirac committed
418
@permission_required('bofh')
419
def add_ban(request, userid):
420 421
    """ Ajouter un banissement, nécessite au moins le droit bofh
    (a fortiori bureau)
422
    Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement"""
423 424 425
    try:
        user = User.objects.get(pk=userid)
    except User.DoesNotExist:
426
        messages.error(request, "Utilisateur inexistant")
427
        return redirect(reverse('users:index'))
428 429 430
    ban_instance = Ban(user=user)
    ban = BanForm(request.POST or None, instance=ban_instance)
    if ban.is_valid():
431
        with transaction.atomic(), reversion.create_revision():
432
            _ban_object = ban.save()
433 434
            reversion.set_user(request.user)
            reversion.set_comment("Création")
435
        messages.success(request, "Bannissement ajouté")
436 437 438 439
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(userid)}
        ))
440
    if user.is_ban:
441 442 443 444
        messages.error(
            request,
            "Attention, cet utilisateur a deja un bannissement actif"
        )
445 446
    return form({'userform': ban}, 'users/user.html', request)

447

chirac's avatar
chirac committed
448
@login_required
chirac's avatar
chirac committed
449
@permission_required('bofh')
450
def edit_ban(request, banid):
451 452
    """ Editer un bannissement, nécessite au moins le droit bofh
    (a fortiori bureau)
453
    Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement"""
454 455
    try:
        ban_instance = Ban.objects.get(pk=banid)
chirac's avatar
chirac committed
456
    except Ban.DoesNotExist:
457
        messages.error(request, "Entrée inexistante")
458
        return redirect(reverse('users:index'))
459 460
    ban = BanForm(request.POST or None, instance=ban_instance)
    if ban.is_valid():
461 462 463
        with transaction.atomic(), reversion.create_revision():
            ban.save()
            reversion.set_user(request.user)
464 465 466
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in ban.changed_data
            ))
467
        messages.success(request, "Bannissement modifié")
468
        return redirect(reverse('users:index'))
469 470
    return form({'userform': ban}, 'users/user.html', request)

471

chirac's avatar
chirac committed
472
@login_required
chirac's avatar
chirac committed
473
@permission_required('cableur')
chirac's avatar
chirac committed
474
def add_whitelist(request, userid):
475 476 477 478
    """ Accorder un accès gracieux, temporaire ou permanent.
    Need droit cableur
    Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement,
    raison obligatoire"""
chirac's avatar
chirac committed
479 480 481
    try:
        user = User.objects.get(pk=userid)
    except User.DoesNotExist:
482
        messages.error(request, "Utilisateur inexistant")
483
        return redirect(reverse('users:index'))
chirac's avatar
chirac committed
484
    whitelist_instance = Whitelist(user=user)
485 486 487 488
    whitelist = WhitelistForm(
        request.POST or None,
        instance=whitelist_instance
    )
chirac's avatar
chirac committed
489
    if whitelist.is_valid():
490 491 492 493
        with transaction.atomic(), reversion.create_revision():
            whitelist.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
chirac's avatar
chirac committed
494
        messages.success(request, "Accès à titre gracieux accordé")
495 496 497 498
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(userid)}
            ))
499
    if user.is_whitelisted:
500 501 502 503
        messages.error(
            request,
            "Attention, cet utilisateur a deja un accès gracieux actif"
        )
chirac's avatar
chirac committed
504 505
    return form({'userform': whitelist}, 'users/user.html', request)

506

chirac's avatar
chirac committed
507
@login_required
chirac's avatar
chirac committed
508
@permission_required('cableur')
chirac's avatar
chirac committed
509
def edit_whitelist(request, whitelistid):
510 511 512 513
    """ Editer un accès gracieux, temporaire ou permanent.
    Need droit cableur
    Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement,
    raison obligatoire"""
chirac's avatar
chirac committed
514 515 516
    try:
        whitelist_instance = Whitelist.objects.get(pk=whitelistid)
    except Whitelist.DoesNotExist:
517
        messages.error(request, "Entrée inexistante")
518
        return redirect(reverse('users:index'))
519 520 521 522
    whitelist = WhitelistForm(
        request.POST or None,
        instance=whitelist_instance
    )
chirac's avatar
chirac committed
523
    if whitelist.is_valid():
524 525 526
        with transaction.atomic(), reversion.create_revision():
            whitelist.save()
            reversion.set_user(request.user)
527 528 529
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in whitelist.changed_data
            ))
chirac's avatar
chirac committed
530
        messages.success(request, "Whitelist modifiée")
531
        return redirect(reverse('users:index'))
chirac's avatar
chirac committed
532 533
    return form({'userform': whitelist}, 'users/user.html', request)

534

chirac's avatar
chirac committed
535
@login_required
chirac's avatar
chirac committed
536
@permission_required('cableur')
537
def add_school(request):
538 539
    """ Ajouter un établissement d'enseignement à la base de donnée,
    need cableur"""
540 541
    school = SchoolForm(request.POST or None)
    if school.is_valid():
542 543 544 545
        with transaction.atomic(), reversion.create_revision():
            school.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
546
        messages.success(request, "L'établissement a été ajouté")
547
        return redirect(reverse('users:index-school'))
548
    return form({'userform': school}, 'users/user.html', request)
549

550

chirac's avatar
chirac committed
551
@login_required
chirac's avatar
chirac committed
552
@permission_required('cableur')
553
def edit_school(request, schoolid):
554 555
    """ Editer un établissement d'enseignement à partir du schoolid dans
    la base de donnée, need cableur"""
556 557 558
    try:
        school_instance = School.objects.get(pk=schoolid)
    except School.DoesNotExist:
559
        messages.error(request, u"Entrée inexistante")
560
        return redirect(reverse('users:index'))
561 562
    school = SchoolForm(request.POST or None, instance=school_instance)
    if school.is_valid():
563 564 565
        with transaction.atomic(), reversion.create_revision():
            school.save()
            reversion.set_user(request.user)
566 567 568
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in school.changed_data
            ))
569
        messages.success(request, "Établissement modifié")
570
        return redirect(reverse('users:index-school'))
571 572
    return form({'userform': school}, 'users/user.html', request)

573

chirac's avatar
chirac committed
574
@login_required
chirac's avatar
chirac committed
575
@permission_required('cableur')
576
def del_school(request):
577 578 579 580
    """ Supprimer un établissement d'enseignement à la base de donnée,
    need cableur
    Objet protégé, possible seulement si aucun user n'est affecté à
    l'établissement """
581 582 583 584 585
    school = DelSchoolForm(request.POST or None)
    if school.is_valid():
        school_dels = school.cleaned_data['schools']
        for school_del in school_dels:
            try:
586 587 588
                with transaction.atomic(), reversion.create_revision():
                    school_del.delete()
                    reversion.set_comment("Destruction")
589 590
                messages.success(request, "L'établissement a été supprimé")
            except ProtectedError:
591 592 593
                messages.error(
                    request,
                    "L'établissement %s est affecté à au moins un user, \
lhark's avatar
lhark committed
594
                        vous ne pouvez pas le supprimer" % school_del)
595
        return redirect(reverse('users:index-school'))
596 597
    return form({'userform': school}, 'users/user.html', request)

598

599 600 601
@login_required
@permission_required('bureau')
def add_listright(request):
602 603
    """ Ajouter un droit/groupe, nécessite droit bureau.
    Obligation de fournir un gid pour la synchro ldap, unique """
604 605 606 607 608 609 610
    listright = NewListRightForm(request.POST or None)
    if listright.is_valid():
        with transaction.atomic(), reversion.create_revision():
            listright.save()
            reversion.set_user(request.user)
            reversion.set_comment("Création")
        messages.success(request, "Le droit/groupe a été ajouté")
611
        return redirect(reverse('users:index-listright'))
612 613
    return form({'userform': listright}, 'users/user.html', request)

614

615 616 617
@login_required
@permission_required('bureau')
def edit_listright(request, listrightid):
618 619
    """ Editer un groupe/droit, necessite droit bureau,
    à partir du listright id """
620 621 622
    try:
        listright_instance = ListRight.objects.get(pk=listrightid)
    except ListRight.DoesNotExist:
623
        messages.error(request, u"Entrée inexistante")
624
        return redirect(reverse('users:index'))
625 626 627 628
    listright = ListRightForm(
        request.POST or None,
        instance=listright_instance
    )
629 630 631 632
    if listright.is_valid():
        with transaction.atomic(), reversion.create_revision():
            listright.save()
            reversion.set_user(request.user)
633 634 635
            reversion.set_comment("Champs modifié(s) : %s" % ', '.join(
                field for field in listright.changed_data
            ))
636
        messages.success(request, "Droit modifié")
637
        return redirect(reverse('users:index-listright'))
638 639
    return form({'userform': listright}, 'users/user.html', request)

640

641 642 643
@login_required
@permission_required('bureau')
def del_listright(request):
644 645
    """ Supprimer un ou plusieurs groupe, possible si il est vide, need droit
    bureau """
646 647 648 649 650 651 652 653 654 655 656 657 658 659
    listright = DelListRightForm(request.POST or None)
    if listright.is_valid():
        listright_dels = listright.cleaned_data['listrights']
        for listright_del in listright_dels:
            try:
                with transaction.atomic(), reversion.create_revision():
                    listright_del.delete()
                    reversion.set_comment("Destruction")
                messages.success(request, "Le droit/groupe a été supprimé")
            except ProtectedError:
                messages.error(
                    request,
                    "L'établissement %s est affecté à au moins un user, \
                        vous ne pouvez pas le supprimer" % listright_del)
660
        return redirect(reverse('users:index-listright'))
661 662
    return form({'userform': listright}, 'users/user.html', request)

663

664 665 666 667 668 669 670 671
@login_required
@permission_required('bureau')
def mass_archive(request):
    """ Permet l'archivage massif"""
    to_archive_date = MassArchiveForm(request.POST or None)
    to_archive_list = []
    if to_archive_date.is_valid():
        date = to_archive_date.cleaned_data['date']
672 673 674 675
        to_archive_list = [user for user in
                           User.objects.exclude(state=User.STATE_ARCHIVE)
                           if not user.end_access()
                           or user.end_access() < date]
676 677 678
        if "valider" in request.POST:
            for user in to_archive_list:
                with transaction.atomic(), reversion.create_revision():
679
                    user.archive()
680
                    user.save()
681
                    reversion.set_user(request.user)
682
                    reversion.set_comment("Archivage")
683 684 685
            messages.success(request, "%s users ont été archivés" % len(
                to_archive_list
            ))
686
            return redirect(reverse('users:index'))
687 688 689 690 691 692
    return form(
        {'userform': to_archive_date, 'to_archive_list': to_archive_list},
        'users/mass_archive.html',
        request
    )

693

chirac's avatar
chirac committed
694
@login_required
695
@permission_required('cableur')
chirac's avatar
chirac committed
696
def index(request):
697
    """ Affiche l'ensemble des adherents, need droit cableur """
698
    options, _created = GeneralOption.objects.get_or_create()
699
    pagination_number = options.pagination_number
700
    users_list = Adherent.objects.select_related('room')
701 702 703 704 705 706
    users_list = SortTable.sort(
        users_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX
    )
707
    paginator = Paginator(users_list, pagination_number)
708 709 710 711 712 713 714 715 716
    page = request.GET.get('page')
    try:
        users_list = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        users_list = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        users_list = paginator.page(paginator.num_pages)
717
    return render(request, 'users/index.html', {'users_list': users_list})
718

719

720 721 722 723 724
@login_required
def index_clubs(request):
    """ Affiche l'ensemble des clubs, need droit cableur """
    options, _created = GeneralOption.objects.get_or_create()
    pagination_number = options.pagination_number
725 726 727 728 729 730
    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')
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
    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})


chirac's avatar
chirac committed
750
@login_required
chirac's avatar
chirac committed
751
@permission_required('cableur')
752
def index_ban(request):
753
    """ Affiche l'ensemble des ban, need droit cableur """
754
    options, _created = GeneralOption.objects.get_or_create()
755
    pagination_number = options.pagination_number
756 757 758 759 760 761 762
    ban_list = Ban.objects.select_related('user')
    ban_list = SortTable.sort(
        ban_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX_BAN
    )
763
    paginator = Paginator(ban_list, pagination_number)
764 765 766 767 768 769 770
    page = request.GET.get('page')
    try:
        ban_list = paginator.page(page)
    except PageNotAnInteger:
        # If page isn't an integer, deliver first page
        ban_list = paginator.page(1)
    except EmptyPage:
771 772
        # If page is out of range (e.g. 9999), deliver last page of results.
        ban_list = paginator.page(paginator.num_pages)
773
    return render(request, 'users/index_ban.html', {'ban_list': ban_list})
774

775

chirac's avatar
chirac committed
776
@login_required
chirac's avatar
chirac committed
777
@permission_required('cableur')
778
def index_white(request):
779
    """ Affiche l'ensemble des whitelist, need droit cableur """
780
    options, _created = GeneralOption.objects.get_or_create()
781
    pagination_number = options.pagination_number
782 783 784 785 786 787 788
    white_list = Whitelist.objects.select_related('user')
    white_list = SortTable.sort(
        white_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX_BAN
    )
789 790 791 792 793 794 795 796
    paginator = Paginator(white_list, pagination_number)
    page = request.GET.get('page')
    try:
        white_list = paginator.page(page)
    except PageNotAnInteger:
        # If page isn't an integer, deliver first page
        white_list = paginator.page(1)
    except EmptyPage:
797 798
        # If page is out of range (e.g. 9999), deliver last page of results.
        white_list = paginator.page(paginator.num_pages)
799 800 801 802 803 804
    return render(
        request,
        'users/index_whitelist.html',
        {'white_list': white_list}
    )

805

chirac's avatar
chirac committed
806
@login_required
chirac's avatar
chirac committed
807
@permission_required('cableur')
808
def index_school(request):
809
    """ Affiche l'ensemble des établissement, need droit cableur """
810
    school_list = School.objects.order_by('name')
811 812 813 814 815 816
    return render(
        request,
        'users/index_schools.html',
        {'school_list': school_list}
    )

817

818 819 820
@login_required
@permission_required('cableur')
def index_listright(request):
821
    """ Affiche l'ensemble des droits , need droit cableur """
822
    listright_list = ListRight.objects.order_by('listright')
823 824 825 826 827 828
    return render(
        request,
        'users/index_listright.html',
        {'listright_list': listright_list}
    )

829

830 831 832 833 834
@login_required
@permission_required('cableur')
def index_serviceusers(request):
    """ Affiche les users de services (pour les accès ldap)"""
    serviceusers_list = ServiceUser.objects.order_by('pseudo')
835 836 837 838 839 840
    return render(
        request,
        'users/index_serviceusers.html',
        {'serviceusers_list': serviceusers_list}
    )

841

842
@login_required
843
def history(request, object_name, object_id):
844 845 846 847 848 849
    """ Affichage de l'historique : (acl, argument)
    user : self or cableur, userid,
    ban : self or cableur, banid,
    whitelist : self or cableur, whitelistid,
    school : cableur, schoolid,
    listright : cableur, listrightid """
850
    if object_name == 'user':
851
        try:
852
            object_instance = User.objects.get(pk=object_id)
853
        except User.DoesNotExist:
854
            messages.error(request, "Utilisateur inexistant")
855
            return redirect(reverse('users:index'))
856 857
        if not object_instance.can_view(request.user):
            messages.error(request, "Vous ne pouvez pas afficher ce menu")
858 859 860 861
            return redirect(reverse(
                'users:profil',
                kwargs={'userid':str(request.user.id)}
                ))
862
    elif object_name == 'serviceuser' and request.user.has_perms(('cableur',)):
863
        try:
864
            object_instance = ServiceUser.objects.get(pk=object_id)
865
        except ServiceUser.DoesNotExist:
866
            messages.error(request, "User service inexistant")
867
            return redirect(reverse('users:index'))
868
    elif object_name == 'ban':
869
        try:
870
            object_instance = Ban.objects.get(pk=object_id)
871
        except Ban.DoesNotExist:
872
            messages.error(request, "Bannissement inexistant")
873
            return redirect(reverse('users:index'))
874 875 876 877
        if not request.user.has_perms(('cableur',)) and\
                object_instance.user != request.user:
            messages.error(request, "Vous ne pouvez pas afficher les bans\
            d'un autre user que vous sans droit cableur")
878 879 880 881
            return redirect(reverse(
                'users:profil',
                kwargs={'userid':str(request.user.id)}
                ))
882
    elif object_name == 'whitelist':
883
        try:
884 885 886
            object_instance = Whitelist.objects.get(pk=object_id)
        except Whitelist.DoesNotExist:
            messages.error(request, "Whitelist inexistant")
887
            return redirect(reverse('users:index'))
888 889 890 891
        if not request.user.has_perms(('cableur',)) and\
                object_instance.user != request.user:
            messages.error(request, "Vous ne pouvez pas afficher les\
            whitelist d'un autre user que vous sans droit cableur")
892 893 894 895
            return redirect(reverse(
                'users:profil',
                kwargs={'userid':str(request.user.id)}
                ))
896
    elif object_name == 'school' and request.user.has_perms(('cableur',)):
897
        try:
898
            object_instance = School.objects.get(pk=object_id)
899
        except School.DoesNotExist:
900
            messages.error(request, "Ecole inexistante")
901
            return redirect(reverse('users:index'))
902
    elif object_name == 'listright' and request.user.has_perms(('cableur',)):
903
        try:
904
            object_instance = ListRight.objects.get(pk=object_id)
905
        except ListRight.DoesNotExist:
906
            messages.error(request, "Droit inexistant")
907
            return redirect(reverse('users:index'))
908 909
    else:
        messages.error(request, "Objet  inconnu")
910
        return redirect(reverse('users:index'))
911
    options, _created = GeneralOption.objects.get_or_create()
912
    pagination_number = options.pagination_number
root's avatar
root committed
913
    reversions = Version.objects.get_for_object(object_instance)
914
    paginator = Paginator(reversions, pagination_number)
chirac's avatar
chirac committed
915 916 917 918 919 920 921 922 923
    page = request.GET.get('page')
    try:
        reversions = paginator.page(page)
    except PageNotAnInteger:
        # If page is not an integer, deliver first page.
        reversions = paginator.page(1)
    except EmptyPage:
        # If page is out of range (e.g. 9999), deliver last page of results.
        reversions = paginator.page(paginator.num_pages)
924 925 926 927 928
    return render(
        request,
        're2o/history.html',
        {'reversions': reversions, 'object': object_instance}
    )
929 930


931 932
@login_required
def mon_profil(request):
933
    """ Lien vers profil, renvoie request.id à la fonction """
934 935 936 937
    return redirect(reverse(
        'users:profil',
        kwargs={'userid':str(request.user.id)}
        ))
938

939

chirac's avatar
chirac committed
940
@login_required
941
def profil(request, userid):
942
    """ Affiche un profil, self or cableur, prend un userid en argument """
943 944 945
    try:
        users = User.objects.get(pk=userid)
    except User.DoesNotExist:
946
        messages.error(request, "Utilisateur inexistant")
947
        return redirect(reverse('users:index'))
948 949
    if not users.can_view(request.user):
        messages.error(request, "Vous ne pouvez pas accéder à ce menu")
950 951 952 953
        return redirect(reverse(
            'users:profil',
            kwargs={'userid':str(request.user.id)}
            ))
954 955 956 957 958
    machines = Machine.objects.filter(user=users).select_related('user')\
        .prefetch_related('interface_set__domain__extension')\
        .prefetch_related('interface_set__ipv4__ip_type__extension')\
        .prefetch_related('interface_set__type')\
        .prefetch_related('interface_set__domain__related_domain__extension')
959 960 961 962 963 964
    machines = SortTable.sort(
        machines,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.MACHINES_INDEX
    )
chirac's avatar
chirac committed
965
    factures = Facture.objects.filter(user=users)
966 967 968 969 970 971
    factures = SortTable.sort(
        factures,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.COTISATIONS_INDEX
    )
chirac's avatar
chirac committed
972
    bans = Ban.objects.filter(user=users)
973 974 975 976 977 978
    bans = SortTable.sort(
        bans,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX_BAN
    )
chirac's avatar
chirac committed
979
    whitelists = Whitelist.objects.filter(user=users)
980 981 982 983 984 985
    whitelists = SortTable.sort(
        whitelists,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX_WHITE
    )
986
    list_droits = Right.objects.filter(user=users)
987
    options, _created = OptionalUser.objects.get_or_create()
chibrac's avatar
chibrac committed
988
    user_solde = options.user_solde
989 990 991 992 993
    return render(
        request,
        'users/profil.html',
        {
            'user': users,
994
            'machines_list': machines,
995 996 997
            'facture_list': factures,
            'ban_list': bans,
            'white_list': whitelists,
chirac's avatar
chirac committed
998
            'list_droits': list_droits,
chibrac's avatar
chibrac committed
999
            'user_solde': user_solde,
lhark's avatar
lhark committed
1000 1001
        }
    )
1002

1003

chirac's avatar
chirac committed
1004
def reset_password(request):
1005
    """ Reintialisation du mot de passe si mdp oublié """
chirac's avatar
chirac committed
1006 1007 1008
    userform = ResetPasswordForm(request.POST or None)
    if userform.is_valid():
        try:
1009 1010 1011 1012
            user = User.objects.get(
                pseudo=userform.cleaned_data['pseudo'],
                email=userform.cleaned_data['email']
            )
chirac's avatar
chirac committed
1013 1014
        except User.DoesNotExist:
            messages.error(request, "Cet utilisateur n'existe pas")
1015 1016
            return form({'userform': userform}, 'users/user.html', request)
        user.reset_passwd_mail(request)
1017 1018 1019
        messages.success(request, "Un mail pour l'initialisation du mot\
        de passe a été envoyé")
        redirect("/")
chirac's avatar
chirac committed
1020 1021
    return form({'userform': userform}, 'users/user.html', request)

1022

1023
def process(request, token):
1024
    """Process, lien pour la reinitialisation du mot de passe"""
1025 1026 1027 1028 1029 1030
    valid_reqs = Request.objects.filter(expires_at__gt=timezone.now())
    req = get_object_or_404(valid_reqs, token=token)

    if req.type == Request.PASSWD:
        return process_passwd(request, req)
    else:
chirac's avatar
chirac committed
1031 1032
        messages.error(request, "Entrée incorrecte, contactez un admin")
        redirect("/")
1033

1034

1035
def process_passwd(request, req):
1036 1037
    """Process le changeemnt de mot de passe, renvoie le formulaire
    demandant le nouveau password"""
1038 1039 1040 1041 1042
    u_form = PassForm(request.POST or None)
    user = req.user
    if u_form.is_valid():
        return password_change_action(u_form, user, request, req=req)
    return form({'userform': u_form}, 'users/user.html', request)
1043

1044 1045

class JSONResponse(HttpResponse):
1046
    """ Framework Rest """
1047 1048 1049 1050 1051
    def __init__(self, data, **kwargs):
        content = JSONRenderer().render(data)
        kwargs['content_type'] = 'application/json'
        super(JSONResponse, self).__init__(content, **kwargs)

1052

1053 1054 1055 1056
@csrf_exempt
@login_required
@permission_required('serveur')
def mailing(request):
chirac's avatar
chirac committed
1057 1058
    """ Fonction de serialisation des addresses mail de tous les users
    Pour generation de ml all users"""
1059
    mails = all_has_access().values('email').distinct()
1060 1061
    seria = MailSerializer(mails, many=True)
    return JSONResponse(seria.data)