Ce serveur Gitlab sera éteint le 30 juin 2020, pensez à migrer vos projets vers les serveurs gitlab-research.centralesupelec.fr et gitlab-student.centralesupelec.fr !

views.py 35.7 KB
Newer Older
Gabriel Detraz's avatar
Gabriel Detraz committed
1
# -*- mode: python; coding: utf-8 -*-
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# 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.

24
# App de gestion des users pour re2o
Dalahro's avatar
Dalahro committed
25
# Goulven Kermarec, Gabriel Détraz, Lemesle Augustin
26
# Gplv2
27 28 29 30 31 32 33 34 35
"""
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
"""
36 37 38

from __future__ import unicode_literals

39
from django.urls import reverse
40
from django.shortcuts import get_object_or_404, render, redirect
41
from django.contrib import messages
42
from django.contrib.auth.decorators import login_required, permission_required
43
from django.db.models import ProtectedError, Count, Max
44
from django.utils import timezone
45
from django.db import transaction
46
from django.http import HttpResponse
47
from django.http import HttpResponseRedirect
48
from django.views.decorators.csrf import csrf_exempt
49
from django.utils.translation import ugettext as _
50 51

from rest_framework.renderers import JSONRenderer
52
from reversion import revisions as reversion
53

54
from cotisations.models import Facture, Paiement
55
from machines.models import Machine
Gabriel Detraz's avatar
Gabriel Detraz committed
56
from preferences.models import OptionalUser, GeneralOption, AssoOption
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
from re2o.views import form
from re2o.utils import (
    all_has_access,
    SortTable,
    re2o_paginator
)
from re2o.acl import (
    can_create,
    can_edit,
    can_delete_set,
    can_delete,
    can_view,
    can_view_all,
    can_change
)
72
from cotisations.utils import find_payment_method
lhark's avatar
lhark committed
73

74 75
from .serializers import MailingSerializer, MailingMemberSerializer
from .models import (
76 77 78 79 80 81 82 83
    User,
    Ban,
    Whitelist,
    School,
    ListRight,
    Request,
    ServiceUser,
    Adherent,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
84
    Club,
85
    ListShell,
86
    EMailAddress,
87
)
88
from .forms import (
89 90
    BanForm,
    WhitelistForm,
91
    EMailAddressForm,
92
    EmailSettingsForm,
93 94 95 96 97
    DelSchoolForm,
    DelListRightForm,
    NewListRightForm,
    StateForm,
    SchoolForm,
98
    ShellForm,
99 100 101 102 103 104 105 106
    EditServiceUserForm,
    ServiceUserForm,
    ListRightForm,
    AdherentForm,
    ClubForm,
    MassArchiveForm,
    PassForm,
    ResetPasswordForm,
107 108
    ClubAdminandMembersForm,
    GroupForm
109
)
110

111

112
@can_create(Adherent)
113
def new_user(request):
114 115
    """ Vue de création d'un nouvel utilisateur,
    envoie un mail pour le mot de passe"""
116
    user = AdherentForm(request.POST or None, user=request.user)
117 118
    GTU_sum_up = GeneralOption.get_cached_value('GTU_sum_up')
    GTU = GeneralOption.get_cached_value('GTU')
119
    if user.is_valid():
120
        user = user.save()
121
        user.reset_passwd_mail(request)
122 123
        messages.success(request, _("The user %s was created, an email to set"
                                    " the password was sent.") % user.pseudo)
124 125
        return redirect(reverse(
            'users:profil',
126 127 128 129 130 131 132 133
            kwargs={'userid': str(user.id)}
        ))
    return form(
        {
            'userform': user,
            'GTU_sum_up': GTU_sum_up,
            'GTU': GTU,
            'showCGU': True,
134
            'action_name': _("Create a user")
135 136 137 138
        },
        'users/user.html',
        request
    )
139

140

141
@login_required
142
@can_create(Club)
143 144 145
def new_club(request):
    """ Vue de création d'un nouveau club,
    envoie un mail pour le mot de passe"""
146
    club = ClubForm(request.POST or None, user=request.user)
147 148
    if club.is_valid():
        club = club.save(commit=False)
149
        club.save()
150
        club.reset_passwd_mail(request)
