Better linter score on users

This commit is contained in:
chapeau 2025-07-08 09:05:03 +02:00
parent 2197aa941b
commit cd722041a4
11 changed files with 221 additions and 297 deletions

View file

@ -45,7 +45,6 @@ from .models import (
Request, Request,
School, School,
ServiceUser, ServiceUser,
User,
Whitelist, Whitelist,
) )
@ -58,8 +57,6 @@ class SchoolAdmin(VersionAdmin):
""" """
pass
class ListRightAdmin(VersionAdmin): class ListRightAdmin(VersionAdmin):
"""ListRight and groups Admin view and management. """ListRight and groups Admin view and management.
@ -82,8 +79,6 @@ class ListShellAdmin(VersionAdmin):
""" """
pass
class RequestAdmin(admin.ModelAdmin): class RequestAdmin(admin.ModelAdmin):
"""User Request Admin view and management, for """User Request Admin view and management, for
@ -106,8 +101,6 @@ class BanAdmin(VersionAdmin):
""" """
pass
class EMailAddressAdmin(VersionAdmin): class EMailAddressAdmin(VersionAdmin):
"""EmailAddress Admin view and management, for """EmailAddress Admin view and management, for
@ -118,8 +111,6 @@ class EMailAddressAdmin(VersionAdmin):
""" """
pass
class WhitelistAdmin(VersionAdmin): class WhitelistAdmin(VersionAdmin):
"""Whitelist Admin view and management, for """Whitelist Admin view and management, for
@ -130,8 +121,6 @@ class WhitelistAdmin(VersionAdmin):
""" """
pass
class AdherentAdmin(VersionAdmin, BaseUserAdmin): class AdherentAdmin(VersionAdmin, BaseUserAdmin):
"""Adherent Admin view and management, for """Adherent Admin view and management, for

View file

@ -22,7 +22,7 @@
from rest_framework import serializers from rest_framework import serializers
import users.models as users import users.models as users
from api.serializers import NamespacedHIField, NamespacedHMSerializer, NamespacedHRField from api.serializers import NamespacedHMSerializer
class UserSerializer(NamespacedHMSerializer): class UserSerializer(NamespacedHMSerializer):

View file

