mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-23 11:53:12 +00:00
Merge branch 'full_archive' into 'dev'
Full archive See merge request federez/re2o!414
This commit is contained in:
commit
3e03fc0c49
12 changed files with 201 additions and 63 deletions
|
@ -455,7 +455,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.
|
||||||
"""
|
"""
|
||||||
queryset = users.User.objects.exclude(Q(state=users.User.STATE_DISABLED) | Q(state=users.User.STATE_NOT_YET_ACTIVE))
|
queryset = users.User.objects.exclude(Q(state=users.User.STATE_DISABLED) | Q(state=users.User.STATE_NOT_YET_ACTIVE) | Q(state=users.User.STATE_FULL_ARCHIVE))
|
||||||
serializer_class = serializers.BasicUserSerializer
|
serializer_class = serializers.BasicUserSerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -104,8 +104,8 @@ from re2o.utils import (
|
||||||
all_adherent,
|
all_adherent,
|
||||||
all_active_assigned_interfaces_count,
|
all_active_assigned_interfaces_count,
|
||||||
all_active_interfaces_count,
|
all_active_interfaces_count,
|
||||||
)
|
)
|
||||||
from re2o.base import (
|
from re2o.base import (
|
||||||
re2o_paginator,
|
re2o_paginator,
|
||||||
SortTable
|
SortTable
|
||||||
)
|
)
|
||||||
|
@ -217,8 +217,8 @@ def stats_general(request):
|
||||||
).count()
|
).count()
|
||||||
ip_dict[ip_range] = [ip_range, ip_range.vlan, all_ip.count(),
|
ip_dict[ip_range] = [ip_range, ip_range.vlan, all_ip.count(),
|
||||||
used_ip, active_ip, all_ip.count()-used_ip]
|
used_ip, active_ip, all_ip.count()-used_ip]
|
||||||
_all_adherent = all_adherent()
|
_all_adherent = all_adherent(including_asso=False)
|
||||||
_all_has_access = all_has_access()
|
_all_has_access = all_has_access(including_asso=False)
|
||||||
_all_baned = all_baned()
|
_all_baned = all_baned()
|
||||||
_all_whitelisted = all_whitelisted()
|
_all_whitelisted = all_whitelisted()
|
||||||
_all_active_interfaces_count = all_active_interfaces_count()
|
_all_active_interfaces_count = all_active_interfaces_count()
|
||||||
|
@ -257,6 +257,14 @@ def stats_general(request):
|
||||||
.count()),
|
.count()),
|
||||||
Club.objects.filter(state=Club.STATE_ARCHIVE).count()
|
Club.objects.filter(state=Club.STATE_ARCHIVE).count()
|
||||||
],
|
],
|
||||||
|
'full_archive_users': [
|
||||||
|
_("Full Archived users"),
|
||||||
|
User.objects.filter(state=User.STATE_FULL_ARCHIVE).count(),
|
||||||
|
(Adherent.objects
|
||||||
|
.filter(state=Adherent.STATE_FULL_ARCHIVE)
|
||||||
|
.count()),
|
||||||
|
Club.objects.filter(state=Club.STATE_FULL_ARCHIVE).count()
|
||||||
|
],
|
||||||
'not_active_users': [
|
'not_active_users': [
|
||||||
_("Not yet active users"),
|
_("Not yet active users"),
|
||||||
User.objects.filter(state=User.STATE_NOT_YET_ACTIVE).count(),
|
User.objects.filter(state=User.STATE_NOT_YET_ACTIVE).count(),
|
||||||
|
|
|
@ -41,6 +41,8 @@ from django.db.models.signals import post_save, post_delete
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.forms import ValidationError
|
from django.forms import ValidationError
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.db import transaction
|
||||||
|
from reversion import revisions as reversion
|
||||||
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 macaddress.fields import MACAddressField, default_dialect
|
from macaddress.fields import MACAddressField, default_dialect
|
||||||
|
@ -222,6 +224,16 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
|
||||||
"""Return a name : user provided name or first interface name"""
|
"""Return a name : user provided name or first interface name"""
|
||||||
return self.name or self.short_name
|
return self.name or self.short_name
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mass_delete(cls, machine_queryset):
|
||||||
|
"""Mass delete for machine queryset"""
|
||||||
|
Domain.objects.filter(cname__interface_parent__machine__in=machine_queryset)._raw_delete(machine_queryset.db)
|
||||||
|
Domain.objects.filter(interface_parent__machine__in=machine_queryset)._raw_delete(machine_queryset.db)
|
||||||
|
Ipv6List.objects.filter(interface__machine__in=machine_queryset)._raw_delete(machine_queryset.db)
|
||||||
|
Interface.objects.filter(machine__in=machine_queryset).filter(port_lists__isnull=False).delete()
|
||||||
|
Interface.objects.filter(machine__in=machine_queryset)._raw_delete(machine_queryset.db)
|
||||||
|
machine_queryset._raw_delete(machine_queryset.db)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def all_complete_names(self):
|
def all_complete_names(self):
|
||||||
"""Renvoie tous les tls complets de la machine"""
|
"""Renvoie tous les tls complets de la machine"""
|
||||||
|
@ -1134,6 +1146,21 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
""" Sans commentaire, désassigne une ipv4"""
|
""" Sans commentaire, désassigne une ipv4"""
|
||||||
self.ipv4 = None
|
self.ipv4 = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mass_unassign_ipv4(cls, interface_list):
|
||||||
|
"""Unassign ipv4 to multiple interfaces"""
|
||||||
|
with transaction.atomic(), reversion.create_revision():
|
||||||
|
interface_list.update(ipv4=None)
|
||||||
|
reversion.set_comment(_("IPv4 unassigning"))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mass_assign_ipv4(cls, interface_list):
|
||||||
|
for interface in interface_list:
|
||||||
|
with transaction.atomic(), reversion.create_revision():
|
||||||
|
interface.assign_ipv4()
|
||||||
|
interface.save()
|
||||||
|
reversion.set_comment(_("IPv4 assigning"))
|
||||||
|
|
||||||
def update_type(self):
|
def update_type(self):
|
||||||
""" Lorsque le machinetype est changé de type d'ip, on réassigne"""
|
""" Lorsque le machinetype est changé de type d'ip, on réassigne"""
|
||||||
self.clean()
|
self.clean()
|
||||||
|
|
|
@ -256,7 +256,7 @@ class OptionalTopologie(AclMixin, PreferencesModel):
|
||||||
"""Return the ip of the interface that the switch have to contact to get it's config"""
|
"""Return the ip of the interface that the switch have to contact to get it's config"""
|
||||||
if self.switchs_ip_type:
|
if self.switchs_ip_type:
|
||||||
from machines.models import Role, Interface
|
from machines.models import Role, Interface
|
||||||
return Interface.objects.filter(machine__interface__in=Role.interface_for_roletype("switch-conf-server")).filter(type__ip_type=self.switchs_ip_type).first()
|
return Interface.objects.filter(machine__interface__in=Role.interface_for_roletype("switch-conf-server")).filter(machine_type__ip_type=self.switchs_ip_type).first()
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -282,11 +282,11 @@ class OptionalTopologie(AclMixin, PreferencesModel):
|
||||||
def return_ips_dict(interfaces):
|
def return_ips_dict(interfaces):
|
||||||
return {'ipv4' : [str(interface.ipv4) for interface in interfaces], 'ipv6' : Ipv6List.objects.filter(interface__in=interfaces).values_list('ipv6', flat=True)}
|
return {'ipv4' : [str(interface.ipv4) for interface in interfaces], 'ipv6' : Ipv6List.objects.filter(interface__in=interfaces).values_list('ipv6', flat=True)}
|
||||||
|
|
||||||
ntp_servers = Role.all_interfaces_for_roletype("ntp-server").filter(type__ip_type=self.switchs_ip_type)
|
ntp_servers = Role.all_interfaces_for_roletype("ntp-server").filter(machine_type__ip_type=self.switchs_ip_type)
|
||||||
log_servers = Role.all_interfaces_for_roletype("log-server").filter(type__ip_type=self.switchs_ip_type)
|
log_servers = Role.all_interfaces_for_roletype("log-server").filter(machine_type__ip_type=self.switchs_ip_type)
|
||||||
radius_servers = Role.all_interfaces_for_roletype("radius-server").filter(type__ip_type=self.switchs_ip_type)
|
radius_servers = Role.all_interfaces_for_roletype("radius-server").filter(machine_type__ip_type=self.switchs_ip_type)
|
||||||
dhcp_servers = Role.all_interfaces_for_roletype("dhcp-server")
|
dhcp_servers = Role.all_interfaces_for_roletype("dhcp-server")
|
||||||
dns_recursive_servers = Role.all_interfaces_for_roletype("dns-recursive-server").filter(type__ip_type=self.switchs_ip_type)
|
dns_recursive_servers = Role.all_interfaces_for_roletype("dns-recursive-server").filter(machine_type__ip_type=self.switchs_ip_type)
|
||||||
subnet = None
|
subnet = None
|
||||||
subnet6 = None
|
subnet6 = None
|
||||||
if self.switchs_ip_type:
|
if self.switchs_ip_type:
|
||||||
|
|
|
@ -44,15 +44,15 @@ from machines.models import Interface, Machine
|
||||||
from users.models import Adherent, User, Ban, Whitelist
|
from users.models import Adherent, User, Ban, Whitelist
|
||||||
from preferences.models import AssoOption
|
from preferences.models import AssoOption
|
||||||
|
|
||||||
def all_adherent(search_time=None):
|
def all_adherent(search_time=None, including_asso=True):
|
||||||
""" Fonction renvoyant tous les users adherents. Optimisee pour n'est
|
""" Fonction renvoyant tous les users adherents. Optimisee pour n'est
|
||||||
qu'une seule requete sql
|
qu'une seule requete sql
|
||||||
Inspecte les factures de l'user et ses cotisation, regarde si elles
|
Inspecte les factures de l'user et ses cotisation, regarde si elles
|
||||||
sont posterieur à now (end_time)"""
|
sont posterieur à now (end_time)"""
|
||||||
if search_time is None:
|
if search_time is None:
|
||||||
search_time = timezone.now()
|
search_time = timezone.now()
|
||||||
return User.objects.filter(
|
filter_user = (
|
||||||
facture__in=Facture.objects.filter(
|
Q(facture__in=Facture.objects.filter(
|
||||||
vente__in=Vente.objects.filter(
|
vente__in=Vente.objects.filter(
|
||||||
Q(type_cotisation='All') | Q(type_cotisation='Adhesion'),
|
Q(type_cotisation='All') | Q(type_cotisation='Adhesion'),
|
||||||
cotisation__in=Cotisation.objects.filter(
|
cotisation__in=Cotisation.objects.filter(
|
||||||
|
@ -62,7 +62,12 @@ def all_adherent(search_time=None):
|
||||||
).filter(Q(date_start__lt=search_time) & Q(date_end__gt=search_time))
|
).filter(Q(date_start__lt=search_time) & Q(date_end__gt=search_time))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).distinct()
|
))
|
||||||
|
if including_asso:
|
||||||
|
asso_user = AssoOption.get_cached_value('utilisateur_asso')
|
||||||
|
if asso_user:
|
||||||
|
filter_user |= Q(id=asso_user.id)
|
||||||
|
return User.objects.filter(filter_user).distinct()
|
||||||
|
|
||||||
|
|
||||||
def all_baned(search_time=None):
|
def all_baned(search_time=None):
|
||||||
|
@ -87,7 +92,7 @@ def all_whitelisted(search_time=None):
|
||||||
).distinct()
|
).distinct()
|
||||||
|
|
||||||
|
|
||||||
def all_has_access(search_time=None):
|
def all_has_access(search_time=None, including_asso=True):
|
||||||
""" Return all connected users : active users and whitelisted +
|
""" Return all connected users : active users and whitelisted +
|
||||||
asso_user defined in AssoOption pannel
|
asso_user defined in AssoOption pannel
|
||||||
----
|
----
|
||||||
|
@ -111,9 +116,10 @@ def all_has_access(search_time=None):
|
||||||
)
|
)
|
||||||
)))
|
)))
|
||||||
)
|
)
|
||||||
asso_user = AssoOption.get_cached_value('utilisateur_asso')
|
if including_asso:
|
||||||
if asso_user:
|
asso_user = AssoOption.get_cached_value('utilisateur_asso')
|
||||||
filter_user |= Q(id=asso_user.id)
|
if asso_user:
|
||||||
|
filter_user |= Q(id=asso_user.id)
|
||||||
return User.objects.filter(filter_user).distinct()
|
return User.objects.filter(filter_user).distinct()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ CHOICES_USER = (
|
||||||
('1', _("Disabled")),
|
('1', _("Disabled")),
|
||||||
('2', _("Archived")),
|
('2', _("Archived")),
|
||||||
('3', _("Not yet active")),
|
('3', _("Not yet active")),
|
||||||
|
('4', _("Full archived")),
|
||||||
)
|
)
|
||||||
|
|
||||||
CHOICES_AFF = (
|
CHOICES_AFF = (
|
||||||
|
|
|
@ -361,12 +361,12 @@ class Switch(AclMixin, Machine):
|
||||||
@cached_property
|
@cached_property
|
||||||
def interfaces_subnet(self):
|
def interfaces_subnet(self):
|
||||||
"""Return dict ip:subnet for all ip of the switch"""
|
"""Return dict ip:subnet for all ip of the switch"""
|
||||||
return dict((str(interface.ipv4), interface.type.ip_type.ip_set_full_info) for interface in self.interface_set.all())
|
return dict((str(interface.ipv4), interface.machine_type.ip_type.ip_set_full_info) for interface in self.interface_set.all())
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def interfaces6_subnet(self):
|
def interfaces6_subnet(self):
|
||||||
"""Return dict ip6:subnet for all ipv6 of the switch"""
|
"""Return dict ip6:subnet for all ipv6 of the switch"""
|
||||||
return dict((str(interface.ipv6().first()), interface.type.ip_type.ip6_set_full_info) for interface in self.interface_set.all())
|
return dict((str(interface.ipv6().first()), interface.machine_type.ip_type.ip6_set_full_info) for interface in self.interface_set.all())
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def list_modules(self):
|
def list_modules(self):
|
||||||
|
|
|
@ -297,6 +297,11 @@ class MassArchiveForm(forms.Form):
|
||||||
du formulaire la date de depart avant laquelle archiver les
|
du formulaire la date de depart avant laquelle archiver les
|
||||||
users"""
|
users"""
|
||||||
date = forms.DateTimeField(help_text='%d/%m/%y')
|
date = forms.DateTimeField(help_text='%d/%m/%y')
|
||||||
|
full_archive = forms.BooleanField(
|
||||||
|
label=_("Make a full archive operation ? (WARNING : CRITICAL OPERATION IF TRUE)"),
|
||||||
|
initial=False,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(MassArchiveForm, self).clean()
|
cleaned_data = super(MassArchiveForm, self).clean()
|
||||||
|
|
20
users/migrations/0081_auto_20190317_0302.py
Normal file
20
users/migrations/0081_auto_20190317_0302.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2019-03-17 02:02
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('users', '0080_auto_20190108_1726'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='user',
|
||||||
|
name='state',
|
||||||
|
field=models.IntegerField(choices=[(0, 'Active'), (1, 'Disabled'), (2, 'Archived'), (3, 'Not yet active'), (4, 'Full Archived')], default=3),
|
||||||
|
),
|
||||||
|
]
|
122
users/models.py
122
users/models.py
|
@ -188,11 +188,13 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
|
||||||
STATE_DISABLED = 1
|
STATE_DISABLED = 1
|
||||||
STATE_ARCHIVE = 2
|
STATE_ARCHIVE = 2
|
||||||
STATE_NOT_YET_ACTIVE = 3
|
STATE_NOT_YET_ACTIVE = 3
|
||||||
|
STATE_FULL_ARCHIVE = 4
|
||||||
STATES = (
|
STATES = (
|
||||||
(0, _("Active")),
|
(0, _("Active")),
|
||||||
(1, _("Disabled")),
|
(1, _("Disabled")),
|
||||||
(2, _("Archived")),
|
(2, _("Archived")),
|
||||||
(3, _("Not yet active")),
|
(3, _("Not yet active")),
|
||||||
|
(4, _("Full Archived")),
|
||||||
)
|
)
|
||||||
|
|
||||||
surname = models.CharField(max_length=255)
|
surname = models.CharField(max_length=255)
|
||||||
|
@ -335,11 +337,17 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
|
||||||
return self.state == self.STATE_ACTIVE or self.state == self.STATE_NOT_YET_ACTIVE
|
return self.state == self.STATE_ACTIVE or self.state == self.STATE_NOT_YET_ACTIVE
|
||||||
|
|
||||||
def set_active(self):
|
def set_active(self):
|
||||||
"""Enable this user if he subscribed successfully one time before"""
|
"""Enable this user if he subscribed successfully one time before
|
||||||
|
Reenable it if it was archived
|
||||||
|
Do nothing if disabed"""
|
||||||
if self.state == self.STATE_NOT_YET_ACTIVE:
|
if self.state == self.STATE_NOT_YET_ACTIVE:
|
||||||
if self.facture_set.filter(valid=True).filter(Q(vente__type_cotisation='All') | Q(vente__type_cotisation='Adhesion')).exists() or OptionalUser.get_cached_value('all_users_active'):
|
if self.facture_set.filter(valid=True).filter(Q(vente__type_cotisation='All') | Q(vente__type_cotisation='Adhesion')).exists() or OptionalUser.get_cached_value('all_users_active'):
|
||||||
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:
|
||||||
|
self.state = self.STATE_ACTIVE
|
||||||
|
self.unarchive()
|
||||||
|
self.save()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_staff(self):
|
def is_staff(self):
|
||||||
|
@ -519,53 +527,112 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
|
||||||
)['total'] or 0
|
)['total'] or 0
|
||||||
return somme_credit - somme_debit
|
return somme_credit - somme_debit
|
||||||
|
|
||||||
def user_interfaces(self, active=True):
|
@classmethod
|
||||||
|
def users_interfaces(cls, users, active=True, all_interfaces=False):
|
||||||
""" Renvoie toutes les interfaces dont les machines appartiennent à
|
""" Renvoie toutes les interfaces dont les machines appartiennent à
|
||||||
self. Par defaut ne prend que les interfaces actives"""
|
self. Par defaut ne prend que les interfaces actives"""
|
||||||
return Interface.objects.filter(
|
if all_interfaces:
|
||||||
machine__in=Machine.objects.filter(user=self, active=active)
|
return Interface.objects.filter(
|
||||||
).select_related('domain__extension')
|
machine__in=Machine.objects.filter(user__in=users)
|
||||||
|
).select_related('domain__extension')
|
||||||
|
else:
|
||||||
|
return Interface.objects.filter(
|
||||||
|
machine__in=Machine.objects.filter(user__in=users, active=active)
|
||||||
|
).select_related('domain__extension')
|
||||||
|
|
||||||
|
def user_interfaces(self, active=True, all_interfaces=False):
|
||||||
|
""" Renvoie toutes les interfaces dont les machines appartiennent à
|
||||||
|
self. Par defaut ne prend que les interfaces actives"""
|
||||||
|
return self.users_interfaces([self], active=active, all_interfaces=all_interfaces)
|
||||||
|
|
||||||
def assign_ips(self):
|
def assign_ips(self):
|
||||||
""" Assign une ipv4 aux machines d'un user """
|
""" Assign une ipv4 aux machines d'un user """
|
||||||
interfaces = self.user_interfaces()
|
interfaces = self.user_interfaces()
|
||||||
for interface in interfaces:
|
with transaction.atomic(), reversion.create_revision():
|
||||||
if not interface.ipv4:
|
Interface.mass_assign_ipv4(interfaces)
|
||||||
with transaction.atomic(), reversion.create_revision():
|
reversion.set_comment(_("IPv4 assigning"))
|
||||||
interface.assign_ipv4()
|
|
||||||
reversion.set_comment(_("IPv4 assigning"))
|
|
||||||
interface.save()
|
|
||||||
|
|
||||||
def unassign_ips(self):
|
def unassign_ips(self):
|
||||||
""" Désassigne les ipv4 aux machines de l'user"""
|
""" Désassigne les ipv4 aux machines de l'user"""
|
||||||
interfaces = self.user_interfaces()
|
interfaces = self.user_interfaces()
|
||||||
for interface in interfaces:
|
with transaction.atomic(), reversion.create_revision():
|
||||||
with transaction.atomic(), reversion.create_revision():
|
Interface.mass_unassign_ipv4(interfaces)
|
||||||
interface.unassign_ipv4()
|
reversion.set_comment(_("IPv4 unassigning"))
|
||||||
reversion.set_comment(_("IPv4 unassigning"))
|
|
||||||
interface.save()
|
@classmethod
|
||||||
|
def mass_unassign_ips(cls, users_list):
|
||||||
|
interfaces = cls.users_interfaces(users_list)
|
||||||
|
with transaction.atomic(), reversion.create_revision():
|
||||||
|
Interface.mass_unassign_ipv4(interfaces)
|
||||||
|
reversion.set_comment(_("IPv4 assigning"))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mass_disable_email(cls, queryset_users):
|
||||||
|
"""Disable email account and redirection"""
|
||||||
|
queryset_users.update(local_email_enabled=False)
|
||||||
|
queryset_users.update(local_email_redirect=False)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mass_delete_data(cls, queryset_users):
|
||||||
|
"""This users will be completely archived, so only keep mandatory data"""
|
||||||
|
cls.mass_disable_email(queryset_users)
|
||||||
|
Machine.mass_delete(Machine.objects.filter(user__in=queryset_users))
|
||||||
|
cls.ldap_delete_users(queryset_users)
|
||||||
|
|
||||||
def disable_email(self):
|
def disable_email(self):
|
||||||
"""Disable email account and redirection"""
|
"""Disable email account and redirection"""
|
||||||
self.email = ""
|
self.local_email_enabled=False
|
||||||
self.local_email_enabled = False
|
self.local_email_redirect=False
|
||||||
self.local_email_redirect = False
|
|
||||||
|
def delete_data(self):
|
||||||
|
"""This user will be completely archived, so only keep mandatory data"""
|
||||||
|
self.disable_email()
|
||||||
|
self.machine_set.all().delete()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mass_archive(cls, users_list):
|
||||||
|
"""Mass Archive several users, take a queryset
|
||||||
|
Copy Queryset to avoid eval problem with queryset update"""
|
||||||
|
#Force eval of queryset
|
||||||
|
bool(users_list)
|
||||||
|
users_list = users_list.all()
|
||||||
|
cls.mass_unassign_ips(users_list)
|
||||||
|
users_list.update(state=User.STATE_ARCHIVE)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mass_full_archive(cls, users_list):
|
||||||
|
"""Mass Archive several users, take a queryset
|
||||||
|
Copy Queryset to avoid eval problem with queryset update"""
|
||||||
|
#Force eval of queryset
|
||||||
|
bool(users_list)
|
||||||
|
users_list = users_list.all()
|
||||||
|
cls.mass_unassign_ips(users_list)
|
||||||
|
cls.mass_delete_data(users_list)
|
||||||
|
users_list.update(state=User.STATE_FULL_ARCHIVE)
|
||||||
|
|
||||||
def archive(self):
|
def archive(self):
|
||||||
""" Filling the user; no more active"""
|
""" Filling the user; no more active"""
|
||||||
self.unassign_ips()
|
self.unassign_ips()
|
||||||
self.disable_email()
|
|
||||||
|
def full_archive(self):
|
||||||
|
"""Full Archive = Archive + Service access complete deletion"""
|
||||||
|
self.archive()
|
||||||
|
self.delete_data()
|
||||||
|
self.ldap_del()
|
||||||
|
|
||||||
def unarchive(self):
|
def unarchive(self):
|
||||||
"""Unfilling the user"""
|
"""Unfilling the user"""
|
||||||
self.assign_ips()
|
self.assign_ips()
|
||||||
|
self.ldap_sync()
|
||||||
|
|
||||||
def state_sync(self):
|
def state_sync(self):
|
||||||
"""Archive, or unarchive, if the user was not active/or archived before"""
|
"""Archive, or unarchive, if the user was not active/or archived before"""
|
||||||
if self.__original_state != self.STATE_ACTIVE and self.state == self.STATE_ACTIVE:
|
if self.__original_state != self.STATE_ACTIVE and self.state == self.STATE_ACTIVE:
|
||||||
self.unarchive()
|
self.unarchive()
|
||||||
elif self.__original_state != self.STATE_ARCHIVE and self.state == self.STATE_ARCHIVE:
|
elif self.__original_state != self.STATE_ARCHIVE and self.state == self.STATE_ARCHIVE:
|
||||||
self.archive()
|
self.archive()
|
||||||
|
elif self.__original_state != self.STATE_FULL_ARCHIVE and self.state == self.STATE_FULL_ARCHIVE:
|
||||||
|
self.full_archive()
|
||||||
|
|
||||||
def ldap_sync(self, base=True, access_refresh=True, mac_refresh=True,
|
def ldap_sync(self, base=True, access_refresh=True, mac_refresh=True,
|
||||||
group_refresh=False):
|
group_refresh=False):
|
||||||
|
@ -578,15 +645,11 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
|
||||||
mac_refresh : synchronise les machines de l'user
|
mac_refresh : synchronise les machines de l'user
|
||||||
group_refresh : synchronise les group de l'user
|
group_refresh : synchronise les group de l'user
|
||||||
Si l'instance n'existe pas, on crée le ldapuser correspondant"""
|
Si l'instance n'existe pas, on crée le ldapuser correspondant"""
|
||||||
if sys.version_info[0] >= 3 and self.state != self.STATE_ARCHIVE and\
|
if sys.version_info[0] >= 3 and (self.state == self.STATE_ACTIVE or self.state == self.STATE_ARCHIVE or self.state == self.STATE_DISABLED):
|
||||||
self.state != self.STATE_DISABLED:
|
|
||||||
self.refresh_from_db()
|
self.refresh_from_db()
|
||||||
try:
|
try:
|
||||||
user_ldap = LdapUser.objects.get(uidNumber=self.uid_number)
|
user_ldap = LdapUser.objects.get(uidNumber=self.uid_number)
|
||||||
except LdapUser.DoesNotExist:
|
except LdapUser.DoesNotExist:
|
||||||
# Freshly created users are NOT synced in ldap base
|
|
||||||
if self.state == self.STATE_NOT_YET_ACTIVE:
|
|
||||||
return
|
|
||||||
user_ldap = LdapUser(uidNumber=self.uid_number)
|
user_ldap = LdapUser(uidNumber=self.uid_number)
|
||||||
base = True
|
base = True
|
||||||
access_refresh = True
|
access_refresh = True
|
||||||
|
@ -639,6 +702,11 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
|
||||||
except LdapUser.DoesNotExist:
|
except LdapUser.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def ldap_delete_users(cls, queryset_users):
|
||||||
|
"""Delete multiple users in ldap"""
|
||||||
|
LdapUser.objects.filter(name__in=list(queryset_users.values_list('pseudo', flat=True)))
|
||||||
|
|
||||||
def notif_inscription(self):
|
def notif_inscription(self):
|
||||||
""" Prend en argument un objet user, envoie un mail de bienvenue """
|
""" Prend en argument un objet user, envoie un mail de bienvenue """
|
||||||
template = loader.get_template('users/email_welcome')
|
template = loader.get_template('users/email_welcome')
|
||||||
|
@ -1025,7 +1093,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
|
||||||
.filter(local_part=self.pseudo.lower()).exclude(user_id=self.id)
|
.filter(local_part=self.pseudo.lower()).exclude(user_id=self.id)
|
||||||
):
|
):
|
||||||
raise ValidationError(_("This username is already used."))
|
raise ValidationError(_("This username is already used."))
|
||||||
if not self.local_email_enabled and not self.email and not (self.state == self.STATE_ARCHIVE):
|
if not self.local_email_enabled and not self.email and not (self.state == self.STATE_FULL_ARCHIVE):
|
||||||
raise ValidationError(_("There is neither a local email address nor an external"
|
raise ValidationError(_("There is neither a local email address nor an external"
|
||||||
" email address for this user.")
|
" email address for this user.")
|
||||||
)
|
)
|
||||||
|
|
|
@ -253,6 +253,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<dd><i class="text-danger">{% trans "Archived" %}</i></dd>
|
<dd><i class="text-danger">{% trans "Archived" %}</i></dd>
|
||||||
{% elif users.state == 3 %}
|
{% elif users.state == 3 %}
|
||||||
<dd><i class="text-danger">{% trans "Not yet member" %}</i></dd>
|
<dd><i class="text-danger">{% trans "Not yet member" %}</i></dd>
|
||||||
|
{% elif users.state == 4 %}
|
||||||
|
<dd><i class="text-danger">{% trans "Full Archived" %}</i></dd>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -776,26 +776,27 @@ def del_listright(request, instances):
|
||||||
@can_change(User, 'state')
|
@can_change(User, 'state')
|
||||||
def mass_archive(request):
|
def mass_archive(request):
|
||||||
""" Permet l'archivage massif"""
|
""" Permet l'archivage massif"""
|
||||||
to_archive_date = MassArchiveForm(request.POST or None)
|
pagination_number = GeneralOption.get_cached_value('pagination_number')
|
||||||
|
to_archive_form = MassArchiveForm(request.POST or None)
|
||||||
to_archive_list = []
|
to_archive_list = []
|
||||||
if to_archive_date.is_valid():
|
if to_archive_form.is_valid():
|
||||||
date = to_archive_date.cleaned_data['date']
|
date = to_archive_form.cleaned_data['date']
|
||||||
to_archive_list = [user for user in
|
full_archive = to_archive_form.cleaned_data['full_archive']
|
||||||
User.objects.exclude(state=User.STATE_ARCHIVE)
|
to_archive_list = User.objects.exclude(id__in=all_has_access()).exclude(id__in=all_has_access(search_time=date)).exclude(state=User.STATE_NOT_YET_ACTIVE).exclude(state=User.STATE_FULL_ARCHIVE)
|
||||||
if not user.end_access()
|
if not full_archive:
|
||||||
or user.end_access() < date]
|
to_archive_list = to_archive_list.exclude(state=User.STATE_ARCHIVE)
|
||||||
if "valider" in request.POST:
|
if "valider" in request.POST:
|
||||||
for user in to_archive_list:
|
if full_archive:
|
||||||
with transaction.atomic(), reversion.create_revision():
|
User.mass_full_archive(to_archive_list)
|
||||||
user.archive()
|
else:
|
||||||
user.save()
|
User.mass_archive(to_archive_list)
|
||||||
reversion.set_comment(_("Archiving"))
|
messages.success(request, _("%s users were archived.") %
|
||||||
messages.success(request, _("%s users were archived.") % len(
|
to_archive_list.count()
|
||||||
to_archive_list
|
)
|
||||||
))
|
|
||||||
return redirect(reverse('users:index'))
|
return redirect(reverse('users:index'))
|
||||||
|
to_archive_list = re2o_paginator(request, to_archive_list, pagination_number)
|
||||||
return form(
|
return form(
|
||||||
{'userform': to_archive_date, 'to_archive_list': to_archive_list},
|
{'userform': to_archive_form, 'to_archive_list': to_archive_list},
|
||||||
'users/mass_archive.html',
|
'users/mass_archive.html',
|
||||||
request
|
request
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue