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 36.6 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
    ClubAdminandMembersForm,
108 109
    GroupForm,
    InitialRegisterForm
110
)
111

112

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, user=request.user)
118 119
    GTU_sum_up = GeneralOption.get_cached_value('GTU_sum_up')
    GTU = GeneralOption.get_cached_value('GTU')
120
    if user.is_valid():
121
        user = user.save()
122
        user.reset_passwd_mail(request)
123 124
        messages.success(request, _("The user %s was created, an email to set"
                                    " the password was sent.") % user.pseudo)
125 126
        return redirect(reverse(
            'users:profil',
127 128 129 130 131 132 133 134
            kwargs={'userid': str(user.id)}
        ))
    return form(
        {
            'userform': user,
            'GTU_sum_up': GTU_sum_up,
            'GTU': GTU,
            'showCGU': True,
135
            'action_name': _("Create a user")
136 137 138 139
        },
        'users/user.html',
        request
    )
140

141

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


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


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

225

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

245

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


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

288

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


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


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

327

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

347

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

362

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

390

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

409

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

427

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

459

chirac's avatar
chirac committed
460
@login_required
461
@can_edit(Whitelist)
462
def edit_whitelist(request, whitelist_instance, **_kwargs):
463 464 465 466 467 468 469 470
    """ 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
471
    if whitelist.is_valid():
472 473
        if whitelist.changed_data:
            whitelist.save()
474
            messages.success(request, _("The whitelist was edited."))
475
        return redirect(reverse('users:index'))
476
    return form(
477
        {'userform': whitelist, 'action_name': _("Edit a whitelist")},
478 479 480
        'users/user.html',
        request
    )
chirac's avatar
chirac committed
481

482

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

500

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

526

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

551

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

569

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

596

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

613

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

631

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

658

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


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


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


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

723

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

744

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

770

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

800

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

816

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


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

852

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

872

chirac's avatar
chirac committed
873
@login_required
874
@can_view_all(School)
875
def index_school(request):
876
    """ Affiche l'ensemble des établissement"""
877
    school_list = School.objects.order_by('name')
878 879 880 881 882 883 884
    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
    )
885
    school_list = re2o_paginator(request, school_list, pagination_number)
886 887 888 889 890 891
    return render(
        request,
        'users/index_schools.html',
        {'school_list': school_list}
    )

892

893 894 895 896 897 898 899 900 901 902 903 904
@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}
    )


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

936

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

948

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

957

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

1028

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

1054

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

1066