@ -42,6 +42,7 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet):
class HomeCreationViewSet(viewsets.ReadOnlyModelViewSet): class HomeCreationViewSet(viewsets.ReadOnlyModelViewSet):
"""Exposes infos of `users.models.Users` objects to create homes.""" """Exposes infos of `users.models.Users` objects to create homes."""
# pylint: disable=unsupported-binary-operation
queryset = users.User.objects.exclude( queryset = users.User.objects.exclude(
Q(state=users.User.STATE_DISABLED) Q(state=users.User.STATE_DISABLED)
| Q(state=users.User.STATE_NOT_YET_ACTIVE) | Q(state=users.User.STATE_NOT_YET_ACTIVE)
@ -137,7 +138,6 @@ class EMailAddressViewSet(viewsets.ReadOnlyModelViewSet):
def get_queryset(self): def get_queryset(self):
if preferences.OptionalUser.get_cached_value("local_email_accounts_enabled"): if preferences.OptionalUser.get_cached_value("local_email_accounts_enabled"):
return users.EMailAddress.objects.filter(user__local_email_enabled=True) return users.EMailAddress.objects.filter(user__local_email_enabled=True)
else:
return users.EMailAddress.objects.none() return users.EMailAddress.objects.none()
@ -149,7 +149,6 @@ class LocalEmailUsersView(generics.ListAPIView):
def get_queryset(self): def get_queryset(self):
if preferences.OptionalUser.get_cached_value("local_email_accounts_enabled"): if preferences.OptionalUser.get_cached_value("local_email_accounts_enabled"):
return users.User.objects.filter(local_email_enabled=True) return users.User.objects.filter(local_email_enabled=True)
else:
return users.User.objects.none() return users.User.objects.none()

View file

@ -45,7 +45,6 @@ from os import path, walk
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.contrib.auth.models import Group, Permission from django.contrib.auth.models import Group, Permission
from django.contrib.auth.password_validation import ( from django.contrib.auth.password_validation import (
password_validators_help_text_html, password_validators_help_text_html,
@ -54,13 +53,11 @@ from django.contrib.auth.password_validation import (
from django.core.validators import MinLengthValidator from django.core.validators import MinLengthValidator
from django.forms import Form, ModelForm from django.forms import Form, ModelForm
from django.utils import timezone from django.utils import timezone
from django.utils.functional import lazy
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from machines.models import Interface, Machine, Nas from machines.models import Interface, Nas
from preferences.models import GeneralOption, OptionalUser from preferences.models import GeneralOption, OptionalUser
from re2o.base import get_input_formats_help_text
from re2o.field_permissions import FieldPermissionFormMixin from re2o.field_permissions import FieldPermissionFormMixin
from re2o.mixins import FormRevMixin from re2o.mixins import FormRevMixin
from re2o.utils import remove_user_room from re2o.utils import remove_user_room
@ -108,7 +105,7 @@ class UserAdminForm(FormRevMixin, forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(UserAdminForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["email"].required = True self.fields["email"].required = True
class Meta: class Meta:
@ -140,7 +137,7 @@ class UserAdminForm(FormRevMixin, forms.ModelForm):
commit : If False, don't make the real save in database commit : If False, don't make the real save in database
""" """
# Save the provided password in hashed format # Save the provided password in hashed format
user = super(UserAdminForm, self).save(commit=False) user = super().save(commit=False)
if self.cleaned_data["password1"]: if self.cleaned_data["password1"]:
user.set_password(self.cleaned_data["password1"]) user.set_password(self.cleaned_data["password1"])
user.save() user.save()
@ -164,7 +161,7 @@ class ServiceUserAdminForm(FormRevMixin, forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ServiceUserAdminForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
class Meta: class Meta:
model = ServiceUser model = ServiceUser
@ -193,7 +190,7 @@ class ServiceUserAdminForm(FormRevMixin, forms.ModelForm):
self : Apply on a django Form ServiceUserAdminForm instance self : Apply on a django Form ServiceUserAdminForm instance
commit : If False, don't make the real save in database commit : If False, don't make the real save in database
""" """
user = super(ServiceUserAdminForm, self).save(commit=False) user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"]) user.set_password(self.cleaned_data["password1"])
user.save() user.save()
return user return user
@ -255,7 +252,6 @@ class PassForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm):
""" """
if not self.instance.check_password(self.cleaned_data.get("selfpasswd")): if not self.instance.check_password(self.cleaned_data.get("selfpasswd")):
raise forms.ValidationError(_("The current password is incorrect.")) raise forms.ValidationError(_("The current password is incorrect."))
return
def save(self, commit=True): def save(self, commit=True):
"""Save function. Call standard "set_password" django function, """Save function. Call standard "set_password" django function,
@ -265,7 +261,7 @@ class PassForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm):
self : Apply on a django Form PassForm instance self : Apply on a django Form PassForm instance
commit : If False, don't make the real save in database commit : If False, don't make the real save in database
""" """
user = super(PassForm, self).save(commit=False) user = super().save(commit=False)
user.set_password(self.cleaned_data.get("passwd1")) user.set_password(self.cleaned_data.get("passwd1"))
user.save() user.save()
@ -297,7 +293,7 @@ class MassArchiveForm(forms.Form):
) )
def clean(self): def clean(self):
cleaned_data = super(MassArchiveForm, self).clean() cleaned_data = super().clean()
date = cleaned_data.get("date") date = cleaned_data.get("date")
if date: if date:
if date > timezone.now(): if date > timezone.now():
@ -320,7 +316,7 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(AdherentForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["name"].label = _("First name") self.fields["name"].label = _("First name")
self.fields["surname"].label = _("Surname") self.fields["surname"].label = _("Surname")
self.fields["email"].label = _("Email address") self.fields["email"].label = _("Email address")
@ -348,7 +344,8 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
"room": AutocompleteModelWidget( "room": AutocompleteModelWidget(
url="/topologie/room-autocomplete", url="/topologie/room-autocomplete",
attrs={ attrs={
"data-minimum-input-length": 3 # Only trigger autocompletion after 3 characters have been typed # Only trigger autocompletion after 3 characters have been typed
"data-minimum-input-length": 3
}, },
), ),
"shell": AutocompleteModelWidget(url="/users/shell-autocomplete"), "shell": AutocompleteModelWidget(url="/users/shell-autocomplete"),
@ -382,7 +379,6 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
room = self.cleaned_data.get("room") room = self.cleaned_data.get("room")
if self.cleaned_data.get("force", False) and room: if self.cleaned_data.get("force", False) and room:
remove_user_room(room) remove_user_room(room)
return
def clean_room(self): def clean_room(self):
"""Clean room, based on room policy provided by preferences. """Clean room, based on room policy provided by preferences.
@ -478,16 +474,13 @@ class AdherentCreationForm(AdherentForm):
] ]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(AdherentCreationForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
gtu_file = GeneralOption.get_cached_value("GTU") gtu_file = GeneralOption.get_cached_value("GTU")
gtu_url = gtu_file.url if gtu_file else "#"
self.fields["email"].required = True self.fields["email"].required = True
self.fields["gtu_check"].label = mark_safe( self.fields["gtu_check"].label = mark_safe(
"%s <a href='%s' download='CGU'>%s</a>." f"""{_("I commit to accept the")} <a href='{gtu_url}' """
% ( f"""download='CGU'>{_("General Terms of Use")}</a>."""
_("I commit to accept the"),
gtu_file.url if gtu_file else "#",
_("General Terms of Use"),
)
) )
# Remove password fields if option is disabled # Remove password fields if option is disabled
@ -553,7 +546,7 @@ class AdherentEditForm(AdherentForm):
""" """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(AdherentEditForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["gpg_fingerprint"].widget.attrs["placeholder"] = _( self.fields["gpg_fingerprint"].widget.attrs["placeholder"] = _(
"Leave empty if you don't have any GPG key." "Leave empty if you don't have any GPG key."
) )
@ -590,7 +583,7 @@ class ClubForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ClubForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["surname"].label = _("Name") self.fields["surname"].label = _("Name")
self.fields["school"].label = _("School") self.fields["school"].label = _("School")
self.fields["comment"].label = _("Comment") self.fields["comment"].label = _("Comment")
@ -659,7 +652,7 @@ class ClubAdminandMembersForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ClubAdminandMembersForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
class PasswordForm(FormRevMixin, ModelForm): class PasswordForm(FormRevMixin, ModelForm):
@ -675,7 +668,7 @@ class PasswordForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(PasswordForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
class ServiceUserForm(FormRevMixin, ModelForm): class ServiceUserForm(FormRevMixin, ModelForm):
@ -700,7 +693,7 @@ class ServiceUserForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ServiceUserForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
def save(self, commit=True): def save(self, commit=True):
"""Save function. If password has been changed and provided, """Save function. If password has been changed and provided,
@ -711,7 +704,7 @@ class ServiceUserForm(FormRevMixin, ModelForm):
self : Apply on a django Form ServiceUserForm instance self : Apply on a django Form ServiceUserForm instance
commit : If False, don't make the real save in database commit : If False, don't make the real save in database
""" """
user = super(ServiceUserForm, self).save(commit=False) user = super().save(commit=False)
if self.cleaned_data["password"]: if self.cleaned_data["password"]:
user.set_password(self.cleaned_data.get("password")) user.set_password(self.cleaned_data.get("password"))
user.save() user.save()
@ -751,7 +744,7 @@ class StateForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(StateForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["state"].label = _("State") self.fields["state"].label = _("State")
self.fields["email_state"].label = _("Email state") self.fields["email_state"].label = _("Email state")
@ -773,7 +766,7 @@ class GroupForm(FieldPermissionFormMixin, FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(GroupForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
if "is_superuser" in self.fields: if "is_superuser" in self.fields:
self.fields["is_superuser"].label = _("Superuser") self.fields["is_superuser"].label = _("Superuser")
@ -791,7 +784,7 @@ class SchoolForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(SchoolForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["name"].label = _("School") self.fields["name"].label = _("School")
@ -808,7 +801,7 @@ class ShellForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ShellForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["shell"].label = _("Shell name") self.fields["shell"].label = _("Shell name")
@ -833,7 +826,7 @@ class ListRightForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(ListRightForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["unix_name"].label = _("Name of the group of rights") self.fields["unix_name"].label = _("Name of the group of rights")
@ -849,7 +842,7 @@ class NewListRightForm(ListRightForm):
fields = ("name", "unix_name", "gid", "critical", "permissions", "details") fields = ("name", "unix_name", "gid", "critical", "permissions", "details")
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(NewListRightForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["gid"].label = _( self.fields["gid"].label = _(
"GID. Warning: this field must not be edited after creation." "GID. Warning: this field must not be edited after creation."
) )
@ -871,7 +864,7 @@ class DelListRightForm(Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
instances = kwargs.pop("instances", None) instances = kwargs.pop("instances", None)
super(DelListRightForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if instances: if instances:
self.fields["listrights"].queryset = instances self.fields["listrights"].queryset = instances
else: else:
@ -894,7 +887,7 @@ class DelSchoolForm(Form):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
instances = kwargs.pop("instances", None) instances = kwargs.pop("instances", None)
super(DelSchoolForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if instances: if instances:
self.fields["schools"].queryset = instances self.fields["schools"].queryset = instances
else: else:
@ -910,7 +903,7 @@ class BanForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(BanForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["date_end"].label = _("End date") self.fields["date_end"].label = _("End date")
self.fields["date_end"].localize = False self.fields["date_end"].localize = False
@ -929,7 +922,7 @@ class WhitelistForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(WhitelistForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["date_end"].label = _("End date") self.fields["date_end"].label = _("End date")
self.fields["date_end"].localize = False self.fields["date_end"].localize = False
@ -949,7 +942,7 @@ class EMailAddressForm(FormRevMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(EMailAddressForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.fields["local_part"].label = _("Local part of the email address") self.fields["local_part"].label = _("Local part of the email address")
self.fields["local_part"].help_text = _("Can't contain @.") self.fields["local_part"].help_text = _("Can't contain @.")
@ -970,7 +963,7 @@ class EmailSettingsForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
prefix = kwargs.pop("prefix", self.Meta.model.__name__) prefix = kwargs.pop("prefix", self.Meta.model.__name__)
super(EmailSettingsForm, self).__init__(*args, prefix=prefix, **kwargs) super().__init__(*args, prefix=prefix, **kwargs)
self.user = kwargs["instance"] self.user = kwargs["instance"]
self.fields["email"].label = _("Main email address") self.fields["email"].label = _("Main email address")
self.fields["email"].required = bool(self.user.email) self.fields["email"].required = bool(self.user.email)
@ -1022,7 +1015,7 @@ class InitialRegisterForm(forms.Form):
self.nas_type = Nas.objects.filter( self.nas_type = Nas.objects.filter(
nas_type__interface__ipv4__ipv4=switch_ip nas_type__interface__ipv4__ipv4=switch_ip
).first() ).first()
super(InitialRegisterForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if hasattr(self, "new_room"): if hasattr(self, "new_room"):
self.fields["register_room"].label = _("This room is my room") self.fields["register_room"].label = _("This room is my room")
else: else:
@ -1074,5 +1067,5 @@ class ThemeForm(FormRevMixin, forms.Form):
_, _, themes = next(walk(path.join(settings.STATIC_ROOT, "css/themes"))) _, _, themes = next(walk(path.join(settings.STATIC_ROOT, "css/themes")))
if not themes: if not themes:
themes = ["default.css"] themes = ["default.css"]
super(ThemeForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["theme"].choices = [(theme, theme) for theme in themes] self.fields["theme"].choices = [(theme, theme) for theme in themes]

View file

@ -46,11 +46,9 @@ from __future__ import unicode_literals
import datetime import datetime
import re import re
import sys
import traceback import traceback
import uuid import uuid
from datetime import timedelta from datetime import timedelta
from io import BytesIO
from django import forms from django import forms
from django.contrib.auth.models import ( from django.contrib.auth.models import (
@ -59,7 +57,6 @@ from django.contrib.auth.models import (
Group, Group,
PermissionsMixin, PermissionsMixin,
) )
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.db import models, transaction from django.db import models, transaction
from django.db.models import Q from django.db.models import Q
@ -71,7 +68,6 @@ from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from PIL import Image
from reversion import revisions as reversion from reversion import revisions as reversion
from cotisations.models import Cotisation, Facture, Paiement, Vente from cotisations.models import Cotisation, Facture, Paiement, Vente
@ -80,7 +76,6 @@ from preferences.models import (
AssoOption, AssoOption,
GeneralOption, GeneralOption,
MailMessageOption, MailMessageOption,
OptionalMachine,
OptionalUser, OptionalUser,
) )
from re2o.base import smtp_check from re2o.base import smtp_check
@ -102,8 +97,8 @@ def linux_user_check(login):
Returns: Returns:
boolean: True if login comply with policy boolean: True if login comply with policy
""" """
UNIX_LOGIN_PATTERN = re.compile("^[a-z][a-z0-9-]*[$]?$") unix_login_pattern = re.compile("^[a-z][a-z0-9-]*[$]?$")
return UNIX_LOGIN_PATTERN.match(login) return unix_login_pattern.match(login)
def linux_user_validator(login): def linux_user_validator(login):
@ -332,7 +327,6 @@ class User(
""" """
if self.is_class_adherent: if self.is_class_adherent:
return self.adherent.name return self.adherent.name
else:
return "" return ""
@cached_property @cached_property
@ -348,9 +342,8 @@ class User(
""" """
if self.is_class_adherent: if self.is_class_adherent:
return self.adherent.room return self.adherent.room
elif self.is_class_club: if self.is_class_club:
return self.club.room return self.club.room
else:
raise NotImplementedError(_("Unknown type.")) raise NotImplementedError(_("Unknown type."))
@cached_property @cached_property
@ -370,8 +363,9 @@ class User(
@cached_property @cached_property
def get_mail(self): def get_mail(self):
"""Shortcuts, returns the email address to use to contact the instance user self. """Shortcuts, returns the email address to use to contact the instance user
Depends on if local_email account has been activated, otherwise returns self.email. self. Depends on if local_email account has been activated, otherwise returns
self.email.
Parameters: Parameters:
self (user instance): user to return infos self (user instance): user to return infos
@ -385,7 +379,6 @@ class User(
or self.local_email_redirect or self.local_email_redirect
): ):
return str(self.email) return str(self.email)
else:
return str(self.emailaddress_set.get(local_part=self.pseudo.lower())) return str(self.emailaddress_set.get(local_part=self.pseudo.lower()))
@cached_property @cached_property
@ -401,9 +394,8 @@ class User(
""" """
if hasattr(self, "adherent"): if hasattr(self, "adherent"):
return "Adherent" return "Adherent"
elif hasattr(self, "club"): if hasattr(self, "club"):
return "Club" return "Club"
else:
raise NotImplementedError(_("Unknown type.")) raise NotImplementedError(_("Unknown type."))
@cached_property @cached_property
@ -419,9 +411,8 @@ class User(
""" """
if hasattr(self, "adherent"): if hasattr(self, "adherent"):
return _("Member") return _("Member")
elif hasattr(self, "club"): if hasattr(self, "club"):
return _("Club") return _("Club")
else:
raise NotImplementedError(_("Unknown type.")) raise NotImplementedError(_("Unknown type."))
@cached_property @cached_property
@ -537,8 +528,7 @@ class User(
""" """
name = self.name name = self.name
if name: if name:
return "%s %s" % (name, self.surname) return f"{name} {self.surname}"
else:
return self.surname return self.surname
def get_short_name(self): def get_short_name(self):
@ -595,7 +585,6 @@ class User(
or self.email_state == self.EMAIL_STATE_UNVERIFIED or self.email_state == self.EMAIL_STATE_UNVERIFIED
): ):
return str(0) return str(0)
else:
return None return None
@cached_property @cached_property
@ -709,9 +698,8 @@ class User(
end = self.end_adhesion() end = self.end_adhesion()
if not end: if not end:
return False return False
elif end < timezone.now(): if end < timezone.now():
return False return False
else:
return True return True
# it looks wrong, we should check if there is a cotisation where # it looks wrong, we should check if there is a cotisation where
# were date_start_memb < timezone.now() < date_end_memb, # were date_start_memb < timezone.now() < date_end_memb,
@ -727,14 +715,14 @@ class User(
self (user instance): user to return infos self (user instance): user to return infos
Returns: Returns:
is_connected (boolean) : True is user has a valid membership and a valid connexion. is_connected (boolean) : True is user has a valid membership and a valid
connexion.
""" """
end = self.end_connexion() end = self.end_connexion()
if not end: if not end:
return False return False
elif end < timezone.now(): if end < timezone.now():
return False return False
else:
return self.is_adherent() return self.is_adherent()
# it looks wrong, we should check if there is a cotisation where # it looks wrong, we should check if there is a cotisation where
# were date_start_con < timezone.now() < date_end_con, # were date_start_con < timezone.now() < date_end_con,
@ -784,9 +772,8 @@ class User(
end = self.end_ban() end = self.end_ban()
if not end: if not end:
return False return False
elif end < timezone.now(): if end < timezone.now():
return False return False
else:
return True return True
def is_whitelisted(self): def is_whitelisted(self):
@ -802,9 +789,8 @@ class User(
end = self.end_whitelist() end = self.end_whitelist()
if not end: if not end:
return False return False
elif end < timezone.now(): if end < timezone.now():
return False return False
else:
return True return True
def has_access(self): def has_access(self):
@ -838,12 +824,9 @@ class User(
if not self.end_connexion(): if not self.end_connexion():
if not self.end_whitelist(): if not self.end_whitelist():
return None return None
else:
return self.end_whitelist() return self.end_whitelist()
else:
if not self.end_whitelist(): if not self.end_whitelist():
return self.end_connexion() return self.end_connexion()
else:
return max(self.end_connexion(), self.end_whitelist()) return max(self.end_connexion(), self.end_whitelist())
@classmethod @classmethod
@ -865,7 +848,6 @@ class User(
return Interface.objects.filter( return Interface.objects.filter(
machine__in=Machine.objects.filter(user__in=users) machine__in=Machine.objects.filter(user__in=users)
).select_related("domain__extension") ).select_related("domain__extension")
else:
return Interface.objects.filter( return Interface.objects.filter(
machine__in=Machine.objects.filter(user__in=users, active=active) machine__in=Machine.objects.filter(user__in=users, active=active)
).select_related("domain__extension") ).select_related("domain__extension")
@ -918,26 +900,25 @@ class User(
): ):
self.state = self.STATE_ACTIVE self.state = self.STATE_ACTIVE
self.save() self.save()
if self.state == self.STATE_ARCHIVE or self.state == self.STATE_FULL_ARCHIVE: if self.state in (self.STATE_ARCHIVE, self.STATE_FULL_ARCHIVE):
self.unarchive() self.unarchive()
self.state = self.STATE_ACTIVE self.state = self.STATE_ACTIVE
self.save() self.save()
def set_password(self, password): def set_password(self, raw_password):
"""Method, overload the basic set_password inherited from django BaseUser. """Method, overload the basic set_password inherited from django BaseUser.
Called when setting a new password, to set the classic django password Called when setting a new password, to set the classic django password
hashed, and also the NTLM hashed pwd_ntlm password. hashed, and also the NTLM hashed pwd_ntlm password.
Parameters: Parameters:
self (user instance): user to set password self (user instance): user to set password
password (string): new password (cleatext) to set. raw_password (string): new password (cleatext) to set.
""" """
from re2o.login import hash_nt from re2o.login import hash_nt
super().set_password(password) super().set_password(raw_password)
self.pwd_ntlm = hash_nt(password) self.pwd_ntlm = hash_nt(raw_password)
return
def confirm_mail(self): def confirm_mail(self):
"""Method, set the email_state to VERIFIED when the email has been verified. """Method, set the email_state to VERIFIED when the email has been verified.
@ -1156,8 +1137,8 @@ class User(
send_mail( send_mail(
request, request,
"Bienvenue au %(name)s / Welcome to %(name)s" f'Bienvenue au {AssoOption.get_cached_value("name")} / '
% {"name": AssoOption.get_cached_value("name")}, f'Welcome to {AssoOption.get_cached_value("name")}',
"", "",
GeneralOption.get_cached_value("email_from"), GeneralOption.get_cached_value("email_from"),
[self.email], [self.email],
@ -1194,8 +1175,8 @@ class User(
send_mail( send_mail(
request, request,
"Changement de mot de passe de %(name)s / Password change for " f'Changement de mot de passe de {AssoOption.get_cached_value("name")} / '
"%(name)s" % {"name": AssoOption.get_cached_value("name")}, f'Password change for {AssoOption.get_cached_value("name")}',
template.render(context), template.render(context),
GeneralOption.get_cached_value("email_from"), GeneralOption.get_cached_value("email_from"),
[req.user.email], [req.user.email],
@ -1290,8 +1271,8 @@ class User(
email: An email with a link to confirm the new email address email: An email with a link to confirm the new email address
""" """
# Delete all older requests for this user, that aren't for this email # Delete all older requests for this user, that aren't for this email
filter = Q(user=self) & Q(type=Request.EMAIL) & ~Q(email=self.email) mail_filter = Q(user=self) & Q(type=Request.EMAIL) & ~Q(email=self.email)
Request.objects.filter(filter).delete() Request.objects.filter(mail_filter).delete()
# Create the request and send the email # Create the request and send the email
req = Request() req = Request()
@ -1316,14 +1297,13 @@ class User(
send_mail( send_mail(
request, request,
"Confirmation du mail de %(name)s / Email confirmation for " f'Confirmation du mail de {AssoOption.get_cached_value("name")} / '
"%(name)s" % {"name": AssoOption.get_cached_value("name")}, f'Email confirmation for {AssoOption.get_cached_value("name")}',
template.render(context), template.render(context),
GeneralOption.get_cached_value("email_from"), GeneralOption.get_cached_value("email_from"),
[req.user.email], [req.user.email],
fail_silently=False, fail_silently=False,
) )
return
def autoregister_machine(self, mac_address, nas_type, request=None): def autoregister_machine(self, mac_address, nas_type, request=None):
"""Function, register a new interface on the user instance account. """Function, register a new interface on the user instance account.
@ -1364,7 +1344,7 @@ class User(
domain.clean() domain.clean()
domain.save() domain.save()
self.notif_auto_newmachine(interface_cible) self.notif_auto_newmachine(interface_cible)
except Exception as error: except Exception:
return False, traceback.format_exc() return False, traceback.format_exc()
return interface_cible, _("OK") return interface_cible, _("OK")
@ -1397,7 +1377,6 @@ class User(
[self.email], [self.email],
html_message=template.render(context), html_message=template.render(context),
) )
return
def notif_disable(self, request=None): def notif_disable(self, request=None):
"""Function/method, send an email to notify that the account is disabled """Function/method, send an email to notify that the account is disabled
@ -1426,7 +1405,6 @@ class User(
[self.email], [self.email],
fail_silently=False, fail_silently=False,
) )
return
def get_next_domain_name(self): def get_next_domain_name(self):
"""Function/method, provide a unique name for a new interface. """Function/method, provide a unique name for a new interface.
@ -1472,25 +1450,23 @@ class User(
or user_request.adherent in self.club.administrators.all() or user_request.adherent in self.club.administrators.all()
): ):
return True, warning_message, None return True, warning_message, None
else:
return ( return (
False, False,
_("You don't have the right to edit this club."), _("You don't have the right to edit this club."),
("users.change_user",), ("users.change_user",),
) )
else:
if self == user_request: if self == user_request:
return True, warning_message, None return True, warning_message, None
elif user_request.has_perm("users.change_all_users"): if user_request.has_perm("users.change_all_users"):
return True, warning_message, None return True, warning_message, None
elif user_request.has_perm("users.change_user"): if user_request.has_perm("users.change_user"):
if self.groups.filter(listright__critical=True): if self.groups.filter(listright__critical=True):
return ( return (
False, False,
_("User with critical rights, can't be edited."), _("User with critical rights, can't be edited."),
("users.change_all_users",), ("users.change_all_users",),
) )
elif self == AssoOption.get_cached_value("utilisateur_asso"): if self == AssoOption.get_cached_value("utilisateur_asso"):
return ( return (
False, False,
_( _(
@ -1499,11 +1475,9 @@ class User(
), ),
("users.change_all_users",), ("users.change_all_users",),
) )
else:
return True, warning_message, None return True, warning_message, None
elif user_request.has_perm("users.change_all_users"): if user_request.has_perm("users.change_all_users"):
return True, warning_message, None return True, warning_message, None
else:
return ( return (
False, False,
_("You don't have the right to edit another user."), _("You don't have the right to edit another user."),
@ -1526,22 +1500,17 @@ class User(
or user_request.adherent in self.club.administrators.all() or user_request.adherent in self.club.administrators.all()
): ):
return True, None, None return True, None, None
else:
return ( return (
False, False,
_("You don't have the right to edit this club."), _("You don't have the right to edit this club."),
("users.change_user_password",), ("users.change_user_password",),
) )
else: if self == user_request or user_request.has_perm("users.change_user_groups"):
if self == user_request or user_request.has_perm(
"users.change_user_groups"
):
# Peut éditer les groupes d'un user, # Peut éditer les groupes d'un user,
# c'est un privilège élevé, True # c'est un privilège élevé, True
return True, None, None return True, None, None
elif user_request.has_perm("users.change_user") and not self.groups.all(): if user_request.has_perm("users.change_user") and not self.groups.all():
return True, None, None return True, None, None
else:
return ( return (
False, False,
_("You don't have the right to edit another user."), _("You don't have the right to edit another user."),
@ -1574,7 +1543,6 @@ class User(
_("You don't have the right to change the room."), _("You don't have the right to change the room."),
("users.change_user",), ("users.change_user",),
) )
else:
return True, None, None return True, None, None
@staticmethod @staticmethod
@ -1611,7 +1579,6 @@ class User(
_("You don't have the right to change the shell."), _("You don't have the right to change the shell."),
("users.change_user_shell",), ("users.change_user_shell",),
) )
else:
return True, None, None return True, None, None
def can_change_pseudo(self, user_request, *_args, **_kwargs): def can_change_pseudo(self, user_request, *_args, **_kwargs):
@ -1634,7 +1601,6 @@ class User(
_("You don't have the right to change the pseudo."), _("You don't have the right to change the pseudo."),
("users.change_user_pseudo",), ("users.change_user_pseudo",),
) )
else:
return True, None, None return True, None, None
@staticmethod @staticmethod
@ -1737,16 +1703,13 @@ class User(
or user_request.adherent in self.club.members.all() or user_request.adherent in self.club.members.all()
): ):
return True, None, None return True, None, None
else:
return ( return (
False, False,
_("You don't have the right to view this club."), _("You don't have the right to view this club."),
("users.view_user",), ("users.view_user",),
) )
else:
if self == user_request or user_request.has_perm("users.view_user"): if self == user_request or user_request.has_perm("users.view_user"):
return True, None, None return True, None, None
else:
return ( return (
False, False,
_("You don't have the right to view another user."), _("You don't have the right to view another user."),
@ -1789,7 +1752,7 @@ class User(
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(User, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.field_permissions = { self.field_permissions = {
"shell": self.can_change_shell, "shell": self.can_change_shell,
"pseudo": self.can_change_pseudo, "pseudo": self.can_change_pseudo,
@ -1854,7 +1817,7 @@ class User(
self (user instance): user to clean. self (user instance): user to clean.
""" """
super(User, self).clean(*args, **kwargs) super().clean(*args, **kwargs)
self.clean_pseudo(*args, **kwargs) self.clean_pseudo(*args, **kwargs)
self.clean_email(*args, **kwargs) self.clean_email(*args, **kwargs)
@ -1868,7 +1831,7 @@ class User(
Returns: Returns:
str: name of theme str: name of theme
""" """
return self.theme.split(".")[0] return self.theme.split(".", maxsplit=1)[0]
class Adherent(User): class Adherent(User):
@ -1946,20 +1909,13 @@ class Adherent(User):
if not user_request.is_authenticated: if not user_request.is_authenticated:
if not OptionalUser.get_cached_value("self_adhesion"): if not OptionalUser.get_cached_value("self_adhesion"):
return False, _("Self registration is disabled."), None return False, _("Self registration is disabled."), None
else:
return True, None, None return True, None, None
else:
if OptionalUser.get_cached_value("all_can_create_adherent"): if OptionalUser.get_cached_value("all_can_create_adherent"):
return True, None, None return True, None, None
else:
can = user_request.has_perm("users.add_user") can = user_request.has_perm("users.add_user")
return ( return (
can, can,
( (_("You don't have the right to create a user.") if not can else None),
_("You don't have the right to create a user.")
if not can
else None
),
("users.add_user",), ("users.add_user",),
) )
@ -1977,7 +1933,6 @@ class Adherent(User):
can, _message, _group = Club.can_view_all(user_request) can, _message, _group = Club.can_view_all(user_request)
if user_request.has_perm("users.view_user") or can: if user_request.has_perm("users.view_user") or can:
return (True, None, None, cls.objects.all()) return (True, None, None, cls.objects.all())
else:
return ( return (
True, True,
_("You don't have the right to list all adherents."), _("You don't have the right to list all adherents."),
@ -1992,7 +1947,7 @@ class Adherent(User):
self (user instance): user to perform clean. self (user instance): user to perform clean.
""" """
super(Adherent, self).clean(*args, **kwargs) super().clean(*args, **kwargs)
if self.gpg_fingerprint: if self.gpg_fingerprint:
self.validate_gpgfp() self.validate_gpgfp()
self.format_gpgfp() self.format_gpgfp()
@ -2035,18 +1990,12 @@ class Club(User):
""" """
if not user_request.is_authenticated: if not user_request.is_authenticated:
return False, _("You must be authenticated."), None return False, _("You must be authenticated."), None
else:
if OptionalUser.get_cached_value("all_can_create_club"): if OptionalUser.get_cached_value("all_can_create_club"):
return True, None, None return True, None, None
else:
can = user_request.has_perm("users.add_user") can = user_request.has_perm("users.add_user")
return ( return (
can, can,
( (_("You don't have the right to create a club.") if not can else None),
_("You don't have the right to create a club.")
if not can
else None
),
("users.add_user",), ("users.add_user",),
) )
@ -2148,10 +2097,11 @@ def user_post_delete(**kwargs):
class ServiceUser(RevMixin, AclMixin, AbstractBaseUser): class ServiceUser(RevMixin, AclMixin, AbstractBaseUser):
"""A class representing a serviceuser (it is considered as a user """A class representing a serviceuser (it is considered as a user
with special informations). with special informations).
The serviceuser is a special user used with special access to authentication tree. It is The serviceuser is a special user used with special access to authentication tree.
its only usefullness, and service user can't connect to re2o. It is its only usefullness, and service user can't connect to re2o.
Each service connected to authentication for auth (ex dokuwiki, owncloud, etc) should Each service connected to authentication for auth (ex dokuwiki, owncloud, etc)
have a different service user with special acl (readonly, auth) and password. should have a different service user with special acl (readonly, auth) and
password.
Attributes: Attributes:
pseudo: login of the serviceuser pseudo: login of the serviceuser
@ -2332,7 +2282,7 @@ class ListShell(RevMixin, AclMixin, models.Model):
pretty_name (string): Return a pretty name string for this shell. pretty_name (string): Return a pretty name string for this shell.
""" """
return self.shell.split("/")[-1] return self.shell.split("/", maxsplit=1)[-1]
@classmethod @classmethod
def can_list(cls, user_request, *_args, **_kwargs): def can_list(cls, user_request, *_args, **_kwargs):
@ -2409,7 +2359,6 @@ class Ban(RevMixin, AclMixin, models.Model):
[self.user.email], [self.user.email],
fail_silently=False, fail_silently=False,
) )
return
def is_active(self): def is_active(self):
"""Method, return if the ban is active now or not. """Method, return if the ban is active now or not.
@ -2437,7 +2386,6 @@ class Ban(RevMixin, AclMixin, models.Model):
_("You don't have the right to view other bans than yours."), _("You don't have the right to view other bans than yours."),
("users.view_ban",), ("users.view_ban",),
) )
else:
return True, None, None return True, None, None
def __str__(self): def __str__(self):
@ -2531,7 +2479,6 @@ class Whitelist(RevMixin, AclMixin, models.Model):
_("You don't have the right to view other whitelists than yours."), _("You don't have the right to view other whitelists than yours."),
("users.view_whitelist",), ("users.view_whitelist",),
) )
else:
return True, None, None return True, None, None
def __str__(self): def __str__(self):
@ -2604,7 +2551,7 @@ class Request(models.Model):
) )
if not self.token: if not self.token:
self.token = str(uuid.uuid4()).replace("-", "") # remove hyphens self.token = str(uuid.uuid4()).replace("-", "") # remove hyphens
super(Request, self).save() super().save()
class EMailAddress(RevMixin, AclMixin, models.Model): class EMailAddress(RevMixin, AclMixin, models.Model):
@ -2673,7 +2620,7 @@ class EMailAddress(RevMixin, AclMixin, models.Model):
), ),
("users.add_emailaddress",), ("users.add_emailaddress",),
) )
elif user_request.email_address.count() >= OptionalUser.get_cached_value( if user_request.email_address.count() >= OptionalUser.get_cached_value(
"max_email_address" "max_email_address"
): ):
return ( return (
@ -2796,4 +2743,4 @@ class EMailAddress(RevMixin, AclMixin, models.Model):
result, reason = smtp_check(self.local_part) result, reason = smtp_check(self.local_part)
if result: if result:
raise ValidationError(reason) raise ValidationError(reason)
super(EMailAddress, self).clean(*args, **kwargs) super().clean(*args, **kwargs)

View file

@ -1,24 +1,28 @@
""" """
A set of signals used by users. Various classes in users emit these signals to signal the need to sync or A set of signals used by users. Various classes in users emit these signals to signal
remove an object from optionnal authentication backends, e.g. LDAP. the need to sync or remove an object from optionnal authentication backends, e.g. LDAP.
* `users.signals.synchronise`: * `users.signals.synchronise`:
Expresses the need for an instance of a users class to be synchronised. `sender` and `instance` are Expresses the need for an instance of a users class to be synchronised. `sender`
always set. It is up to the receiver to ensure the others are set correctly if they make sense. and `instance` are always set. It is up to the receiver to ensure the others are
set correctly if they make sense.
Arguments: Arguments:
* `sender` : The model class. * `sender` : The model class.
* `instance` : The actual instance being synchronised. * `instance` : The actual instance being synchronised.
* `base` : Default `True`. When `True`, synchronise basic attributes. * `base` : Default `True`. When `True`, synchronise basic attributes.
* `access_refresh` : Default `True`. When `True`, synchronise the access time. * `access_refresh` : Default `True`. When `True`, synchronise the access time.
* `mac_refresh` : Default `True`. When True, synchronise the list of mac addresses. * `mac_refresh` : Default `True`. When True, synchronise the list of mac
* `group_refresh`: Default `False`. When `True` synchronise the groups of the instance. addresses.
* `group_refresh`: Default `False`. When `True` synchronise the groups of
the instance.
* `users.signals.remove`: * `users.signals.remove`:
Expresses the need for an instance of a users class to be removed. Expresses the need for an instance of a users class to be removed.
Arguments: Arguments:
* `sender` : The model class. * `sender` : The model class.
* `instance` : The actual instance being removed. * `instance` : The actual instance being removed.
* `users.signals.remove_mass`: * `users.signals.remove_mass`:
Same as `users.signals.remove` except it removes a queryset. For now it is only used by `users.models.User`. Same as `users.signals.remove` except it removes a queryset. For now it is only used
by `users.models.User`.
Arguments: Arguments:
* `sender` : The model class. * `sender` : The model class.
* `queryset` : The actual instances being removed. * `queryset` : The actual instances being removed.

View file

@ -19,7 +19,7 @@ class UserModelTests(TestCase):
paiement = Paiement.objects.create(moyen="test payment") paiement = Paiement.objects.create(moyen="test payment")
invoice = Facture.objects.create(user=self.user, paiement=paiement, valid=True) invoice = Facture.objects.create(user=self.user, paiement=paiement, valid=True)
date = timezone.now() date = timezone.now()
purchase1 = Vente.objects.create( Vente.objects.create(
facture=invoice, facture=invoice,
number=1, number=1,
name="Test purchase", name="Test purchase",
@ -29,7 +29,7 @@ class UserModelTests(TestCase):
duration_connection=0, duration_connection=0,
prix=0, prix=0,
) )
purchase2 = Vente.objects.create( Vente.objects.create(
facture=invoice, facture=invoice,
number=1, number=1,
name="Test purchase", name="Test purchase",

View file

@ -23,9 +23,6 @@
The tests for the Users module. The tests for the Users module.
""" """
import os.path
from django.conf import settings
from django.test import TestCase from django.test import TestCase
from . import models from . import models

View file

@ -44,38 +44,33 @@ Also add extra views for :
* Ask for new email for email confirmation * Ask for new email for email confirmation
* Register room and interface on user account with switch web redirection. * Register room and interface on user account with switch web redirection.
All the view must be as simple as possible, with returning the correct form to user during All the view must be as simple as possible, with returning the correct form to user
get, and during post, performing change in database with simple ".save()" function. during get, and during post, performing change in database with simple ".save()"
function.
The aim is to put all "intelligent" functions in both forms and models functions. In fact, this The aim is to put all "intelligent" functions in both forms and models functions. In
will allow to user other frontend (like REST api) to perform editions, creations, etc on database, fact, this will allow to user other frontend (like REST api) to perform editions,
without code duplication. creations, etc on database, without code duplication.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
import os
from importlib import import_module from importlib import import_module
from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required
from django.db import transaction from django.db import transaction
from django.db.models import Count, Max, ProtectedError from django.db.models import Count, Max, ProtectedError
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from reversion import revisions as reversion from reversion import revisions as reversion
from cotisations.models import Facture, Paiement from cotisations.models import Paiement
from cotisations.utils import find_payment_method from cotisations.utils import find_payment_method
from machines.models import Machine
from preferences.models import AssoOption, GeneralOption, OptionalUser from preferences.models import AssoOption, GeneralOption, OptionalUser
from re2o.acl import ( from re2o.acl import (
can_change, can_change,
@ -150,8 +145,8 @@ def new_user(request):
) )
user.request = request user.request = request
GTU_sum_up = GeneralOption.get_cached_value("GTU_sum_up") gtu_sum_up = GeneralOption.get_cached_value("GTU_sum_up")
GTU = GeneralOption.get_cached_value("GTU") gtu = GeneralOption.get_cached_value("GTU")
is_set_password_allowed = OptionalUser.get_cached_value( is_set_password_allowed = OptionalUser.get_cached_value(
"allow_set_password_during_user_creation" "allow_set_password_during_user_creation"
) )
@ -180,8 +175,8 @@ def new_user(request):
# but they should be treated differently # but they should be treated differently
params = { params = {
"userform": user, "userform": user,
"GTU_sum_up": GTU_sum_up, "GTU_sum_up": gtu_sum_up,
"GTU": GTU, "GTU": gtu,
"showCGU": True, "showCGU": True,
"action_name": _("Commit"), "action_name": _("Commit"),
} }
@ -1487,9 +1482,8 @@ def process(request, token):
if req.type == Request.PASSWD: if req.type == Request.PASSWD:
return process_passwd(request, req) return process_passwd(request, req)
elif req.type == Request.EMAIL: if req.type == Request.EMAIL:
return process_email(request, req) return process_email(request, req)
else:
messages.error(request, _("Error: please contact an admin.")) messages.error(request, _("Error: please contact an admin."))
redirect(reverse("index")) redirect(reverse("index"))
@ -1545,7 +1539,7 @@ def process_email(request, req):
# Delete all remaining requests # Delete all remaining requests
Request.objects.filter(user=user, type=Request.EMAIL).delete() Request.objects.filter(user=user, type=Request.EMAIL).delete()
messages.success(request, _("The %s address was confirmed." % user.email)) messages.success(request, _("The %s address was confirmed.") % user.email)
return redirect(reverse("index")) return redirect(reverse("index"))
return form( return form(
@ -1557,7 +1551,7 @@ def process_email(request, req):
@login_required @login_required
@can_edit(User) @can_edit(User)
def resend_confirmation_email(request, logged_user, userid): def resend_confirmation_email(request, _logged_user, userid):
"""View to resend confirm email, for adding a new email. """View to resend confirm email, for adding a new email.
Check if User has the correct acl. Check if User has the correct acl.
@ -1590,8 +1584,8 @@ def initial_register(request):
This view is used with switchs function of redirect web after AAA authentication This view is used with switchs function of redirect web after AAA authentication
failed. Then, the users log-in, and the new mac-address and switch port, in order to failed. Then, the users log-in, and the new mac-address and switch port, in order to
get the room, are included in HTTP Headers by the switch redirection functionnality. get the room, are included in HTTP Headers by the switch redirection functionnality.
This allow to add the new interface with the correct mac-address, and confirm if needed, This allow to add the new interface with the correct mac-address, and confirm if
the new room of request.user. needed, the new room of request.user.
Parameters: Parameters:
request (django request): Standard django request. request (django request): Standard django request.

View file

@ -31,7 +31,7 @@ Here are defined the autocomplete class based view.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db.models import CharField, Q, Value from django.db.models import Q, Value
from django.db.models.functions import Concat from django.db.models.functions import Concat
from re2o.views import AutocompleteLoggedOutViewMixin, AutocompleteViewMixin from re2o.views import AutocompleteLoggedOutViewMixin, AutocompleteViewMixin
@ -46,7 +46,8 @@ class SchoolAutocomplete(AutocompleteLoggedOutViewMixin):
class UserAutocomplete(AutocompleteViewMixin): class UserAutocomplete(AutocompleteViewMixin):
obj_type = User obj_type = User
# Precision on search to add annotations so search behaves more like users expect it to # Precision on search to add annotations so search behaves more like users
# expect it to
def filter_results(self): def filter_results(self):
# Comments explain what we try to match # Comments explain what we try to match
self.query_set = self.query_set.annotate( self.query_set = self.query_set.annotate(
@ -59,6 +60,7 @@ class UserAutocomplete(AutocompleteViewMixin):
).all() ).all()
if self.q: if self.q:
# pylint: disable=unsupported-binary-operation
self.query_set = self.query_set.filter( self.query_set = self.query_set.filter(
Q(pseudo__icontains=self.q) Q(pseudo__icontains=self.q)
| Q(full_name__icontains=self.q) | Q(full_name__icontains=self.q)
@ -69,7 +71,8 @@ class UserAutocomplete(AutocompleteViewMixin):
class AdherentAutocomplete(AutocompleteViewMixin): class AdherentAutocomplete(AutocompleteViewMixin):
obj_type = Adherent obj_type = Adherent
# Precision on search to add annotations so search behaves more like users expect it to # Precision on search to add annotations so search behaves more like users
# expect it to
def filter_results(self): def filter_results(self):
# Comments explain what we try to match # Comments explain what we try to match
self.query_set = self.query_set.annotate( self.query_set = self.query_set.annotate(
@ -82,6 +85,7 @@ class AdherentAutocomplete(AutocompleteViewMixin):
).all() ).all()
if self.q: if self.q:
# pylint: disable=unsupported-binary-operation
self.query_set = self.query_set.filter( self.query_set = self.query_set.filter(
Q(pseudo__icontains=self.q) Q(pseudo__icontains=self.q)
| Q(full_name__icontains=self.q) | Q(full_name__icontains=self.q)

View file

@ -1,13 +1,10 @@
from django.conf import settings from django.conf import settings
from django.forms.utils import flatatt from django.forms.utils import flatatt
from django.forms.widgets import Input from django.forms.widgets import Input
from django.template import Template
from django.template.loader import get_template from django.template.loader import get_template
from django.utils.dates import ( from django.utils.dates import (
MONTHS, MONTHS,
MONTHS_3, MONTHS_3,
MONTHS_ALT,
MONTHS_AP,
WEEKDAYS, WEEKDAYS,
WEEKDAYS_ABBR, WEEKDAYS_ABBR,
) )