views.py 36.9 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
73
from topologie.models import Port
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
    EditServiceUserForm,
    ServiceUserForm,
    ListRightForm,
102
    AdherentCreationForm,
103
    AdherentEditForm,
104 105 106 107
    ClubForm,
    MassArchiveForm,
    PassForm,
    ResetPasswordForm,
108
    ClubAdminandMembersForm,
109 110
    GroupForm,
    InitialRegisterForm
111
)
112

113

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

142

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


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


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

226

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

246

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


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

289

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


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


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

328

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

348

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

363

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

391

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

410

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

428

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

460

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

483

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

501

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

527

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

552

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

570

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

597

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

614

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

632

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

659

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


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


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


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

724

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

745

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

771

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

801

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

817

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


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

853

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

873

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

893

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


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

937

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

949

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

958

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

1029

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

1055

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