151 152
        messages.success(request, _("The club %s was created, an email to set"
                                    " the password was sent.") % club.pseudo)
153 154
        return redirect(reverse(
            'users:profil',
155 156 157
            kwargs={'userid': str(club.id)}
        ))
    return form(
158
        {'userform': club, 'showCGU': False, 'action_name': _("Create a club")},
159 160 161
        'users/user.html',
        request
    )
162 163


164
@login_required
165
@can_edit(Club)
166
def edit_club_admin_members(request, club_instance, **_kwargs):
167 168
    """Vue d'edition de la liste des users administrateurs et
    membres d'un club"""
169 170 171 172
    club = ClubAdminandMembersForm(
        request.POST or None,
        instance=club_instance
    )
173
    if club.is_valid():
174 175
        if club.changed_data:
            club.save()
176
            messages.success(request, _("The club was edited."))
177 178
        return redirect(reverse(
            'users:profil',
179 180 181 182 183 184
            kwargs={'userid': str(club_instance.id)}
        ))
    return form(
        {
            'userform': club,
            'showCGU': False,
185
            'action_name': _("Edit the admins and members")
186 187 188 189
        },
        'users/user.html',
        request
    )
190 191


chirac's avatar
chirac committed
192
@login_required
193
@can_edit(User)
194
def edit_info(request, user, userid):
195 196 197
    """ Edite un utilisateur à partir de son id,
    si l'id est différent de request.user, vérifie la
    possession du droit cableur """
198
    if user.is_class_adherent:
199
        user_form = AdherentForm(
200 201 202 203
            request.POST or None,
            instance=user.adherent,
            user=request.user
        )
204 205
    else:
        user_form = ClubForm(
206 207 208 209
            request.POST or None,
            instance=user.club,
            user=request.user
        )
210 211 212
    if user_form.is_valid():
        if user_form.changed_data:
            user_form.save()
213
            messages.success(request, _("The user was edited."))
214 215
        return redirect(reverse(
            'users:profil',
216 217 218
            kwargs={'userid': str(userid)}
        ))
    return form(
219
        {'userform': user_form, 'action_name': _("Edit the user")},
220 221 222
        'users/user.html',
        request
    )
223

224

chirac's avatar
chirac committed
225
@login_required
226
@can_edit(User, 'state')
227
def state(request, user, userid):
chirac's avatar
chirac committed
228
    """ Change the state (active/unactive/archived) of a user"""
229 230 231 232
    state_form = StateForm(request.POST or None, instance=user)
    if state_form.is_valid():
        if state_form.changed_data:
            state_form.save()
233
            messages.success(request, _("The state was edited."))
234 235
        return redirect(reverse(
            'users:profil',
236 237 238
            kwargs={'userid': str(userid)}
        ))
    return form(
239
        {'userform': state_form, 'action_name': _("Edit the state")},
240 241 242
        'users/user.html',
        request
    )
243

244

245
@login_required
246
@can_edit(User, 'groups')
247
def groups(request, user, userid):
248
    """ View to edit the groups of a user """
249 250
    group_form = GroupForm(request.POST or None,
                           instance=user, user=request.user)
251 252 253
    if group_form.is_valid():
        if group_form.changed_data:
            group_form.save()
254
            messages.success(request, _("The groups were edited."))
255 256
        return redirect(reverse(
            'users:profil',
257
            kwargs={'userid': str(userid)}
258
        ))
259
    return form(
260
        {'userform': group_form, 'action_name': _("Edit the groups")},
261 262 263
        'users/user.html',
        request
    )
264 265


chirac's avatar
chirac committed
266
@login_required
267
@can_edit(User, 'password')
268
def password(request, user, userid):
269 270 271
    """ 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 """
272
    u_form = PassForm(request.POST or None, instance=user, user=request.user)
273
    if u_form.is_valid():
274 275
        if u_form.changed_data:
            u_form.save()
276
            messages.success(request, _("The password was changed."))
277
        return redirect(reverse(
278
            'users:profil',
279
            kwargs={'userid': str(userid)}
280
        ))
281
    return form(
282
        {'userform': u_form, 'action_name': _("Change the password")},
283 284 285
        'users/user.html',
        request
    )
chirac's avatar
chirac committed
286

287

