forms.py 26.8 KB
Newer Older
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
# 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.
chirac's avatar
chirac committed
23 24
"""
Definition des forms pour l'application users.
25

chirac's avatar
chirac committed
26 27 28 29 30 31 32
Modification, creation de :
    - un user (informations personnelles)
    - un bannissement
    - le mot de passe d'un user
    - une whiteliste
    - un user de service
"""
33

34
from __future__ import unicode_literals
35 36

from django import forms
37
from django.forms import ModelForm, Form
38
from django.contrib.auth.forms import ReadOnlyPasswordHashField
Gabriel Detraz's avatar
Gabriel Detraz committed
39
from django.core.validators import MinLengthValidator
40
from django.utils import timezone
41
from django.contrib.auth.models import Group, Permission
42
from django.utils.translation import ugettext_lazy as _
Alexandre Iooss's avatar
Alexandre Iooss committed
43
from django.utils.safestring import mark_safe
44

45 46
from machines.models import Interface, Machine, Nas
from topologie.models import Port
chirac's avatar
chirac committed
47
from preferences.models import OptionalUser
48
from re2o.utils import remove_user_room, get_input_formats_help_text
49 50 51
from re2o.mixins import FormRevMixin
from re2o.field_permissions import FieldPermissionFormMixin

edpibu's avatar
edpibu committed
52 53
from preferences.models import GeneralOption

root's avatar
root committed
54 55
from .widgets import DateTimePicker

56 57 58 59 60 61
from .models import (
    User,
    ServiceUser,
    School,
    ListRight,
    Whitelist,
62
    EMailAddress,
63 64 65 66 67
    ListShell,
    Ban,
    Adherent,
    Club
)
68

69

70
class PassForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm):
chirac's avatar
chirac committed
71 72 73
    """Formulaire de changement de mot de passe. Verifie que les 2
    nouveaux mots de passe renseignés sont identiques et respectent
    une norme"""
74
    selfpasswd = forms.CharField(
75
        label=_("Current password"),
76 77 78
        max_length=255,
        widget=forms.PasswordInput
    )
chirac's avatar
chirac committed
79
    passwd1 = forms.CharField(
80
        label=_("New password"),
chirac's avatar
chirac committed
81 82 83 84 85
        max_length=255,
        validators=[MinLengthValidator(8)],
        widget=forms.PasswordInput
    )
    passwd2 = forms.CharField(
86
        label=_("New password confirmation"),
chirac's avatar
chirac committed
87 88 89 90
        max_length=255,
        validators=[MinLengthValidator(8)],
        widget=forms.PasswordInput
    )
91

92 93 94 95
    class Meta:
        model = User
        fields = []

96
    def clean_passwd2(self):
chirac's avatar
chirac committed
97
        """Verifie que passwd1 et 2 sont identiques"""
98 99 100 101
        # Check that the two password entries match
        password1 = self.cleaned_data.get("passwd1")
        password2 = self.cleaned_data.get("passwd2")
        if password1 and password2 and password1 != password2:
102
            raise forms.ValidationError(
103
                _("The new passwords don't match.")
104
            )
105
        return password2
106

107 108
    def clean_selfpasswd(self):
        """Verifie si il y a lieu que le mdp self est correct"""
109
        if not self.instance.check_password(
110 111
                self.cleaned_data.get("selfpasswd")
            ):
112
            raise forms.ValidationError(_("The current password is incorrect."))
113 114 115 116 117 118 119 120
        return

    def save(self, commit=True):
        """Changement du mot de passe"""
        user = super(PassForm, self).save(commit=False)
        user.set_password(self.cleaned_data.get("passwd1"))
        user.save()

chirac's avatar
chirac committed
121

122
class UserCreationForm(FormRevMixin, forms.ModelForm):
123
    """A form for creating new users. Includes all the required
chirac's avatar
chirac committed
124 125 126 127 128 129
    fields, plus a repeated password.

    Formulaire pour la création d'un user. N'est utilisé que pour
    l'admin, lors de la creation d'un user par admin. Inclu tous les
    champs obligatoires"""
    password1 = forms.CharField(
130
        label=_("Password"),
chirac's avatar
chirac committed
131 132 133 134 135
        widget=forms.PasswordInput,
        validators=[MinLengthValidator(8)],
        max_length=255
    )
    password2 = forms.CharField(
136
        label=_("Password confirmation"),
chirac's avatar
chirac committed
137 138 139 140
        widget=forms.PasswordInput,
        validators=[MinLengthValidator(8)],
        max_length=255
    )
