8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-27 09:23:47 +00:00
re2o/users/forms.py

965 lines
33 KiB
Python
Raw Normal View History

# -*- mode: python; coding: utf-8 -*-
2017-01-15 23:01:18 +00:00
# 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.
#
2020-04-17 14:48:27 +00:00
# Copyright © 2017-2020 Gabriel Détraz
# Copyright © 2017-2020 Lara Kermarec
# Copyright © 2017-2020 Augustin Lemesle
# Copyright © 2017-2020 Hugo Levy--Falk
# Copyright © 2017-2020 Jean-Romain Garnier
2017-01-15 23:01:18 +00:00
#
# 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.
2017-10-14 18:18:12 +00:00
"""
Definition des forms pour l'application users.
2017-01-15 23:01:18 +00:00
2017-10-14 18:18:12 +00:00
Modification, creation de :
- un user (informations personnelles)
- un bannissement
- le mot de passe d'un user
- une whiteliste
- un user de service
"""
from __future__ import unicode_literals
from django import forms
from django.forms import ModelForm, Form
from django.contrib.auth.forms import ReadOnlyPasswordHashField
2020-04-19 20:40:49 +00:00
from django.contrib.auth.password_validation import validate_password, password_validators_help_text_html
2016-11-21 19:14:25 +00:00
from django.core.validators import MinLengthValidator
from django.utils import timezone
2019-09-05 17:55:54 +00:00
from django.utils.functional import lazy
2017-12-31 16:11:19 +00:00
from django.contrib.auth.models import Group, Permission
2018-08-15 17:15:26 +00:00
from django.utils.translation import ugettext_lazy as _
2018-09-20 13:38:36 +00:00
from django.utils.safestring import mark_safe
from machines.models import Interface, Machine, Nas
from topologie.models import Port
2017-10-14 18:18:12 +00:00
from preferences.models import OptionalUser
from re2o.utils import remove_user_room
from re2o.base import get_input_formats_help_text
2018-04-14 23:16:49 +00:00
from re2o.mixins import FormRevMixin
from re2o.field_permissions import FieldPermissionFormMixin
2018-09-20 08:57:31 +00:00
from preferences.models import GeneralOption
2018-05-05 15:58:13 +00:00
from .widgets import DateTimePicker
from .models import (
User,
ServiceUser,
School,
ListRight,
Whitelist,
2018-08-01 11:06:25 +00:00
EMailAddress,
ListShell,
Ban,
Adherent,
Club,
)
class PassForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm):
2017-10-14 18:18:12 +00:00
"""Formulaire de changement de mot de passe. Verifie que les 2
nouveaux mots de passe renseignés sont identiques et respectent
une norme"""
selfpasswd = forms.CharField(
label=_("Current password"), max_length=255, widget=forms.PasswordInput
)
2017-10-14 18:18:12 +00:00
passwd1 = forms.CharField(
2018-08-15 17:15:26 +00:00
label=_("New password"),
2017-10-14 18:18:12 +00:00
max_length=255,
widget=forms.PasswordInput,
2020-04-19 20:40:49 +00:00
help_text=password_validators_help_text_html()
2017-10-14 18:18:12 +00:00
)
passwd2 = forms.CharField(
2018-08-15 17:15:26 +00:00
label=_("New password confirmation"),
2017-10-14 18:18:12 +00:00
max_length=255,
widget=forms.PasswordInput,
2017-10-14 18:18:12 +00:00
)
class Meta:
model = User
fields = []
def clean_passwd2(self):
2017-10-14 18:18:12 +00:00
"""Verifie que passwd1 et 2 sont identiques"""
# 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:
raise forms.ValidationError(_("The new passwords don't match."))
validate_password(password1, user=self.instance)
return password2
def clean_selfpasswd(self):
"""Verifie si il y a lieu que le mdp self est correct"""
if not self.instance.check_password(self.cleaned_data.get("selfpasswd")):
2018-08-15 17:15:26 +00:00
raise forms.ValidationError(_("The current password is incorrect."))
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.state = User.STATE_NOT_YET_ACTIVE
user.set_active()
2020-04-16 20:06:14 +00:00
user.save()
class UserCreationForm(FormRevMixin, forms.ModelForm):
"""A form for creating new users. Includes all the required
2017-10-14 18:18:12 +00:00
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"""
2017-10-14 18:18:12 +00:00
password1 = forms.CharField(
2018-08-15 17:15:26 +00:00
label=_("Password"),
2017-10-14 18:18:12 +00:00
widget=forms.PasswordInput,
max_length=255,
2020-04-19 20:40:49 +00:00
help_text=password_validators_help_text_html()
2017-10-14 18:18:12 +00:00
)
password2 = forms.CharField(
2018-08-15 17:15:26 +00:00
label=_("Password confirmation"),
2017-10-14 18:18:12 +00:00
widget=forms.PasswordInput,
max_length=255,
2017-10-14 18:18:12 +00:00
)
2018-08-15 17:15:26 +00:00
is_admin = forms.BooleanField(label=_("Is admin"))
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(UserCreationForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields["email"].required = True
def clean_email(self):
2020-04-21 14:47:09 +00:00
new_email = self.cleaned_data.get("email")
if not new_email or len(new_email) == 0:
raise forms.ValidationError(
_("Email field cannot be empty.")
)
if not OptionalUser.objects.first().local_email_domain in new_email:
return new_email.lower()
else:
raise forms.ValidationError(
2019-11-20 00:52:11 +00:00
_("You can't use an internal address as your external address.")
)
class Meta:
model = Adherent
fields = ("pseudo", "surname", "email")
def clean_password2(self):
2017-10-14 18:18:12 +00:00
"""Verifie que password1 et 2 sont identiques"""
# 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:
2018-08-15 17:15:26 +00:00
raise forms.ValidationError(_("The passwords don't match."))
validate_password(password1)
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
2017-10-14 18:18:12 +00:00
class ServiceUserCreationForm(FormRevMixin, forms.ModelForm):
2016-07-31 03:03:07 +00:00
"""A form for creating new users. Includes all the required
2017-10-14 18:18:12 +00:00
fields, plus a repeated password.
Formulaire pour la creation de nouveaux serviceusers.
Requiert seulement un mot de passe; et un pseudo"""
2017-10-14 18:18:12 +00:00
password1 = forms.CharField(
label=_("Password"), widget=forms.PasswordInput, min_length=8, max_length=255
2017-10-14 18:18:12 +00:00
)
password2 = forms.CharField(
2018-08-15 17:15:26 +00:00
label=_("Password confirmation"),
2017-10-14 18:18:12 +00:00
widget=forms.PasswordInput,
min_length=8,
max_length=255,
2017-10-14 18:18:12 +00:00
)
2016-07-31 03:03:07 +00:00
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ServiceUserCreationForm, self).__init__(*args, prefix=prefix, **kwargs)
2016-07-31 03:03:07 +00:00
class Meta:
model = ServiceUser
fields = ("pseudo",)
2016-07-31 03:03:07 +00:00
def clean_password2(self):
2017-10-14 18:18:12 +00:00
"""Verifie que password1 et 2 sont indentiques"""
2016-07-31 03:03:07 +00:00
# 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:
2018-08-15 17:15:26 +00:00
raise forms.ValidationError(_("The passwords don't match."))
2016-07-31 03:03:07 +00:00
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
2017-10-14 18:18:12 +00:00
class UserChangeForm(FormRevMixin, forms.ModelForm):
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
2017-10-14 18:18:12 +00:00
Formulaire pour la modification d'un user coté admin
"""
password = ReadOnlyPasswordHashField()
2018-08-15 17:15:26 +00:00
is_admin = forms.BooleanField(label=_("Is admin"), required=False)
class Meta:
model = Adherent
fields = ("pseudo", "password", "surname", "email")
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(UserChangeForm, self).__init__(*args, prefix=prefix, **kwargs)
print(_("User is admin: %s") % kwargs["instance"].is_admin)
self.initial["is_admin"] = kwargs["instance"].is_admin
def clean_password(self):
2017-10-14 18:18:12 +00:00
"""Dummy fun"""
# 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
2016-07-20 10:06:33 +00:00
2017-10-14 18:18:12 +00:00
class ServiceUserChangeForm(FormRevMixin, forms.ModelForm):
2016-07-31 03:03:07 +00:00
"""A form for updating users. Includes all the fields on
the user, but replaces the password field with admin's
password hash display field.
2017-10-14 18:18:12 +00:00
Formulaire pour l'edition des service users coté admin
2016-07-31 03:03:07 +00:00
"""
2016-07-31 03:03:07 +00:00
password = ReadOnlyPasswordHashField()
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ServiceUserChangeForm, self).__init__(*args, prefix=prefix, **kwargs)
2016-07-31 03:03:07 +00:00
class Meta:
model = ServiceUser
fields = ("pseudo",)
2016-07-31 03:03:07 +00:00
def clean_password(self):
2017-10-14 18:18:12 +00:00
"""Dummy fun"""
2016-07-31 03:03:07 +00:00
return self.initial["password"]
2017-10-14 18:18:12 +00:00
2016-07-20 10:06:33 +00:00
class ResetPasswordForm(forms.Form):
2017-10-14 18:18:12 +00:00
"""Formulaire de demande de reinitialisation de mot de passe,
mdp oublié"""
2018-08-15 17:15:26 +00:00
pseudo = forms.CharField(label=_("Username"), max_length=255)
2016-07-20 10:06:33 +00:00
email = forms.EmailField(max_length=255)
2017-10-14 18:18:12 +00:00
class MassArchiveForm(forms.Form):
2017-10-14 18:18:12 +00:00
"""Formulaire d'archivage des users inactif. Prend en argument
du formulaire la date de depart avant laquelle archiver les
users"""
date = forms.DateTimeField(help_text="%d/%m/%y")
full_archive = forms.BooleanField(
label=_(
2019-11-20 00:52:11 +00:00
"Fully archive users? WARNING: CRITICAL OPERATION IF TRUE"
),
initial=False,
required=False,
)
def clean(self):
2017-10-14 18:18:12 +00:00
cleaned_data = super(MassArchiveForm, self).clean()
date = cleaned_data.get("date")
if date:
if date > timezone.now():
raise forms.ValidationError(
_(
"Impossible to archive users"
" whose end access date is in"
" the future."
)
)
2017-10-14 18:18:12 +00:00
class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
2017-10-14 18:18:12 +00:00
"""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__)
super(AdherentForm, self).__init__(*args, prefix=prefix, **kwargs)
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")
if "room" in self.fields:
self.fields["room"].label = _("Room")
self.fields["room"].empty_label = _("No room")
self.fields["school"].empty_label = _("Select a school")
2018-07-30 15:00:41 +00:00
class Meta:
model = Adherent
fields = [
"name",
"surname",
"pseudo",
"email",
"school",
"comment",
"telephone",
"room",
]
force = forms.BooleanField(
label=_("Force the move?"), initial=False, required=False
)
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:
raise forms.ValidationError(
_("You can't use a {} address.").format(
OptionalUser.objects.first().local_email_domain
)
)
def clean_telephone(self):
2017-10-14 18:18:12 +00:00
"""Verifie que le tel est présent si 'option est validée
dans preferences"""
telephone = self.cleaned_data["telephone"]
if not telephone and OptionalUser.get_cached_value("is_tel_mandatory"):
raise forms.ValidationError(_("A valid telephone number is required."))
return telephone
def clean_force(self):
"""On supprime l'ancien user de la chambre si et seulement si la
case est cochée"""
room = self.cleaned_data.get("room")
if self.cleaned_data.get("force", False) and room:
2019-09-10 15:09:26 +00:00
remove_user_room(room)
return
2017-10-14 18:18:12 +00:00
2020-04-15 19:04:14 +00:00
def clean_room(self):
"""On supprime l'ancien user de la chambre si l'option est activée,
et que l'ancien user a une connexion désactivée"""
# Handle case where regular users can force move
room = self.cleaned_data.get("room")
room_policy = OptionalUser.get_cached_value("self_room_policy")
if room_policy == OptionalUser.DISABLED or not room:
2020-04-15 19:04:14 +00:00
return room
# Remove the previous user's room, if allowed and necessary
remove_user_room(room, force=bool(room_policy == OptionalUser.ALL_ROOM))
2020-04-15 19:04:14 +00:00
# Run standard clean process
return room
class AdherentCreationForm(AdherentForm):
"""Formulaire de création d'un user.
AdherentForm auquel on ajoute une checkbox afin d'éviter les
doublons d'utilisateurs et, optionnellement,
un champ mot de passe"""
2020-04-17 16:01:35 +00:00
# Champ pour choisir si un lien est envoyé par mail pour le mot de passe
init_password_by_mail_info = _(
"If this options is set, you will receive a link to set"
" your initial password by email. If you do not have"
" any means of accessing your emails, you can disable"
" this option to set your password immediatly."
" You will still receive an email to confirm your address."
" Failure to confirm your address will result in an"
" automatic suspension of your account until you do."
)
2020-04-17 16:01:35 +00:00
init_password_by_mail = forms.BooleanField(
help_text=init_password_by_mail_info,
required=False,
initial=True
)
init_password_by_mail.label = _("Send password reset link by email.")
# Champs pour initialiser le mot de passe
# Validators are handled manually since theses fields aren't always required
password1 = forms.CharField(
required=False,
label=_("Password"),
widget=forms.PasswordInput,
max_length=255,
2020-04-19 20:40:49 +00:00
help_text=password_validators_help_text_html()
2020-04-17 16:01:35 +00:00
)
password2 = forms.CharField(
required=False,
label=_("Password confirmation"),
widget=forms.PasswordInput,
max_length=255,
)
2018-09-19 21:24:15 +00:00
# Champ permettant d'éviter au maxium les doublons d'utilisateurs
former_user_check_info = _(
2019-11-20 00:52:11 +00:00
"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
)
2019-11-20 00:52:11 +00:00
former_user_check.label = _("I certify that I have not had an account before.")
2018-09-20 08:57:31 +00:00
# Checkbox for GTU
gtu_check = forms.BooleanField(required=True)
class Meta:
model = Adherent
fields = [
"name",
"surname",
"pseudo",
"email",
"school",
"comment",
"telephone",
"room",
"state",
]
2018-09-19 21:24:15 +00:00
def __init__(self, *args, **kwargs):
super(AdherentCreationForm, self).__init__(*args, **kwargs)
gtu_file = GeneralOption.get_cached_value("GTU")
self.fields["email"].required = True
self.fields["gtu_check"].label = mark_safe(
"%s <a href='%s' download='CGU'>%s</a>."
% (
2019-09-05 17:55:54 +00:00
_("I commit to accept the"),
2019-09-20 12:20:42 +00:00
gtu_file.url if gtu_file else "#",
_("General Terms of Use"),
2019-09-05 17:55:54 +00:00
)
)
2020-04-17 16:01:35 +00:00
# Remove password fields if option is disabled
if not OptionalUser.get_cached_value("allow_set_password_during_user_creation"):
self.fields.pop("init_password_by_mail")
self.fields.pop("password1")
self.fields.pop("password2")
2020-04-21 14:47:09 +00:00
def clean_email(self):
"""Forbid empty email"""
new_email = self.cleaned_data.get("email")
if not new_email or len(new_email) == 0:
raise forms.ValidationError(
_("Email field cannot be empty.")
)
return new_email
def clean_password2(self):
"""Verifie que password1 et 2 sont identiques (si nécessaire)"""
send_email = self.cleaned_data.get("init_password_by_mail")
if send_email:
return None
# 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:
raise forms.ValidationError(_("The passwords don't match."))
validate_password(password1)
return password2
def save(self, commit=True):
"""Set the user's password, if entered
Returns the user and a bool indicating whether
an email to init the password should be sent"""
# Save the provided password in hashed format
user = super(AdherentForm, self).save(commit=False)
is_set_password_allowed = OptionalUser.get_cached_value("allow_set_password_during_user_creation")
2020-04-17 18:41:02 +00:00
set_passwd = is_set_password_allowed and not self.cleaned_data.get("init_password_by_mail")
if set_passwd:
user.set_password(self.cleaned_data["password1"])
user.save()
return user
2019-09-05 17:55:54 +00:00
class AdherentEditForm(AdherentForm):
"""Formulaire d'édition d'un user.
AdherentForm incluant la modification des champs gpg et shell"""
def __init__(self, *args, **kwargs):
super(AdherentEditForm, self).__init__(*args, **kwargs)
self.fields["gpg_fingerprint"].widget.attrs["placeholder"] = _(
"Leave empty if you don't have any GPG key."
)
2020-04-21 14:47:09 +00:00
self.user = kwargs["instance"]
self.fields["email"].required = self.user.email and len(self.user.email)
if "shell" in self.fields:
self.fields["shell"].empty_label = _("Default shell")
class Meta:
model = Adherent
fields = [
"name",
"surname",
"pseudo",
"email",
"school",
"comment",
"telephone",
"room",
"shell",
"gpg_fingerprint",
"shortcuts_enabled",
]
2020-04-21 14:47:09 +00:00
def clean_email(self):
"""Forbid empty email"""
original_email = self.user.email
new_email = self.cleaned_data.get("email")
# Allow empty emails if the user had an empty email before
if original_email is None or len(original_email) == 0:
return new_email
if new_email is None or len(new_email) == 0:
raise forms.ValidationError(
_("Email field cannot be empty.")
)
return new_email
class ClubForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
"""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__)
super(ClubForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields["surname"].label = _("Name")
self.fields["school"].label = _("School")
self.fields["comment"].label = _("Comment")
self.fields["email"].label = _("Email address")
if "room" in self.fields:
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")
class Meta:
model = Club
fields = [
"surname",
"pseudo",
"school",
"comment",
"room",
"email",
"telephone",
"email",
"shell",
"mailing",
]
def clean_telephone(self):
"""Verifie que le tel est présent si 'option est validée
dans preferences"""
telephone = self.cleaned_data["telephone"]
if not telephone and OptionalUser.get_cached_value("is_tel_mandatory"):
raise forms.ValidationError(_("A valid telephone number is required."))
return telephone
class ClubAdminandMembersForm(FormRevMixin, ModelForm):
"""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__)
super(ClubAdminandMembersForm, self).__init__(*args, prefix=prefix, **kwargs)
class PasswordForm(FormRevMixin, ModelForm):
2017-10-14 18:18:12 +00:00
""" Formulaire de changement brut de mot de passe.
Ne pas utiliser sans traitement"""
class Meta:
model = User
fields = ["password", "pwd_ntlm"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(PasswordForm, self).__init__(*args, prefix=prefix, **kwargs)
2017-10-14 18:18:12 +00:00
class ServiceUserForm(FormRevMixin, ModelForm):
2018-12-22 12:10:31 +00:00
"""Service user creation
force initial password set"""
2017-10-14 18:18:12 +00:00
password = forms.CharField(
2018-08-15 17:15:26 +00:00
label=_("New password"),
2017-10-14 18:18:12 +00:00
max_length=255,
validators=[MinLengthValidator(8)],
widget=forms.PasswordInput,
required=True,
2017-10-14 18:18:12 +00:00
)
class Meta:
model = ServiceUser
fields = ("pseudo", "access_group", "comment")
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ServiceUserForm, self).__init__(*args, prefix=prefix, **kwargs)
def save(self, commit=True):
2018-12-22 12:10:31 +00:00
"""Password change"""
user = super(ServiceUserForm, self).save(commit=False)
if self.cleaned_data["password"]:
user.set_password(self.cleaned_data.get("password"))
user.save()
2017-10-14 18:18:12 +00:00
class EditServiceUserForm(ServiceUserForm):
2017-10-14 18:18:12 +00:00
"""Formulaire d'edition de base d'un service user. Ne permet
d'editer que son group d'acl et son commentaire"""
2018-12-22 12:10:31 +00:00
password = forms.CharField(
label=_("New password"),
max_length=255,
validators=[MinLengthValidator(8)],
widget=forms.PasswordInput,
required=False,
2018-12-22 12:10:31 +00:00
)
class Meta(ServiceUserForm.Meta):
fields = ["access_group", "comment"]
2017-10-14 18:18:12 +00:00
class StateForm(FormRevMixin, ModelForm):
2020-04-17 22:12:22 +00:00
"""Change state of an user, and if its main email is verified or not"""
class Meta:
model = User
2020-04-17 22:29:50 +00:00
fields = ["state", "email_state"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(StateForm, self).__init__(*args, prefix=prefix, **kwargs)
2020-04-17 22:29:50 +00:00
self.fields["state"].label = _("State")
self.fields["email_state"].label = _("Email state")
2018-05-03 12:22:52 +00:00
class GroupForm(FieldPermissionFormMixin, FormRevMixin, ModelForm):
2017-12-31 16:11:19 +00:00
""" Gestion des groupes d'un user"""
2017-12-31 16:11:19 +00:00
groups = forms.ModelMultipleChoiceField(
Group.objects.all(), widget=forms.CheckboxSelectMultiple, required=False
2017-12-31 16:11:19 +00:00
)
class Meta:
model = User
fields = ["is_superuser", "groups"]
2017-12-31 16:11:19 +00:00
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
2017-12-31 16:11:19 +00:00
super(GroupForm, self).__init__(*args, prefix=prefix, **kwargs)
if "is_superuser" in self.fields:
self.fields["is_superuser"].label = _("Superuser")
2017-12-31 16:11:19 +00:00
class SchoolForm(FormRevMixin, ModelForm):
2017-10-14 18:18:12 +00:00
"""Edition, creation d'un école"""
class Meta:
model = School
fields = ["name"]
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(SchoolForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields["name"].label = _("School")
2017-10-14 18:18:12 +00:00
class ShellForm(FormRevMixin, ModelForm):
"""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)
self.fields["shell"].label = _("Shell name")
class ListRightForm(FormRevMixin, ModelForm):
2017-10-14 18:18:12 +00:00
"""Edition, d'un groupe , équivalent à un droit
Ne permet pas d'editer le gid, car il sert de primary key"""
2017-12-31 16:11:19 +00:00
permissions = forms.ModelMultipleChoiceField(
Permission.objects.all().select_related("content_type"),
2017-12-31 16:11:19 +00:00
widget=forms.CheckboxSelectMultiple,
required=False,
2017-12-31 16:11:19 +00:00
)
class Meta:
model = ListRight
fields = ("name", "unix_name", "critical", "permissions", "details")
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ListRightForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields["unix_name"].label = _("Name of the group of rights")
2017-10-14 18:18:12 +00:00
class NewListRightForm(ListRightForm):
2017-10-14 18:18:12 +00:00
"""Ajout d'un groupe/list de droit """
class Meta(ListRightForm.Meta):
fields = ("name", "unix_name", "gid", "critical", "permissions", "details")
def __init__(self, *args, **kwargs):
super(NewListRightForm, self).__init__(*args, **kwargs)
self.fields["gid"].label = _(
2019-11-20 00:52:11 +00:00
"GID. Warning: this field must not be edited after creation."
)
2017-10-14 18:18:12 +00:00
class DelListRightForm(Form):
2017-10-14 18:18:12 +00:00
"""Suppression d'un ou plusieurs groupes"""
2017-10-14 18:18:12 +00:00
listrights = forms.ModelMultipleChoiceField(
2017-12-13 17:35:16 +00:00
queryset=ListRight.objects.none(),
2018-08-15 17:15:26 +00:00
label=_("Current groups of rights"),
widget=forms.CheckboxSelectMultiple,
2017-10-14 18:18:12 +00:00
)
2017-12-13 17:35:16 +00:00
def __init__(self, *args, **kwargs):
instances = kwargs.pop("instances", None)
2017-12-13 17:35:16 +00:00
super(DelListRightForm, self).__init__(*args, **kwargs)
if instances:
self.fields["listrights"].queryset = instances
2017-12-13 17:35:16 +00:00
else:
self.fields["listrights"].queryset = ListRight.objects.all()
2017-12-13 17:35:16 +00:00
class DelSchoolForm(Form):
2017-10-14 18:18:12 +00:00
"""Suppression d'une ou plusieurs écoles"""
2017-10-14 18:18:12 +00:00
schools = forms.ModelMultipleChoiceField(
2017-12-13 17:35:16 +00:00
queryset=School.objects.none(),
2018-08-15 17:15:26 +00:00
label=_("Current schools"),
widget=forms.CheckboxSelectMultiple,
2017-10-14 18:18:12 +00:00
)
2017-12-12 03:33:50 +00:00
def __init__(self, *args, **kwargs):
instances = kwargs.pop("instances", None)
2017-12-12 03:33:50 +00:00
super(DelSchoolForm, self).__init__(*args, **kwargs)
2017-12-13 17:35:16 +00:00
if instances:
self.fields["schools"].queryset = instances
2017-12-13 17:35:16 +00:00
else:
self.fields["schools"].queryset = School.objects.all()
2017-12-12 03:33:50 +00:00
class BanForm(FormRevMixin, ModelForm):
2017-10-14 18:18:12 +00:00
"""Creation, edition d'un objet bannissement"""
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(BanForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields["date_end"].label = _("End date")
self.fields["date_end"].localize = False
class Meta:
model = Ban
exclude = ["user"]
widgets = {"date_end": DateTimePicker}
class WhitelistForm(FormRevMixin, ModelForm):
2017-10-14 18:18:12 +00:00
"""Creation, edition d'un objet whitelist"""
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(WhitelistForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields["date_end"].label = _("End date")
self.fields["date_end"].localize = False
class Meta:
model = Whitelist
exclude = ["user"]
widgets = {"date_end": DateTimePicker}
2018-08-01 11:06:25 +00:00
class EMailAddressForm(FormRevMixin, ModelForm):
"""Create and edit a local email address"""
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
2018-08-01 11:06:25 +00:00
super(EMailAddressForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields["local_part"].label = _("Local part of the email address")
2019-11-20 00:52:11 +00:00
self.fields["local_part"].help_text = _("Can't contain @.")
def clean_local_part(self):
return self.cleaned_data.get("local_part").lower()
class Meta:
2018-08-01 11:06:25 +00:00
model = EMailAddress
exclude = ["user"]
2018-07-30 15:00:41 +00:00
class EmailSettingsForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
"""Edit email-related settings"""
def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__)
2018-07-30 15:00:41 +00:00
super(EmailSettingsForm, self).__init__(*args, prefix=prefix, **kwargs)
2020-04-21 14:47:09 +00:00
self.user = kwargs["instance"]
self.fields["email"].label = _("Main email address")
self.fields["email"].required = self.user.email and len(self.user.email)
if "local_email_redirect" in self.fields:
self.fields["local_email_redirect"].label = _("Redirect local emails")
if "local_email_enabled" in self.fields:
self.fields["local_email_enabled"].label = _("Use local emails")
def clean_email(self):
2020-04-21 14:47:09 +00:00
original_email = self.user.email
new_email = self.cleaned_data.get("email")
# Allow empty emails if the user had an empty email before
if original_email is None or len(original_email) == 0:
return new_email
if new_email is None or len(new_email) == 0:
raise forms.ValidationError(
_("Email field cannot be empty.")
)
if not OptionalUser.objects.first().local_email_domain in new_email:
return new_email.lower()
else:
2018-08-15 17:15:26 +00:00
raise forms.ValidationError(
_("You can't use a {} address.").format(
OptionalUser.objects.first().local_email_domain
)
)
class Meta:
2018-06-29 14:36:04 +00:00
model = User
fields = ["email", "local_email_enabled", "local_email_redirect"]
2018-08-15 17:15:26 +00:00
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:
if (
port.get_port_profile.radius_type != "NO"
and port.get_port_profile.radius_mode == "STRICT"
and hasattr(port, "room")
):
# 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"):
self.fields["register_room"].label = _("This room is my room")
else:
self.fields.pop("register_room")
if hasattr(self, "mac_address"):
self.fields["register_machine"].label = _(
"This new connected device is mine"
)
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)