288
@login_required
289
@can_edit(User, 'groups')
290
def del_group(request, user, listrightid, **_kwargs):
291
    """ View used to delete a group """
292 293
    user.groups.remove(ListRight.objects.get(id=listrightid))
    user.save()
294
    messages.success(request, _("%s was removed from the group.") % user)
295
    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
296 297


298
@login_required
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
299
@can_edit(User, 'is_superuser')
300 301 302 303
def del_superuser(request, user, **_kwargs):
    """Remove the superuser right of an user."""
    user.is_superuser = False
    user.save()
304
    messages.success(request, _("%s is no longer superuser.") % user)
305 306 307
    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))


308
@login_required
309
@can_create(ServiceUser)
310 311 312 313
def new_serviceuser(request):
    """ Vue de création d'un nouvel utilisateur service"""
    user = ServiceUserForm(request.POST or None)
    if user.is_valid():
314
        user.save()
315 316
        messages.success(
            request,
317
            _("The service user was created.")
318
        )
319
        return redirect(reverse('users:index-serviceusers'))
320
    return form(
321
        {'userform': user, 'action_name': _("Create a service user")},
322 323 324
        'users/user.html',
        request
    )
325

326

327
@login_required
328
@can_edit(ServiceUser)
329
def edit_serviceuser(request, serviceuser, **_kwargs):
330
    """ Edit a ServiceUser """
331 332 333 334
    serviceuser = EditServiceUserForm(
        request.POST or None,
        instance=serviceuser
    )
335 336
    if serviceuser.is_valid():
        if serviceuser.changed_data:
337
            serviceuser.save()
338
        messages.success(request, _("The service user was edited."))
339
        return redirect(reverse('users:index-serviceusers'))
340
    return form(
341
        {'userform': serviceuser, 'action_name': _("Edit a service user")},
342 343 344
        'users/user.html',
        request
    )
345

346

347
@login_required
348
@can_delete(ServiceUser)
349
def del_serviceuser(request, serviceuser, **_kwargs):
350
    """Suppression d'un ou plusieurs serviceusers"""
351
    if request.method == "POST":
352
        serviceuser.delete()
353
        messages.success(request, _("The service user was deleted."))
354
        return redirect(reverse('users:index-serviceusers'))
355
    return form(
356
        {'objet': serviceuser, 'objet_name': 'service user'},
357 358 359 360
        'users/delete.html',
        request
    )

361

chirac's avatar
chirac committed
362
@login_required
363 364 365
@can_create(Ban)
@can_edit(User)
def add_ban(request, user, userid):
366 367
    """ Ajouter un banissement, nécessite au moins le droit bofh
    (a fortiori bureau)
368
    Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement"""
369 370 371
    ban_instance = Ban(user=user)
    ban = BanForm(request.POST or None, instance=ban_instance)
    if ban.is_valid():
372
        ban.save()
373
        messages.success(request, _("The ban was added."))
374 375
        return redirect(reverse(
            'users:profil',
376
            kwargs={'userid': str(userid)}
377
        ))
378
    if user.is_ban():
379 380
        messages.error(
            request,
381
            _("Warning: this user already has an active ban.")
382
        )
383
    return form(
384
        {'userform': ban, 'action_name': _("Add a ban")},
385 386 387 388
        'users/user.html',
        request
    )

389

chirac's avatar
chirac committed
390
@login_required
391
@can_edit(Ban)
392
def edit_ban(request, ban_instance, **_kwargs):
393 394
    """ Editer un bannissement, nécessite au moins le droit bofh
    (a fortiori bureau)
395
    Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement"""
396 397
    ban = BanForm(request.POST or None, instance=ban_instance)
    if ban.is_valid():
398 399
        if ban.changed_data:
            ban.save()
400
            messages.success(request, _("The ban was edited."))
401
        return redirect(reverse('users:index'))
402
    return form(
403
        {'userform': ban, 'action_name': _("Edit a ban")},
404 405 406
        'users/user.html',
        request
    )
407

408

409 410 411
@login_required
@can_delete(Ban)
def del_ban(request, ban, **_kwargs):
412 413 414
    """ Supprime un banissement"""
    if request.method == "POST":
        ban.delete()
415
        messages.success(request, _("The ban was deleted."))