141
    is_admin = forms.BooleanField(label=_("Is admin"))
142

143
    def __init__(self, *args, **kwargs):
144
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
145 146
        super(UserCreationForm, self).__init__(*args, prefix=prefix, **kwargs)

147 148 149 150
    def clean_email(self):
        if not OptionalUser.objects.first().local_email_domain in self.cleaned_data.get('email'):
            return self.cleaned_data.get('email').lower()
        else:
151 152
            raise forms.ValidationError(_("You can't use an internal address"
                                          " as your external address."))
153

154
    class Meta:
155
        model = Adherent
156
        fields = ('pseudo', 'surname', 'email')
157 158

    def clean_password2(self):
chirac's avatar
chirac committed
159
        """Verifie que password1 et 2 sont identiques"""
160 161 162 163
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
164
            raise forms.ValidationError(_("The passwords don't match."))
165 166 167 168 169 170 171 172 173 174
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        user.save()
        user.is_admin = self.cleaned_data.get("is_admin")
        return user

chirac's avatar
chirac committed
175

176
class ServiceUserCreationForm(FormRevMixin, forms.ModelForm):
chirac's avatar
chirac committed
177
    """A form for creating new users. Includes all the required
chirac's avatar
chirac committed
178 179 180 181 182
    fields, plus a repeated password.

    Formulaire pour la creation de nouveaux serviceusers.
    Requiert seulement un mot de passe; et un pseudo"""
    password1 = forms.CharField(
183
        label=_("Password"),
chirac's avatar
chirac committed
184 185 186 187 188
        widget=forms.PasswordInput,
        min_length=8,
        max_length=255
    )
    password2 = forms.CharField(
189
        label=_("Password confirmation"),
chirac's avatar
chirac committed
190 191 192 193
        widget=forms.PasswordInput,
        min_length=8,
        max_length=255
    )
chirac's avatar
chirac committed
194

195
    def __init__(self, *args, **kwargs):
196
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
chirac's avatar
chirac committed
197 198 199 200 201
        super(ServiceUserCreationForm, self).__init__(
            *args,
            prefix=prefix,
            **kwargs
        )
202

chirac's avatar
chirac committed
203 204 205 206 207
    class Meta:
        model = ServiceUser
        fields = ('pseudo',)

    def clean_password2(self):
chirac's avatar
chirac committed
208
        """Verifie que password1 et 2 sont indentiques"""
chirac's avatar
chirac committed
209 210 211 212
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
213
            raise forms.ValidationError(_("The passwords don't match."))