416 417 418 419 420 421 422 423 424
        return redirect(reverse(
            'users:profil',
            kwargs={'userid': str(ban.user.id)}
        ))
    return form(
        {'objet': ban, 'objet_name': 'ban'},
        'users/delete.html',
        request
    )
425

426

chirac's avatar
chirac committed
427
@login_required
428 429 430
@can_create(Whitelist)
@can_edit(User)
def add_whitelist(request, user, userid):
431 432 433 434
    """ 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
435
    whitelist_instance = Whitelist(user=user)
436 437 438 439
    whitelist = WhitelistForm(
        request.POST or None,
        instance=whitelist_instance
    )
chirac's avatar
chirac committed
440
    if whitelist.is_valid():
441
        whitelist.save()
442
        messages.success(request, _("The whitelist was added."))
443 444
        return redirect(reverse(
            'users:profil',
445 446
            kwargs={'userid': str(userid)}
        ))
447
    if user.is_whitelisted():
448 449
        messages.error(
            request,
450
            _("Warning: this user already has an active whitelist.")
451
        )
452
    return form(
453
        {'userform': whitelist, 'action_name': _("Add a whitelist")},
454 455 456
        'users/user.html',
        request
    )
chirac's avatar
chirac committed
457

458

chirac's avatar
chirac committed
459
@login_required
460
@can_edit(Whitelist)
461
def edit_whitelist(request, whitelist_instance, **_kwargs):
462 463 464 465 466 467 468 469
    """ Editer un accès gracieux, temporaire ou permanent.
    Need droit cableur
    Syntaxe : JJ/MM/AAAA , heure optionnelle, prend effet immédiatement,
    raison obligatoire"""
    whitelist = WhitelistForm(
        request.POST or None,
        instance=whitelist_instance
    )
chirac's avatar
chirac committed
470
    if whitelist.is_valid():
471 472
        if whitelist.changed_data:
            whitelist.save()
473
            messages.success(request, _("The whitelist was edited."))
474
        return redirect(reverse('users:index'))
475
    return form(
476
        {'userform': whitelist, 'action_name': _("Edit a whitelist")},
477 478 479
        'users/user.html',
        request
    )
chirac's avatar
chirac committed
480

481

482 483 484
@login_required
@can_delete(Whitelist)
def del_whitelist(request, whitelist, **_kwargs):
485 486 487
    """ Supprime un acces gracieux"""
    if request.method == "POST":
        whitelist.delete()
488
        messages.success(request, _("The whitelist was deleted."))
489 490 491 492 493 494 495 496 497 498
        return redirect(reverse(
            'users:profil',
            kwargs={'userid': str(whitelist.user.id)}
        ))
    return form(
        {'objet': whitelist, 'objet_name': 'whitelist'},
        'users/delete.html',
        request
    )

499

500
@login_required
501
@can_create(EMailAddress)
502
@can_edit(User)
503
def add_emailaddress(request, user, userid):
504
    """ Create a new local email account"""
505 506
    emailaddress_instance = EMailAddress(user=user)
    emailaddress = EMailAddressForm(
507
        request.POST or None,
508
        instance=emailaddress_instance
509
    )
510 511
    if emailaddress.is_valid():
        emailaddress.save()
512
        messages.success(request, _("The local email account was created."))
513 514 515 516 517
        return redirect(reverse(
            'users:profil',
            kwargs={'userid': str(userid)}
        ))
    return form(
518
        {'userform': emailaddress,
519
         'showCGU': False,
520
         'action_name': _("Add a local email account")},
521 522 523 524
        'users/user.html',
        request
    )

525

526
@login_required
527 528
@can_edit(EMailAddress)
def edit_emailaddress(request, emailaddress_instance, **_kwargs):
529
    """ Edit a local email account"""
530
    emailaddress = EMailAddressForm(
531
        request.POST or None,
532
        instance=emailaddress_instance
533
    )
534 535 536
    if emailaddress.is_valid():
        if emailaddress.changed_data:
            emailaddress.save()
537
            messages.success(request, _("The local email account was edited."))
538 539
        return redirect(reverse(
            'users:profil',
540
            kwargs={'userid': str(emailaddress_instance.user.id)}
541
        ))
542
    return form(
543
        {'userform': emailaddress,
544
         'showCGU': False,
545
         'action_name': _("Edit a local email account")},
546 547 548 549
        'users/user.html',
        request
    )

550

551
@login_required
552 553
@can_delete(EMailAddress)
def del_emailaddress(request, emailaddress, **_kwargs):
554 555
    """Delete a local email account"""
    if request.method == "POST":
556
        emailaddress.delete()
557
        messages.success(request, _("The local email account was deleted."))
558 559
        return redirect(reverse(
            'users:profil',
560
            kwargs={'userid': str(emailaddress.user.id)}
561 562
            ))
    return form(
563
        {'objet': emailaddress, 'objet_name': 'emailaddress'},
564 565 566 567
        'users/delete.html',
        request
    )

568

569
@login_required
570
@can_edit(User)
571 572 573
def edit_email_settings(request, user_instance, **_kwargs):
    """Edit the email settings of a user"""
    email_settings = EmailSettingsForm(
574
        request.POST or None,
575 576
        instance=user_instance,
        user=request.user
577
    )
578 579 580
    if email_settings.is_valid():
        if email_settings.changed_data:
            email_settings.save()
581
            messages.success(request, _("The email settings were edited."))
582 583 584 585
        return redirect(reverse(
            'users:profil',
            kwargs={'userid': str(user_instance.id)}
            ))
586
    return form(
587 588
        {'userform': email_settings,
         'showCGU': False,
589
         'load_js_file': '/static/js/email_address.js',
590
         'action_name': _("Edit the email settings")},
591 592 593 594
        'users/user.html',
        request
    )

595

chirac's avatar
chirac committed
596
@login_required
597
@can_create(School)
598
def add_school(request):
599 600
    """ Ajouter un établissement d'enseignement à la base de donnée,
    need cableur"""
601 602
    school = SchoolForm(request.POST or None)
    if school.is_valid():
603
        school.save()
604
        messages.success(request, _("The school was added."))
605
        return redirect(reverse('users:index-school'))
606
    return form(
607
        {'userform': school, 'action_name': _("Add a school")},
608 609 610
        'users/user.html',
        request
    )
611

612

chirac's avatar
chirac committed
613
@login_required
614
@can_edit(School)
615
def edit_school(request, school_instance, **_kwargs):
616 617
    """ Editer un établissement d'enseignement à partir du schoolid dans
    la base de donnée, need cableur"""
618 619
    school = SchoolForm(request.POST or None, instance=school_instance)
    if school.is_valid():
620 621
        if school.changed_data:
            school.save()
622
            messages.success(request, _("The school was edited."))
623
        return redirect(reverse('users:index-school'))
624
    return form(
625
        {'userform': school, 'action_name': _("Edit a school")},
626 627 628
        'users/user.html',
        request
    )
629

630

chirac's avatar
chirac committed
631
@login_required
632
@can_delete_set(School)
633
def del_school(request, instances):
634 635 636 637
    """ 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 """
638
    school = DelSchoolForm(request.POST or None, instances=instances)
639 640 641 642
    if school.is_valid():
        school_dels = school.cleaned_data['schools']
        for school_del in school_dels:
            try:
643
                school_del.delete()
644
                messages.success(request, _("The school was deleted."))
645
            except ProtectedError:
646 647
                messages.error(
                    request,
648 649
                    _("The school %s is assigned to at least one user,"
                      " impossible to delete it.") % school_del)
650
        return redirect(reverse('users:index-school'))
651
    return form(
652
        {'userform': school, 'action_name': _("Delete")},
653 654 655
        'users/user.html',
        request
    )
656

657

658 659 660
@login_required
@can_create(ListShell)
def add_shell(request):
Gabriel Detraz's avatar
Gabriel Detraz committed
661
    """ Ajouter un shell à la base de donnée"""
662 663
    shell = ShellForm(request.POST or None)
    if shell.is_valid():
664
        shell.save()
665
        messages.success(request, _("The shell was added."))
666
        return redirect(reverse('users:index-shell'))
667
    return form(
668
        {'userform': shell, 'action_name': _("Add a shell")},
669 670 671
        'users/user.html',
        request
    )
672 673 674 675


@login_required
@can_edit(ListShell)
676
def edit_shell(request, shell_instance, **_kwargs):
Gabriel Detraz's avatar
Gabriel Detraz committed
677
    """ Editer un shell à partir du listshellid"""
678 679
    shell = ShellForm(request.POST or None, instance=shell_instance)
    if shell.is_valid():
680 681
        if shell.changed_data:
            shell.save()
682
            messages.success(request, _("The shell was edited."))
683
        return redirect(reverse('users:index-shell'))
684
    return form(
685
        {'userform': shell, 'action_name': _("Edit a shell")},
686 687 688
        'users/user.html',
        request
    )
689 690 691 692


@login_required
@can_delete(ListShell)
693
def del_shell(request, shell, **_kwargs):
694 695
    """Destruction d'un shell"""
    if request.method == "POST":
696
        shell.delete()
697
        messages.success(request, _("The shell was deleted."))
698 699 700 701 702 703 704 705
        return redirect(reverse('users:index-shell'))
    return form(
        {'objet': shell, 'objet_name': 'shell'},
        'users/delete.html',
        request
    )


706
@login_required
707
@can_create(ListRight)
708
def add_listright(request):
709 710
    """ Ajouter un droit/groupe, nécessite droit bureau.
    Obligation de fournir un gid pour la synchro ldap, unique """
711 712
    listright = NewListRightForm(request.POST or None)
    if listright.is_valid():
713
        listright.save()
714
        messages.success(request, _("The group of rights was added."))
715
        return redirect(reverse('users:index-listright'))
716
    return form(
717
        {'userform': listright, 'action_name': _("Add a group of rights")},
718 719 720
        'users/user.html',
        request
    )
721

722

723
@login_required
724
@can_edit(ListRight)
725
def edit_listright(request, listright_instance, **_kwargs):
726 727 728 729 730 731
    """ Editer un groupe/droit, necessite droit bureau,
    à partir du listright id """
    listright = ListRightForm(
        request.POST or None,
        instance=listright_instance
    )
732
    if listright.is_valid():
733 734
        if listright.changed_data:
            listright.save()
735
            messages.success(request, _("The group of rights was edited."))