chirac's avatar
chirac committed
214 215 216 217 218 219 220 221
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(ServiceUserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        user.save()
        return user
222

chirac's avatar
chirac committed
223

224
class UserChangeForm(FormRevMixin, forms.ModelForm):
225 226 227
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    password hash display field.
chirac's avatar
chirac committed
228 229

    Formulaire pour la modification d'un user coté admin
230 231
    """
    password = ReadOnlyPasswordHashField()
232
    is_admin = forms.BooleanField(label=_("Is admin"), required=False)
233 234

    class Meta:
235
        model = Adherent
236
        fields = ('pseudo', 'password', 'surname', 'email')
237 238

    def __init__(self, *args, **kwargs):
239
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
240
        super(UserChangeForm, self).__init__(*args, prefix=prefix, **kwargs)
241
        print(_("User is admin: %s") % kwargs['instance'].is_admin)
242 243 244
        self.initial['is_admin'] = kwargs['instance'].is_admin

    def clean_password(self):
chirac's avatar
chirac committed
245
        """Dummy fun"""
246 247 248 249 250 251 252 253 254 255 256 257
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserChangeForm, self).save(commit=False)
        user.is_admin = self.cleaned_data.get("is_admin")
        if commit:
            user.save()
        return user
chirac's avatar
chirac committed
258

chirac's avatar
chirac committed
259

260
class ServiceUserChangeForm(FormRevMixin, forms.ModelForm):
chirac's avatar
chirac committed
261 262 263
    """A form for updating users. Includes all the fields on
    the user, but replaces the password field with admin's
    password hash display field.
chirac's avatar
chirac committed
264 265

    Formulaire pour l'edition des service users coté admin
chirac's avatar
chirac committed
266 267 268
    """
    password = ReadOnlyPasswordHashField()

269
    def __init__(self, *args, **kwargs):
270
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
chirac's avatar
chirac committed
271 272 273 274 275
        super(ServiceUserChangeForm, self).__init__(
            *args,
            prefix=prefix,
            **kwargs
        )
276

chirac's avatar
chirac committed
277 278 279 280 281
    class Meta:
        model = ServiceUser
        fields = ('pseudo',)

    def clean_password(self):
chirac's avatar
chirac committed
282
        """Dummy fun"""
chirac's avatar
chirac committed
283 284
        return self.initial["password"]

chirac's avatar
chirac committed
285

chirac's avatar
chirac committed
286
class ResetPasswordForm(forms.Form):
chirac's avatar
chirac committed
287 288
    """Formulaire de demande de reinitialisation de mot de passe,
    mdp oublié"""
289
    pseudo = forms.CharField(label=_("Username"), max_length=255)
chirac's avatar
chirac committed
290
    email = forms.EmailField(max_length=255)
291

chirac's avatar
chirac committed
292

293
class MassArchiveForm(forms.Form):
chirac's avatar
chirac committed
294 295 296
    """Formulaire d'archivage des users inactif. Prend en argument
    du formulaire la date de depart avant laquelle archiver les
    users"""
297 298 299
    date = forms.DateTimeField(help_text='%d/%m/%y')

    def clean(self):
chirac's avatar
chirac committed
300
        cleaned_data = super(MassArchiveForm, self).clean()
301 302
        date = cleaned_data.get("date")
        if date:
303
            if date > timezone.now():
304 305 306
                raise forms.ValidationError(_("Impossible to archive users"
                                              " whose end access date is in"
                                              " the future."))
chirac's avatar
chirac committed
307

308

309
class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
chirac's avatar
chirac committed
310 311 312
    """Formulaire de base d'edition d'un user. Formulaire de base, utilisé
    pour l'edition de self par self ou un cableur. On formate les champs
    avec des label plus jolis"""
313
    def __init__(self, *args, **kwargs):
314
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
315
        super(AdherentForm, self).__init__(*args, prefix=prefix, **kwargs)
316 317 318 319 320 321 322 323
        self.fields['name'].label = _("First name")
        self.fields['surname'].label = _("Surname")
        self.fields['email'].label = _("Email address")
        self.fields['school'].label = _("School")
        self.fields['comment'].label = _("Comment")
        self.fields['room'].label = _("Room")
        self.fields['room'].empty_label = _("No room")
        self.fields['school'].empty_label = _("Select a school")
324

325 326 327 328
    def clean_email(self):
        if not OptionalUser.objects.first().local_email_domain in self.cleaned_data.get('email'):
            return self.cleaned_data.get('email').lower()
        else:
329 330 331
            raise forms.ValidationError(
                    _("You can't use a {} address.").format(
                        OptionalUser.objects.first().local_email_domain))
332

333
    class Meta:
334
        model = Adherent
335 336 337 338
        fields = [
            'name',
            'surname',
            'pseudo',
339
            'email',
340 341
            'school',
            'comment',
342
            'telephone',
343
            'room'
344 345
        ]

346

347
    def clean_telephone(self):
chirac's avatar
chirac committed
348 349
        """Verifie que le tel est présent si 'option est validée
        dans preferences"""
350
        telephone = self.cleaned_data['telephone']
351
        if not telephone and OptionalUser.get_cached_value('is_tel_mandatory'):
chirac's avatar
chirac committed
352
            raise forms.ValidationError(
353
                _("A valid telephone number is required.")
chirac's avatar
chirac committed
354
            )
355 356
        return telephone

357
    force = forms.BooleanField(
358
        label=_("Force the move?"),
359 360 361 362 363 364 365 366
        initial=False,
        required=False
    )

    def clean_force(self):
        """On supprime l'ancien user de la chambre si et seulement si la
        case est cochée"""
        if self.cleaned_data.get('force', False):
367
            remove_user_room(self.cleaned_data.get('room'))
368
        return
chirac's avatar
chirac committed
369

370 371 372 373 374
class AdherentCreationForm(AdherentForm):
    """Formulaire de création d'un user.
    AdherentForm auquel on ajoute une checkbox afin d'éviter les
    doublons d'utilisateurs"""

edpibu's avatar
edpibu committed
375 376 377 378 379 380
    # Champ permettant d'éviter au maxium les doublons d'utilisateurs
    former_user_check_info = _("If you already have an account, please use it. "\
                           + "If your lost access to it, please consider "\
                           + "using the forgotten password button on the "\
                           + "login page or contacting support.")
    former_user_check = forms.BooleanField(required=True, help_text=former_user_check_info)
381
    former_user_check.label = _("I certifie that I have not had an account before")
382

edpibu's avatar
edpibu committed
383 384
    # Checkbox for GTU
    gtu_check = forms.BooleanField(required=True)
385 386
    gtu_check.label = mark_safe("{} <a href='/media/{}' download='CGU'>{}</a>{}".format(
        _("I commit to accept the"), GeneralOption.get_cached_value('GTU'), _("General Terms of Use"), _(".")))
edpibu's avatar
edpibu committed
387

edpibu's avatar
edpibu committed
388 389
    def __init__(self, *args, **kwargs):
        super(AdherentCreationForm, self).__init__(*args, **kwargs)
390 391 392 393

class AdherentEditForm(AdherentForm):
    """Formulaire d'édition d'un user.
    AdherentForm incluant la modification des champs gpg et shell"""
394
    def __init__(self, *args, **kwargs):
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
       super(AdherentEditForm, self).__init__(*args, **kwargs)
       self.fields['gpg_fingerprint'].widget.attrs['placeholder'] = _("Leave empty if you don't have any GPG key.")
       if 'shell' in self.fields:
           self.fields['shell'].empty_label = _("Default shell")

    def clean_gpg_fingerprint(self):
        """Format the GPG fingerprint"""
        gpg_fingerprint = self.cleaned_data.get('gpg_fingerprint', None)
        if gpg_fingerprint:
            return gpg_fingerprint.replace(' ', '').upper()

    class Meta:
        model = Adherent
        fields = [
            'name',
            'surname',
            'pseudo',
            'email',
            'school',
            'comment',
            'telephone',
            'room',
            'shell',
            'gpg_fingerprint'
        ]
420

421
class ClubForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
422 423 424 425 426
    """Formulaire de base d'edition d'un user. Formulaire de base, utilisé
    pour l'edition de self par self ou un cableur. On formate les champs
    avec des label plus jolis"""
    def __init__(self, *args, **kwargs):
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
427
        super(ClubForm, self).__init__(*args, prefix=prefix, **kwargs)
428 429 430 431 432 433 434
        self.fields['surname'].label = _("Name")
        self.fields['school'].label = _("School")
        self.fields['comment'].label = _("Comment")
        self.fields['room'].label = _("Room")
        self.fields['room'].empty_label = _("No room")
        self.fields['school'].empty_label = _("Select a school")
        self.fields['mailing'].label = _("Use a mailing list")
435 436 437 438 439 440 441 442 443 444

    class Meta:
        model = Club
        fields = [
            'surname',
            'pseudo',
            'school',
            'comment',
            'room',
            'telephone',
445
            'shell',
446
            'mailing'
447 448 449 450 451 452
        ]

    def clean_telephone(self):
        """Verifie que le tel est présent si 'option est validée
        dans preferences"""
        telephone = self.cleaned_data['telephone']
453
        if not telephone and OptionalUser.get_cached_value('is_tel_mandatory'):
454
            raise forms.ValidationError(
455
                _("A valid telephone number is required.")
456 457 458 459
            )
        return telephone


460
class ClubAdminandMembersForm(FormRevMixin, ModelForm):
461 462 463 464 465 466 467 468
    """Permet d'éditer la liste des membres et des administrateurs
    d'un club"""
    class Meta:
        model = Club
        fields = ['administrators', 'members']

    def __init__(self, *args, **kwargs):
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
469 470 471 472 473
        super(ClubAdminandMembersForm, self).__init__(
            *args,
            prefix=prefix,
            **kwargs
        )
474 475


476
class PasswordForm(FormRevMixin, ModelForm):
chirac's avatar
chirac committed
477 478
    """ Formulaire de changement brut de mot de passe.
    Ne pas utiliser sans traitement"""
479 480 481 482
    class Meta:
        model = User
        fields = ['password', 'pwd_ntlm']

483
    def __init__(self, *args, **kwargs):
484
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
485 486
        super(PasswordForm, self).__init__(*args, prefix=prefix, **kwargs)

chirac's avatar
chirac committed
487

488
class ServiceUserForm(FormRevMixin, ModelForm):
chirac's avatar
chirac committed
489
    """ Modification d'un service user"""
chirac's avatar
chirac committed
490
    password = forms.CharField(
491
        label=_("New password"),
chirac's avatar
chirac committed
492 493 494 495 496
        max_length=255,
        validators=[MinLengthValidator(8)],
        widget=forms.PasswordInput,
        required=False
    )
497 498 499

    class Meta:
        model = ServiceUser
500
        fields = ('pseudo', 'access_group','comment')
501

502
    def __init__(self, *args, **kwargs):
503
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
504 505
        super(ServiceUserForm, self).__init__(*args, prefix=prefix, **kwargs)

506 507 508 509 510 511 512
    def save(self, commit=True):
        """Changement du mot de passe"""
        user = super(ServiceUserForm, self).save(commit=False)
        if self.cleaned_data['password']:
            user.set_password(self.cleaned_data.get("password"))
        user.save()

chirac's avatar
chirac committed
513

514
class EditServiceUserForm(ServiceUserForm):
chirac's avatar
chirac committed
515 516
    """Formulaire d'edition de base d'un service user. Ne permet
    d'editer que son group d'acl et son commentaire"""
517
    class Meta(ServiceUserForm.Meta):
chirac's avatar
chirac committed
518 519
        fields = ['access_group', 'comment']

520

521
class StateForm(FormRevMixin, ModelForm):
chirac's avatar
chirac committed
522
    """ Changement de l'état d'un user"""
523 524 525 526
    class Meta:
        model = User
        fields = ['state']

527
    def __init__(self, *args, **kwargs):
528
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
529 530
        super(StateForm, self).__init__(*args, prefix=prefix, **kwargs)

531

Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
532
class GroupForm(FieldPermissionFormMixin, FormRevMixin, ModelForm):
533 534 535 536 537 538 539 540 541
    """ Gestion des groupes d'un user"""
    groups = forms.ModelMultipleChoiceField(
        Group.objects.all(),
        widget=forms.CheckboxSelectMultiple,
        required=False
    )

    class Meta:
        model = User
542
        fields = ['is_superuser', 'groups']
543 544 545 546

    def __init__(self, *args, **kwargs):
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
        super(GroupForm, self).__init__(*args, prefix=prefix, **kwargs)
Levy--Falk Hugo's avatar
Levy--Falk Hugo committed
547
        if 'is_superuser' in self.fields:
548
            self.fields['is_superuser'].label = _("Superuser")
549 550


551
class SchoolForm(FormRevMixin, ModelForm):
chirac's avatar
chirac committed
552
    """Edition, creation d'un école"""
553 554 555 556 557
    class Meta:
        model = School
        fields = ['name']

    def __init__(self, *args, **kwargs):
558
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
559
        super(SchoolForm, self).__init__(*args, prefix=prefix, **kwargs)
560
        self.fields['name'].label = _("School")
561

chirac's avatar
chirac committed
562

563
class ShellForm(FormRevMixin, ModelForm):
564 565 566 567 568 569 570 571
    """Edition, creation d'un école"""
    class Meta:
        model = ListShell
        fields = ['shell']

    def __init__(self, *args, **kwargs):
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
        super(ShellForm, self).__init__(*args, prefix=prefix, **kwargs)
572
        self.fields['shell'].label = _("Shell name")
573 574


575
class ListRightForm(FormRevMixin, ModelForm):
chirac's avatar
chirac committed
576
    """Edition, d'un groupe , équivalent à un droit
577
    Ne permet pas d'editer le gid, car il sert de primary key"""
578
    permissions = forms.ModelMultipleChoiceField(
579
        Permission.objects.all().select_related('content_type'),
580 581 582 583
        widget=forms.CheckboxSelectMultiple,
        required=False
    )

584 585
    class Meta:
        model = ListRight
586
        fields = ('name', 'unix_name', 'critical', 'permissions', 'details')
587 588

    def __init__(self, *args, **kwargs):
589
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
590
        super(ListRightForm, self).__init__(*args, prefix=prefix, **kwargs)
591
        self.fields['unix_name'].label = _("Name of the group of rights")
592

chirac's avatar
chirac committed
593

594
class NewListRightForm(ListRightForm):
chirac's avatar
chirac committed
595
    """Ajout d'un groupe/list de droit """
596
    class Meta(ListRightForm.Meta):
597 598
        fields = ('name', 'unix_name', 'gid', 'critical', 'permissions',
                  'details')
599 600 601

    def __init__(self, *args, **kwargs):
        super(NewListRightForm, self).__init__(*args, **kwargs)
602 603
        self.fields['gid'].label = _("GID. Warning: this field must not be"
                                     " edited after creation.")
chirac's avatar
chirac committed
604

605

606
class DelListRightForm(Form):
chirac's avatar
chirac committed
607 608
    """Suppression d'un ou plusieurs groupes"""
    listrights = forms.ModelMultipleChoiceField(
609
        queryset=ListRight.objects.none(),
610
        label=_("Current groups of rights"),
chirac's avatar
chirac committed
611 612 613
        widget=forms.CheckboxSelectMultiple
    )

614 615 616 617
    def __init__(self, *args, **kwargs):
        instances = kwargs.pop('instances', None)
        super(DelListRightForm, self).__init__(*args, **kwargs)
        if instances:
618
            self.fields['listrights'].queryset = instances
619
        else:
620
            self.fields['listrights'].queryset = ListRight.objects.all()
621

622

623
class DelSchoolForm(Form):
chirac's avatar
chirac committed
624 625
    """Suppression d'une ou plusieurs écoles"""
    schools = forms.ModelMultipleChoiceField(
626
        queryset=School.objects.none(),
627
        label=_("Current schools"),
chirac's avatar
chirac committed
628 629 630
        widget=forms.CheckboxSelectMultiple
    )

631
    def __init__(self, *args, **kwargs):
632
        instances = kwargs.pop('instances', None)
633
        super(DelSchoolForm, self).__init__(*args, **kwargs)
634 635 636 637
        if instances:
            self.fields['schools'].queryset = instances
        else:
            self.fields['schools'].queryset = School.objects.all()
638

639

640
class BanForm(FormRevMixin, ModelForm):
chirac's avatar
chirac committed
641
    """Creation, edition d'un objet bannissement"""
642
    def __init__(self, *args, **kwargs):
643
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
644
        super(BanForm, self).__init__(*args, prefix=prefix, **kwargs)
645
        self.fields['date_end'].label = _("End date")
646
        self.fields['date_end'].localize = False
647 648 649 650

    class Meta:
        model = Ban
        exclude = ['user']
651
        widgets = {'date_end':DateTimePicker}
652 653


654
class WhitelistForm(FormRevMixin, ModelForm):
chirac's avatar
chirac committed
655
    """Creation, edition d'un objet whitelist"""
656
    def __init__(self, *args, **kwargs):
657
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
658
        super(WhitelistForm, self).__init__(*args, prefix=prefix, **kwargs)
659
        self.fields['date_end'].label = _("End date")
root's avatar
root committed
660
        self.fields['date_end'].localize = False
661 662 663 664

    class Meta:
        model = Whitelist
        exclude = ['user']
root's avatar
root committed
665
        widgets = {'date_end':DateTimePicker}
666 667


668 669
class EMailAddressForm(FormRevMixin, ModelForm):
    """Create and edit a local email address"""
670 671
    def __init__(self, *args, **kwargs):
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
672
        super(EMailAddressForm, self).__init__(*args, prefix=prefix, **kwargs)
673 674
        self.fields['local_part'].label = _("Local part of the email address")
        self.fields['local_part'].help_text = _("Can't contain @")
675

676 677
    def clean_local_part(self):
        return self.cleaned_data.get('local_part').lower()
678 679

    class Meta:
680
        model = EMailAddress
681
        exclude = ['user']
682

683 684 685

class EmailSettingsForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
    """Edit email-related settings"""
686 687
    def __init__(self, *args, **kwargs):
        prefix = kwargs.pop('prefix', self.Meta.model.__name__)
688
        super(EmailSettingsForm, self).__init__(*args, prefix=prefix, **kwargs)
689
        self.fields['email'].label = _("Main email address")
690
        if 'local_email_redirect' in self.fields:
691
            self.fields['local_email_redirect'].label = _("Redirect local emails")
692
        if 'local_email_enabled' in self.fields:
693
            self.fields['local_email_enabled'].label = _("Use local emails")
694

695 696 697 698
    def clean_email(self):
        if not OptionalUser.objects.first().local_email_domain in self.cleaned_data.get('email'):
            return self.cleaned_data.get('email').lower()
        else:
699 700 701
            raise forms.ValidationError(
                    _("You can't use a {} address.").format(
                        OptionalUser.objects.first().local_email_domain))
702

703
    class Meta:
704
        model = User
705
        fields = ['email','local_email_enabled', 'local_email_redirect']
706

707 708 709 710 711 712 713 714 715 716 717 718 719 720 721

class InitialRegisterForm(forms.Form):
    register_room = forms.BooleanField(required=False)
    register_machine = forms.BooleanField(required=False)

    def __init__(self, *args, **kwargs):
        switch_ip = kwargs.pop('switch_ip')
        switch_port = kwargs.pop('switch_port')
        client_mac = kwargs.pop('client_mac')
        self.user = kwargs.pop('user')
        if switch_ip and switch_port:
            # Looking for a port
            port = Port.objects.filter(switch__interface__ipv4__ipv4=switch_ip, port=switch_port).first()
            # If a port exists, checking there is a room AND radius
            if port:
722
                if port.get_port_profil.radius_type != 'NO' and port.get_port_profil.radius_mode == 'STRICT' and hasattr(port, 'room'):
723 724 725 726 727 728 729 730 731 732
                    # Requesting user is not in this room ?
                    if self.user.room != port.room:
                        self.new_room = port.room
        if client_mac and switch_ip:
            # If this interface doesn't already exists
            if not Interface.objects.filter(mac_address=client_mac):
                self.mac_address = client_mac
                self.nas_type = Nas.objects.filter(nas_type__interface__ipv4__ipv4=switch_ip).first()
        super(InitialRegisterForm, self).__init__(*args, **kwargs)
        if hasattr(self, 'new_room'):
733
            self.fields['register_room'].label = _("This room is my room")
734 735 736
        else:
            self.fields.pop('register_room')
        if hasattr(self, 'mac_address'):
737
            self.fields['register_machine'].label = _("This new connected device is mine")
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
        else:
            self.fields.pop('register_machine')

    def clean_register_room(self):
        if self.cleaned_data['register_room']:
            if self.user.is_class_adherent:
                remove_user_room(self.new_room)
                user = self.user.adherent
                user.room = self.new_room
                user.save()
            if self.user.is_class_club:
                user = self.user.club
                user.room = self.new_room
                user.save()

    def clean_register_machine(self):
        if self.cleaned_data['register_machine']:
            if self.mac_address and self.nas_type:
                self.user.autoregister_machine(self.mac_address, self.nas_type)