736
        return redirect(reverse('users:index-listright'))
737
    return form(
738
        {'userform': listright, 'action_name': _("Edit a group of rights")},
739 740 741
        'users/user.html',
        request
    )
742

743

744
@login_required
745
@can_delete_set(ListRight)
746
def del_listright(request, instances):
747 748
    """ Supprimer un ou plusieurs groupe, possible si il est vide, need droit
    bureau """
749
    listright = DelListRightForm(request.POST or None, instances=instances)
750 751 752 753
    if listright.is_valid():
        listright_dels = listright.cleaned_data['listrights']
        for listright_del in listright_dels:
            try:
754
                listright_del.delete()
755 756
                messages.success(request, _("The group of rights was"
                                            " deleted."))
757 758 759
            except ProtectedError:
                messages.error(
                    request,
760 761
                    _("The group of rights %s is assigned to at least one"
                      " user, impossible to delete it.") % listright_del)
762
        return redirect(reverse('users:index-listright'))
763
    return form(
764
        {'userform': listright, 'action_name': _("Delete")},
765 766 767
        'users/user.html',
        request
    )
768

769

770
@login_required
771 772
@can_view_all(User)
@can_change(User, 'state')
773 774 775 776 777 778
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']
779 780 781 782
        to_archive_list = [user for user in
                           User.objects.exclude(state=User.STATE_ARCHIVE)
                           if not user.end_access()
                           or user.end_access() < date]
783 784 785
        if "valider" in request.POST:
            for user in to_archive_list:
                with transaction.atomic(), reversion.create_revision():
786
                    user.archive()
787
                    user.save()
788 789
                    reversion.set_comment(_("Archiving"))
            messages.success(request, _("%s users were archived.") % len(
790 791
                to_archive_list
            ))
792
            return redirect(reverse('users:index'))
793 794 795 796 797 798
    return form(
        {'userform': to_archive_date, 'to_archive_list': to_archive_list},
        'users/mass_archive.html',
        request
    )

799

chirac's avatar
chirac committed
800
@login_required
801
@can_view_all(Adherent)
chirac's avatar
chirac committed
802
def index(request):
803
    """ Affiche l'ensemble des adherents, need droit cableur """
804
    pagination_number = GeneralOption.get_cached_value('pagination_number')
805
    users_list = Adherent.objects.select_related('room')
806 807 808 809 810 811
    users_list = SortTable.sort(
        users_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX
    )
812
    users_list = re2o_paginator(request, users_list, pagination_number)
813
    return render(request, 'users/index.html', {'users_list': users_list})
814

815

816
@login_required
817
@can_view_all(Club)
818 819
def index_clubs(request):
    """ Affiche l'ensemble des clubs, need droit cableur """
820
    pagination_number = GeneralOption.get_cached_value('pagination_number')
821
    clubs_list = Club.objects.select_related('room')
822 823 824 825 826 827
    clubs_list = SortTable.sort(
        clubs_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX
    )
828
    clubs_list = re2o_paginator(request, clubs_list, pagination_number)
829 830 831 832 833
    return render(
        request,
        'users/index_clubs.html',
        {'clubs_list': clubs_list}
    )
834 835


chirac's avatar
chirac committed
836
@login_required
837
@can_view_all(Ban)
838
def index_ban(request):
839
    """ Affiche l'ensemble des ban, need droit cableur """
840
    pagination_number = GeneralOption.get_cached_value('pagination_number')
841 842 843 844 845 846 847
    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
    )
848
    ban_list = re2o_paginator(request, ban_list, pagination_number)
849
    return render(request, 'users/index_ban.html', {'ban_list': ban_list})
850

851

chirac's avatar
chirac committed
852
@login_required
853
@can_view_all(Whitelist)
854
def index_white(request):
855
    """ Affiche l'ensemble des whitelist, need droit cableur """
856
    pagination_number = GeneralOption.get_cached_value('pagination_number')
857 858 859 860 861 862 863
    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
    )
864
    white_list = re2o_paginator(request, white_list, pagination_number)
865 866 867 868 869 870
    return render(
        request,
        'users/index_whitelist.html',
        {'white_list': white_list}
    )

871

chirac's avatar
chirac committed
872
@login_required
873
@can_view_all(School)
874
def index_school(request):
875
    """ Affiche l'ensemble des établissement"""
876
    school_list = School.objects.order_by('name')
877 878 879 880 881 882 883
    pagination_number = GeneralOption.get_cached_value('pagination_number')
    school_list = SortTable.sort(
        school_list,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX_SCHOOL
    )
884
    school_list = re2o_paginator(request, school_list, pagination_number)
885 886 887 888 889 890
    return render(
        request,
        'users/index_schools.html',
        {'school_list': school_list}
    )

891

892 893 894 895 896 897 898 899 900 901 902 903
@login_required
@can_view_all(ListShell)
def index_shell(request):
    """ Affiche l'ensemble des shells"""
    shell_list = ListShell.objects.order_by('shell')
    return render(
        request,
        'users/index_shell.html',
        {'shell_list': shell_list}
    )


904
@login_required
905
@can_view_all(ListRight)
906
def index_listright(request):
907
    """ Affiche l'ensemble des droits"""
908 909 910 911 912
    rights = {}
    for right in (ListRight.objects
                  .order_by('name')
                  .prefetch_related('permissions')
                  .prefetch_related('user_set')
913
                  .prefetch_related('user_set__facture_set__vente_set__cotisation')
914 915 916
                 ):
        rights[right] = (right.user_set
                         .annotate(action_number=Count('revision'),
917 918
                                   last_seen=Max('revision__date_created'),
                                   end_adhesion=Max('facture__vente__cotisation__date_end'))
919 920 921 922
                        )
    superusers = (User.objects
                  .filter(is_superuser=True)
                  .annotate(action_number=Count('revision'),
923 924
                            last_seen=Max('revision__date_created'),
                            end_adhesion=Max('facture__vente__cotisation__date_end'))
925
                 )
926 927 928
    return render(
        request,
        'users/index_listright.html',
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
929
        {
930 931
            'rights': rights,
            'superusers' : superusers,
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
932
        }
933 934
    )

935

936
@login_required
937
@can_view_all(ServiceUser)
938 939 940
def index_serviceusers(request):
    """ Affiche les users de services (pour les accès ldap)"""
    serviceusers_list = ServiceUser.objects.order_by('pseudo')
941 942 943 944 945 946
    return render(
        request,
        'users/index_serviceusers.html',
        {'serviceusers_list': serviceusers_list}
    )

947

948 949
@login_required
def mon_profil(request):
950
    """ Lien vers profil, renvoie request.id à la fonction """
951 952
    return redirect(reverse(
        'users:profil',
953
        kwargs={'userid': str(request.user.id)}
954
    ))
955

956

chirac's avatar
chirac committed
957
@login_required
958
@can_view(User)
959
def profil(request, users, **_kwargs):
960
    """ Affiche un profil, self or cableur, prend un userid en argument """
961 962 963 964 965
    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')
966 967 968 969 970 971
    machines = SortTable.sort(
        machines,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.MACHINES_INDEX
    )
972 973 974
    pagination_large_number = GeneralOption.get_cached_value(
        'pagination_large_number'
    )
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
975
    nb_machines = machines.count()
976
    machines = re2o_paginator(request, machines, pagination_large_number)
chirac's avatar
chirac committed
977
    factures = Facture.objects.filter(user=users)
978 979 980 981 982 983
    factures = SortTable.sort(
        factures,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.COTISATIONS_INDEX
    )
chirac's avatar
chirac committed
984
    bans = Ban.objects.filter(user=users)
985 986 987 988 989 990
    bans = SortTable.sort(
        bans,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX_BAN
    )
chirac's avatar
chirac committed
991
    whitelists = Whitelist.objects.filter(user=users)
992 993 994 995 996 997
    whitelists = SortTable.sort(
        whitelists,
        request.GET.get('col'),
        request.GET.get('order'),
        SortTable.USERS_INDEX_WHITE
    )
998 999 1000 1001 1002 1003 1004 1005 1006
    try:
        balance = find_payment_method(Paiement.objects.get(is_balance=True))
    except Paiement.DoesNotExist:
        user_solde = False
    else:
        user_solde = (
            balance is not None
            and balance.can_credit_balance(request.user)
        )
1007 1008 1009 1010
    return render(
        request,
        'users/profil.html',
        {
1011
            'users': users,
1012
            'machines_list': machines,
1013
            'nb_machines': nb_machines,
1014 1015 1016
            'facture_list': factures,
            'ban_list': bans,
            'white_list': whitelists,
chibrac's avatar
chibrac committed
1017
            'user_solde': user_solde,
Gabriel Detraz's avatar
Gabriel Detraz committed
1018
            'solde_activated': Paiement.objects.filter(is_balance=True).exists(),
1019
            'asso_name': AssoOption.objects.first().name,
1020
            'emailaddress_list': users.email_address,
1021 1022
            'local_email_accounts_enabled': (
                OptionalUser.objects.first().local_email_accounts_enabled
1023
            )
lhark's avatar
lhark committed
1024 1025
        }
    )
1026

1027

chirac's avatar
chirac committed
1028
def reset_password(request):
1029
    """ Reintialisation du mot de passe si mdp oublié """
chirac's avatar
chirac committed
1030 1031 1032
    userform = ResetPasswordForm(request.POST or None)
    if userform.is_valid():
        try:
1033 1034 1035 1036
            user = User.objects.get(
                pseudo=userform.cleaned_data['pseudo'],
                email=userform.cleaned_data['email']
            )
chirac's avatar
chirac committed
1037
        except User.DoesNotExist:
1038
            messages.error(request, _("The user doesn't exist."))
1039
            return form(
1040
                {'userform': userform, 'action_name': _("Reset")},
1041 1042 1043
                'users/user.html',
                request
            )
1044
        user.reset_passwd_mail(request)
1045
        messages.success(request, _("An email to reset the password was sent."))
1046
        redirect(reverse('index'))
1047
    return form(
1048
        {'userform': userform, 'action_name': _("Reset")},
1049 1050 1051
        'users/user.html',
        request
    )
chirac's avatar
chirac committed
1052

1053

1054
def process(request, token):
1055
    """Process, lien pour la reinitialisation du mot de passe"""
1056 1057 1058 1059 1060 1061
    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:
1062
        messages.error(request, _("Error: please contact an admin."))
1063
        redirect(reverse('index'))
1064

1065

1066
def process_passwd(request, req):
1067 1068
    """Process le changeemnt de mot de passe, renvoie le formulaire
    demandant le nouveau password"""