2017-09-10 14:53:02 +00:00
# -*- 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.
#
# Copyright © 2017 Gabriel Détraz
# Copyright © 2017 Goulven Kermarec
# Copyright © 2017 Augustin Lemesle
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2017-09-10 23:29:24 +00:00
from __future__ import unicode_literals
2016-06-30 01:39:07 +00:00
from django . db import models
2016-07-10 02:49:09 +00:00
from django . db . models import Q
2016-07-02 02:40:24 +00:00
from django import forms
2016-07-26 00:54:32 +00:00
from django . db . models . signals import post_save , post_delete
from django . dispatch import receiver
2017-05-26 22:43:51 +00:00
from django . utils . functional import cached_property
2017-08-28 19:51:12 +00:00
from django . template import Context , RequestContext , loader
from django . core . mail import send_mail
from django . core . urlresolvers import reverse
2016-07-10 02:02:48 +00:00
2017-07-21 04:49:39 +00:00
from reversion import revisions as reversion
from django . db import transaction
2016-07-26 00:54:32 +00:00
import ldapdb . models
import ldapdb . models . fields
2017-08-26 14:04:51 +00:00
from re2o . settings import RIGHTS_LINK , LDAP , GID_RANGES , UID_RANGES
2016-07-20 01:53:46 +00:00
import re , uuid
import datetime
2016-06-30 01:39:07 +00:00
2016-07-03 00:15:17 +00:00
from django . utils import timezone
2016-07-08 01:12:28 +00:00
from django . contrib . auth . models import AbstractBaseUser , BaseUserManager
2016-07-03 00:15:17 +00:00
2017-06-18 12:59:53 +00:00
from django . core . validators import MinLengthValidator
2016-07-03 12:36:51 +00:00
from topologie . models import Room
2017-06-26 17:23:01 +00:00
from cotisations . models import Cotisation , Facture , Paiement , Vente
2017-09-10 23:29:24 +00:00
from machines . models import Domain , Interface , MachineType , Machine , Nas , MachineType , regen
2017-09-10 20:50:20 +00:00
from preferences . models import GeneralOption , AssoOption , OptionalUser , OptionalMachine , MailMessageOption
2016-07-03 12:36:51 +00:00
2017-08-18 22:01:06 +00:00
now = timezone . now ( )
2016-07-03 13:26:44 +00:00
def remove_user_room ( room ) :
""" Déménage de force l ' ancien locataire de la chambre """
try :
user = User . objects . get ( room = room )
except User . DoesNotExist :
return
user . room = None
user . save ( )
2016-07-08 01:12:28 +00:00
def linux_user_check ( login ) :
2016-07-06 00:56:30 +00:00
""" Validation du pseudo pour respecter les contraintes unix """
2017-08-01 11:51:59 +00:00
UNIX_LOGIN_PATTERN = re . compile ( " ^[a-zA-Z0-9-]*[$]?$ " )
2016-07-08 01:12:28 +00:00
return UNIX_LOGIN_PATTERN . match ( login )
def linux_user_validator ( login ) :
if not linux_user_check ( login ) :
2016-07-06 00:56:30 +00:00
raise forms . ValidationError (
" , ce pseudo ( ' %(label)s ' ) contient des carractères interdits " ,
params = { ' label ' : login } ,
)
2016-10-12 10:24:01 +00:00
def get_fresh_user_uid ( ) :
uids = list ( range ( int ( min ( UID_RANGES [ ' users ' ] ) ) , int ( max ( UID_RANGES [ ' users ' ] ) ) ) )
2016-12-18 09:52:20 +00:00
try :
2017-08-26 13:10:18 +00:00
used_uids = list ( User . objects . values_list ( ' uid_number ' , flat = True ) )
2016-12-18 09:52:20 +00:00
except :
used_uids = [ ]
2016-10-12 10:24:01 +00:00
free_uids = [ id for id in uids if id not in used_uids ]
return min ( free_uids )
def get_fresh_gid ( ) :
gids = list ( range ( int ( min ( GID_RANGES [ ' posix ' ] ) ) , int ( max ( GID_RANGES [ ' posix ' ] ) ) ) )
2017-08-26 13:10:18 +00:00
used_gids = list ( ListRight . objects . values_list ( ' gid ' , flat = True ) )
2016-10-12 10:24:01 +00:00
free_gids = [ id for id in gids if id not in used_gids ]
return min ( free_gids )
2016-07-08 01:12:28 +00:00
def get_admin_right ( ) :
try :
admin_right = ListRight . objects . get ( listright = " admin " )
except ListRight . DoesNotExist :
admin_right = ListRight ( listright = " admin " )
2016-10-12 10:24:01 +00:00
admin_right . gid = get_fresh_gid ( )
2016-07-08 01:12:28 +00:00
admin_right . save ( )
return admin_right
2017-08-18 22:01:06 +00:00
def all_adherent ( search_time = now ) :
return User . objects . filter ( facture__in = Facture . objects . filter ( vente__in = Vente . objects . filter ( cotisation__in = Cotisation . objects . filter ( vente__in = Vente . objects . filter ( facture__in = Facture . objects . all ( ) . exclude ( valid = False ) ) ) . filter ( date_end__gt = search_time ) ) ) ) . distinct ( )
2017-05-26 22:43:51 +00:00
2017-08-18 22:01:06 +00:00
def all_baned ( search_time = now ) :
return User . objects . filter ( ban__in = Ban . objects . filter ( date_end__gt = search_time ) ) . distinct ( )
2017-05-26 22:43:51 +00:00
2017-08-18 22:01:06 +00:00
def all_whitelisted ( search_time = now ) :
return User . objects . filter ( whitelist__in = Whitelist . objects . filter ( date_end__gt = search_time ) ) . distinct ( )
2017-05-26 22:43:51 +00:00
2017-08-18 22:01:06 +00:00
def all_has_access ( search_time = now ) :
return User . objects . filter ( Q ( state = User . STATE_ACTIVE ) & ~ Q ( ban__in = Ban . objects . filter ( date_end__gt = timezone . now ( ) ) ) & ( Q ( whitelist__in = Whitelist . objects . filter ( date_end__gt = timezone . now ( ) ) ) | Q ( facture__in = Facture . objects . filter ( vente__in = Vente . objects . filter ( cotisation__in = Cotisation . objects . filter ( vente__in = Vente . objects . filter ( facture__in = Facture . objects . all ( ) . exclude ( valid = False ) ) ) . filter ( date_end__gt = search_time ) ) ) ) ) ) . distinct ( )
2016-07-08 01:12:28 +00:00
class UserManager ( BaseUserManager ) :
def _create_user ( self , pseudo , name , surname , email , password = None , su = False ) :
if not pseudo :
raise ValueError ( ' Users must have an username ' )
if not linux_user_check ( pseudo ) :
2017-08-01 12:12:27 +00:00
raise ValueError ( ' Username shall only contain [a-z0-9-] ' )
2016-07-08 01:12:28 +00:00
user = self . model (
pseudo = pseudo ,
name = name ,
surname = surname ,
email = self . normalize_email ( email ) ,
)
user . set_password ( password )
user . save ( using = self . _db )
if su :
user . make_admin ( )
return user
def create_user ( self , pseudo , name , surname , email , password = None ) :
"""
Creates and saves a User with the given pseudo , name , surname , email ,
and password .
"""
return self . _create_user ( pseudo , name , surname , email , password , False )
def create_superuser ( self , pseudo , name , surname , email , password ) :
"""
Creates and saves a superuser with the given pseudo , name , surname ,
email , and password .
"""
return self . _create_user ( pseudo , name , surname , email , password , True )
class User ( AbstractBaseUser ) :
2016-11-01 01:14:06 +00:00
PRETTY_NAME = " Utilisateurs "
2016-06-30 01:39:07 +00:00
STATE_ACTIVE = 0
2016-10-18 15:11:45 +00:00
STATE_DISABLED = 1
STATE_ARCHIVE = 2
2016-06-30 01:39:07 +00:00
STATES = (
2016-06-30 18:18:06 +00:00
( 0 , ' STATE_ACTIVE ' ) ,
2016-10-18 15:11:45 +00:00
( 1 , ' STATE_DISABLED ' ) ,
( 2 , ' STATE_ARCHIVE ' ) ,
2016-06-30 01:39:07 +00:00
)
2016-07-31 03:03:07 +00:00
def auto_uid ( ) :
2016-10-12 10:24:01 +00:00
return get_fresh_user_uid ( )
2016-07-31 03:03:07 +00:00
2016-06-30 01:39:07 +00:00
name = models . CharField ( max_length = 255 )
surname = models . CharField ( max_length = 255 )
2016-07-06 10:02:49 +00:00
pseudo = models . CharField ( max_length = 32 , unique = True , help_text = " Doit contenir uniquement des lettres, chiffres, ou tirets " , validators = [ linux_user_validator ] )
2016-06-30 01:39:07 +00:00
email = models . EmailField ( )
2016-10-11 15:11:46 +00:00
school = models . ForeignKey ( ' School ' , on_delete = models . PROTECT , null = True , blank = True )
2016-07-27 00:39:19 +00:00
shell = models . ForeignKey ( ' ListShell ' , on_delete = models . PROTECT , null = True , blank = True )
2016-07-04 15:54:52 +00:00
comment = models . CharField ( help_text = " Commentaire, promo " , max_length = 255 , blank = True )
2016-07-03 12:36:51 +00:00
room = models . OneToOneField ( ' topologie.Room ' , on_delete = models . PROTECT , blank = True , null = True )
2016-06-30 01:39:07 +00:00
pwd_ntlm = models . CharField ( max_length = 255 )
2016-06-30 23:03:28 +00:00
state = models . IntegerField ( choices = STATES , default = STATE_ACTIVE )
2016-07-02 23:29:26 +00:00
registered = models . DateTimeField ( auto_now_add = True )
2017-06-25 02:12:21 +00:00
telephone = models . CharField ( max_length = 15 , blank = True , null = True )
2016-07-31 03:03:07 +00:00
uid_number = models . IntegerField ( default = auto_uid , unique = True )
2016-10-07 19:30:05 +00:00
rezo_rez_uid = models . IntegerField ( unique = True , blank = True , null = True )
2016-06-30 01:39:07 +00:00
2016-07-08 01:12:28 +00:00
USERNAME_FIELD = ' pseudo '
REQUIRED_FIELDS = [ ' name ' , ' surname ' , ' email ' ]
objects = UserManager ( )
@property
def is_active ( self ) :
return self . state == self . STATE_ACTIVE
@property
def is_staff ( self ) :
return self . is_admin
@property
def is_admin ( self ) :
try :
Right . objects . get ( user = self , right__listright = ' admin ' )
except Right . DoesNotExist :
return False
return True
@is_admin.setter
def is_admin ( self , value ) :
if value and not self . is_admin :
self . make_admin ( )
elif not value and self . is_admin :
self . un_admin ( )
def get_full_name ( self ) :
return ' %s %s ' % ( self . name , self . surname )
def get_short_name ( self ) :
return self . name
2016-07-09 02:12:09 +00:00
def has_perms ( self , perms , obj = None ) :
for perm in perms :
2016-07-10 14:39:21 +00:00
if perm in RIGHTS_LINK :
query = Q ( )
for right in RIGHTS_LINK [ perm ] :
query = query | Q ( right__listright = right )
if Right . objects . filter ( Q ( user = self ) & query ) :
return True
2016-07-09 02:12:09 +00:00
try :
Right . objects . get ( user = self , right__listright = perm )
except Right . DoesNotExist :
return False
2016-07-08 01:12:28 +00:00
return True
2016-07-09 12:17:05 +00:00
def has_perm ( self , perm , obj = None ) :
return True
2017-05-27 13:12:21 +00:00
def has_right ( self , right ) :
2017-07-02 21:52:43 +00:00
try :
list_right = ListRight . objects . get ( listright = right )
except :
list_right = ListRight ( listright = right , gid = get_fresh_gid ( ) )
list_right . save ( )
return Right . objects . filter ( user = self ) . filter ( right = list_right ) . exists ( )
2017-05-27 13:12:21 +00:00
@cached_property
def is_bureau ( self ) :
2017-07-02 21:52:43 +00:00
return self . has_right ( ' bureau ' )
2017-05-27 13:12:21 +00:00
@cached_property
def is_bofh ( self ) :
2017-07-02 21:52:43 +00:00
return self . has_right ( ' bofh ' )
2017-05-27 13:12:21 +00:00
@cached_property
def is_cableur ( self ) :
return self . has_right ( ' cableur ' ) or self . has_right ( ' bureau ' ) or self . has_right ( ' infra ' ) or self . has_right ( ' bofh ' )
@cached_property
def is_trez ( self ) :
2017-07-02 21:52:43 +00:00
return self . has_right ( ' trésorier ' )
2017-05-27 13:12:21 +00:00
@cached_property
def is_infra ( self ) :
2017-07-02 21:52:43 +00:00
return self . has_right ( ' infra ' )
2017-05-27 13:12:21 +00:00
2016-07-10 02:02:48 +00:00
def end_adhesion ( self ) :
2016-12-14 02:08:57 +00:00
date_max = Cotisation . objects . filter ( vente__in = Vente . objects . filter ( facture__in = Facture . objects . filter ( user = self ) . exclude ( valid = False ) ) ) . aggregate ( models . Max ( ' date_end ' ) ) [ ' date_end__max ' ]
2016-07-10 02:02:48 +00:00
return date_max
def is_adherent ( self ) :
2017-07-18 01:49:36 +00:00
end = self . end_adhesion ( )
2016-07-10 02:02:48 +00:00
if not end :
return False
elif end < timezone . now ( ) :
return False
else :
return True
2017-05-26 22:43:51 +00:00
@cached_property
2016-07-10 02:02:48 +00:00
def end_ban ( self ) :
""" Renvoie la date de fin de ban d ' un user, False sinon """
2016-12-14 02:08:57 +00:00
date_max = Ban . objects . filter ( user = self ) . aggregate ( models . Max ( ' date_end ' ) ) [ ' date_end__max ' ]
2016-07-10 02:02:48 +00:00
return date_max
2017-05-26 22:43:51 +00:00
@cached_property
2016-07-10 02:02:48 +00:00
def end_whitelist ( self ) :
2017-05-26 01:07:10 +00:00
""" Renvoie la date de fin de whitelist d ' un user, False sinon """
2016-12-14 02:08:57 +00:00
date_max = Whitelist . objects . filter ( user = self ) . aggregate ( models . Max ( ' date_end ' ) ) [ ' date_end__max ' ]
2016-07-10 02:02:48 +00:00
return date_max
2017-05-26 22:43:51 +00:00
@cached_property
2016-07-10 02:02:48 +00:00
def is_ban ( self ) :
""" Renvoie si un user est banni ou non """
2017-05-26 22:43:51 +00:00
end = self . end_ban
2016-07-10 02:02:48 +00:00
if not end :
return False
elif end < timezone . now ( ) :
return False
else :
return True
2017-05-26 22:43:51 +00:00
@cached_property
2016-07-10 02:02:48 +00:00
def is_whitelisted ( self ) :
""" Renvoie si un user est whitelisté ou non """
2017-05-26 22:43:51 +00:00
end = self . end_whitelist
2016-07-10 02:02:48 +00:00
if not end :
return False
elif end < timezone . now ( ) :
return False
else :
return True
def has_access ( self ) :
""" Renvoie si un utilisateur a accès à internet """
return self . state == User . STATE_ACTIVE \
2017-07-18 01:49:36 +00:00
and not self . is_ban and ( self . is_adherent ( ) or self . is_whitelisted )
2016-07-10 02:02:48 +00:00
2017-05-26 01:07:10 +00:00
def end_access ( self ) :
""" Renvoie la date de fin normale d ' accès (adhésion ou whiteliste) """
2017-07-18 01:49:36 +00:00
if not self . end_adhesion ( ) :
2017-05-26 22:43:51 +00:00
if not self . end_whitelist :
2017-05-26 01:07:10 +00:00
return None
else :
2017-05-26 22:43:51 +00:00
return self . end_whitelist
2017-05-26 01:07:10 +00:00
else :
2017-05-26 22:43:51 +00:00
if not self . end_whitelist :
2017-07-18 01:49:36 +00:00
return self . end_adhesion ( )
2017-05-26 01:07:10 +00:00
else :
2017-07-18 01:49:36 +00:00
return max ( self . end_adhesion ( ) , self . end_whitelist )
2017-05-26 01:07:10 +00:00
2017-06-26 17:23:01 +00:00
@cached_property
def solde ( self ) :
options , created = OptionalUser . objects . get_or_create ( )
user_solde = options . user_solde
if user_solde :
solde_object , created = Paiement . objects . get_or_create ( moyen = ' Solde ' )
somme_debit = Vente . objects . filter ( facture__in = Facture . objects . filter ( user = self , paiement = solde_object ) ) . aggregate ( total = models . Sum ( models . F ( ' prix ' ) * models . F ( ' number ' ) , output_field = models . FloatField ( ) ) ) [ ' total ' ] or 0
somme_credit = Vente . objects . filter ( facture__in = Facture . objects . filter ( user = self ) , name = " solde " ) . aggregate ( total = models . Sum ( models . F ( ' prix ' ) * models . F ( ' number ' ) , output_field = models . FloatField ( ) ) ) [ ' total ' ] or 0
return somme_credit - somme_debit
else :
return 0
2016-11-24 00:18:15 +00:00
def user_interfaces ( self ) :
2016-12-18 22:25:21 +00:00
return Interface . objects . filter ( machine__in = Machine . objects . filter ( user = self , active = True ) )
2016-11-24 00:18:15 +00:00
2017-07-21 04:49:39 +00:00
def assign_ips ( self ) :
""" Assign une ipv4 aux machines d ' un user """
interfaces = self . user_interfaces ( )
for interface in interfaces :
if not interface . ipv4 :
with transaction . atomic ( ) , reversion . create_revision ( ) :
interface . assign_ipv4 ( )
reversion . set_comment ( " Assignation ipv4 " )
interface . save ( )
def unassign_ips ( self ) :
interfaces = self . user_interfaces ( )
for interface in interfaces :
with transaction . atomic ( ) , reversion . create_revision ( ) :
interface . unassign_ipv4 ( )
reversion . set_comment ( " Désassignation ipv4 " )
interface . save ( )
def archive ( self ) :
self . unassign_ips ( )
self . state = User . STATE_ARCHIVE
def unarchive ( self ) :
self . assign_ips ( )
self . state = User . STATE_ACTIVE
2016-07-08 01:12:28 +00:00
def has_module_perms ( self , app_label ) :
# Simplest version again
return True
def make_admin ( self ) :
""" Make User admin """
user_admin_right = Right ( user = self , right = get_admin_right ( ) )
user_admin_right . save ( )
def un_admin ( self ) :
try :
user_right = Right . objects . get ( user = self , right = get_admin_right ( ) )
except Right . DoesNotExist :
return
user_right . delete ( )
2016-07-26 00:54:32 +00:00
def ldap_sync ( self , base = True , access_refresh = True , mac_refresh = True ) :
2016-07-31 01:36:54 +00:00
self . refresh_from_db ( )
2016-07-26 00:54:32 +00:00
try :
2016-10-11 15:11:46 +00:00
user_ldap = LdapUser . objects . get ( uidNumber = self . uid_number )
2016-07-26 00:54:32 +00:00
except LdapUser . DoesNotExist :
2016-10-11 15:11:46 +00:00
user_ldap = LdapUser ( uidNumber = self . uid_number )
2016-07-26 00:54:32 +00:00
if base :
2016-07-31 03:03:07 +00:00
user_ldap . name = self . pseudo
2016-07-26 00:54:32 +00:00
user_ldap . sn = self . pseudo
2017-07-18 01:49:36 +00:00
user_ldap . dialupAccess = str ( self . has_access ( ) )
2016-07-26 00:54:32 +00:00
user_ldap . home_directory = ' /home/ ' + self . pseudo
user_ldap . mail = self . email
user_ldap . given_name = str ( self . surname ) . lower ( ) + ' _ ' + str ( self . name ) . lower ( ) [ : 3 ]
2016-07-27 00:39:19 +00:00
user_ldap . gid = LDAP [ ' user_gid ' ]
2016-11-20 15:53:59 +00:00
user_ldap . user_password = self . password [ : 6 ] + self . password [ 7 : ]
2016-11-21 17:32:53 +00:00
user_ldap . sambat_nt_password = self . pwd_ntlm . upper ( )
2016-07-31 01:36:54 +00:00
if self . shell :
2017-06-26 20:23:58 +00:00
user_ldap . login_shell = self . shell . shell
if self . state == self . STATE_DISABLED :
user_ldap . shadowexpire = str ( 0 )
else :
user_ldap . shadowexpire = None
2016-07-26 00:54:32 +00:00
if access_refresh :
2017-07-18 01:49:36 +00:00
user_ldap . dialupAccess = str ( self . has_access ( ) )
2016-07-26 00:54:32 +00:00
if mac_refresh :
2016-12-14 02:08:57 +00:00
user_ldap . macs = [ inter . mac_bare ( ) for inter in Interface . objects . filter ( machine__in = Machine . objects . filter ( user = self ) ) ]
2016-07-26 00:54:32 +00:00
user_ldap . save ( )
def ldap_del ( self ) :
try :
user_ldap = LdapUser . objects . get ( name = self . pseudo )
user_ldap . delete ( )
except LdapUser . DoesNotExist :
pass
2017-08-28 19:51:12 +00:00
def notif_inscription ( self ) :
""" Prend en argument un objet user, envoie un mail de bienvenue """
t = loader . get_template ( ' users/email_welcome ' )
2017-09-08 20:53:13 +00:00
assooptions , created = AssoOption . objects . get_or_create ( )
mailmessageoptions , created = MailMessageOption . objects . get_or_create ( )
2017-08-28 19:51:12 +00:00
general_options , created = GeneralOption . objects . get_or_create ( )
c = Context ( {
' nom ' : str ( self . name ) + ' ' + str ( self . surname ) ,
2017-09-08 20:53:13 +00:00
' asso_name ' : assooptions . name ,
' asso_email ' : assooptions . contact ,
' welcome_mail_fr ' : mailmessageoptions . welcome_mail_fr ,
' welcome_mail_en ' : mailmessageoptions . welcome_mail_en ,
2017-08-28 19:51:12 +00:00
' pseudo ' : self . pseudo ,
} )
2017-09-08 20:53:13 +00:00
send_mail ( ' Bienvenue au %(name)s / Welcome to %(name)s ' % { ' name ' : assooptions . name } , ' ' ,
2017-08-28 19:51:12 +00:00
general_options . email_from , [ self . email ] , html_message = t . render ( c ) )
return
def reset_passwd_mail ( self , request ) :
""" Prend en argument un request, envoie un mail de réinitialisation de mot de pass """
req = Request ( )
req . type = Request . PASSWD
req . user = self
req . save ( )
t = loader . get_template ( ' users/email_passwd_request ' )
options , created = AssoOption . objects . get_or_create ( )
general_options , created = GeneralOption . objects . get_or_create ( )
c = {
' name ' : str ( req . user . name ) + ' ' + str ( req . user . surname ) ,
' asso ' : options . name ,
' asso_mail ' : options . contact ,
' site_name ' : general_options . site_name ,
' url ' : request . build_absolute_uri (
reverse ( ' users:process ' , kwargs = { ' token ' : req . token } ) ) ,
' expire_in ' : str ( general_options . req_expire_hrs ) + ' heures ' ,
}
send_mail ( ' Changement de mot de passe du %(name)s / Password renewal for %(name)s ' % { ' name ' : options . name } , t . render ( c ) ,
general_options . email_from , [ req . user . email ] , fail_silently = False )
return
2017-09-14 16:15:14 +00:00
def autoregister_machine ( self , mac_address , nas_type ) :
2017-09-10 20:50:20 +00:00
all_machines = self . all_machines ( )
options , created = OptionalMachine . objects . get_or_create ( )
2017-09-10 23:29:24 +00:00
if all_machines . count ( ) > options . max_lambdauser_interfaces :
2017-09-10 20:50:20 +00:00
return False , " Maximum de machines enregistrees atteinte "
2017-09-14 16:15:14 +00:00
if not nas_type :
2017-09-10 23:29:24 +00:00
return False , " Re2o ne sait pas à quel machinetype affecter cette machine "
2017-09-14 16:15:14 +00:00
machine_type_cible = nas_type . machine_type
2017-09-10 20:50:20 +00:00
try :
machine_parent = Machine ( )
machine_parent . user = self
interface_cible = Interface ( )
interface_cible . mac_address = mac_address
2017-09-10 23:29:24 +00:00
interface_cible . type = machine_type_cible
2017-09-10 20:50:20 +00:00
interface_cible . clean ( )
machine_parent . clean ( )
domain = Domain ( )
domain . name = self . pseudo . replace ( ' _ ' , ' - ' ) . lower ( ) + str ( all_machines . count ( ) )
2017-09-11 01:37:01 +00:00
machine_parent . save ( )
interface_cible . machine = machine_parent
interface_cible . save ( )
domain . interface_parent = interface_cible
domain . clean ( )
domain . save ( )
2017-09-10 20:50:20 +00:00
except Exception as e :
return False , e
return True , " Ok "
def all_machines ( self ) :
2017-09-10 23:29:24 +00:00
return Interface . objects . filter ( machine__in = Machine . objects . filter ( user = self ) )
2017-09-10 20:50:20 +00:00
2016-06-30 23:03:28 +00:00
def __str__ ( self ) :
2016-07-02 02:40:24 +00:00
return self . pseudo
2016-06-30 01:39:07 +00:00
2016-11-20 15:53:59 +00:00
@receiver ( post_save , sender = User )
def user_post_save ( sender , * * kwargs ) :
2017-08-28 19:51:12 +00:00
is_created = kwargs [ ' created ' ]
2016-11-20 15:53:59 +00:00
user = kwargs [ ' instance ' ]
2017-08-28 19:51:12 +00:00
if is_created :
user . notif_inscription ( )
2016-11-20 15:53:59 +00:00
user . ldap_sync ( base = True , access_refresh = True , mac_refresh = False )
2016-07-26 00:54:32 +00:00
@receiver ( post_delete , sender = User )
def user_post_delete ( sender , * * kwargs ) :
user = kwargs [ ' instance ' ]
2016-11-20 15:53:59 +00:00
user . ldap_del ( )
2016-07-08 01:12:28 +00:00
2016-07-31 01:36:54 +00:00
class ServiceUser ( AbstractBaseUser ) :
2017-06-18 12:59:53 +00:00
readonly = ' readonly '
ACCESS = (
( ' auth ' , ' auth ' ) ,
( ' readonly ' , ' readonly ' ) ,
( ' usermgmt ' , ' usermgmt ' ) ,
)
2016-11-01 01:14:06 +00:00
PRETTY_NAME = " Utilisateurs de service "
2016-07-31 01:36:54 +00:00
pseudo = models . CharField ( max_length = 32 , unique = True , help_text = " Doit contenir uniquement des lettres, chiffres, ou tirets " , validators = [ linux_user_validator ] )
2017-06-18 12:59:53 +00:00
access_group = models . CharField ( choices = ACCESS , default = readonly , max_length = 32 )
2017-06-18 17:24:53 +00:00
comment = models . CharField ( help_text = " Commentaire " , max_length = 255 , blank = True )
2016-07-31 01:36:54 +00:00
USERNAME_FIELD = ' pseudo '
objects = UserManager ( )
def ldap_sync ( self ) :
try :
user_ldap = LdapServiceUser . objects . get ( name = self . pseudo )
except LdapServiceUser . DoesNotExist :
user_ldap = LdapServiceUser ( name = self . pseudo )
2017-06-18 12:59:53 +00:00
user_ldap . user_password = self . password [ : 6 ] + self . password [ 7 : ]
2016-07-31 01:36:54 +00:00
user_ldap . save ( )
2017-06-18 12:59:53 +00:00
self . serviceuser_group_sync ( )
2016-07-31 01:36:54 +00:00
def ldap_del ( self ) :
try :
user_ldap = LdapServiceUser . objects . get ( name = self . pseudo )
user_ldap . delete ( )
except LdapUser . DoesNotExist :
pass
2017-06-18 12:59:53 +00:00
self . serviceuser_group_sync ( )
def serviceuser_group_sync ( self ) :
try :
group = LdapServiceUserGroup . objects . get ( name = self . access_group )
except :
group = LdapServiceUserGroup ( name = self . access_group )
2017-08-26 13:10:18 +00:00
group . members = list ( LdapServiceUser . objects . filter ( name__in = [ user . pseudo for user in ServiceUser . objects . filter ( access_group = self . access_group ) ] ) . values_list ( ' dn ' , flat = True ) )
2017-06-18 12:59:53 +00:00
group . save ( )
2016-07-31 01:36:54 +00:00
def __str__ ( self ) :
return self . pseudo
@receiver ( post_save , sender = ServiceUser )
def service_user_post_save ( sender , * * kwargs ) :
service_user = kwargs [ ' instance ' ]
2017-06-18 12:59:53 +00:00
service_user . ldap_sync ( )
2016-07-31 01:36:54 +00:00
@receiver ( post_delete , sender = ServiceUser )
def service_user_post_delete ( sender , * * kwargs ) :
service_user = kwargs [ ' instance ' ]
2017-06-18 12:59:53 +00:00
service_user . ldap_del ( )
2016-07-31 01:36:54 +00:00
2016-07-02 00:42:04 +00:00
class Right ( models . Model ) :
2016-11-01 01:14:06 +00:00
PRETTY_NAME = " Droits affectés à des users "
2016-07-08 01:12:28 +00:00
user = models . ForeignKey ( ' User ' , on_delete = models . PROTECT )
2016-07-02 00:42:04 +00:00
right = models . ForeignKey ( ' ListRight ' , on_delete = models . PROTECT )
2016-07-08 01:12:28 +00:00
2016-07-02 00:42:04 +00:00
class Meta :
unique_together = ( " user " , " right " )
2016-07-02 02:40:24 +00:00
def __str__ ( self ) :
2017-07-07 02:13:25 +00:00
return str ( self . user )
2016-07-02 02:40:24 +00:00
2016-07-26 00:54:32 +00:00
@receiver ( post_save , sender = Right )
def right_post_save ( sender , * * kwargs ) :
right = kwargs [ ' instance ' ] . right
2016-11-20 15:53:59 +00:00
right . ldap_sync ( )
2016-07-26 00:54:32 +00:00
@receiver ( post_delete , sender = Right )
def right_post_delete ( sender , * * kwargs ) :
right = kwargs [ ' instance ' ] . right
2016-11-20 15:53:59 +00:00
right . ldap_sync ( )
2016-07-08 01:12:28 +00:00
2016-06-30 01:39:07 +00:00
class School ( models . Model ) :
2016-11-01 01:14:06 +00:00
PRETTY_NAME = " Etablissements enregistrés "
2016-06-30 01:39:07 +00:00
name = models . CharField ( max_length = 255 )
2016-06-30 23:03:28 +00:00
def __str__ ( self ) :
return self . name
2016-07-08 01:12:28 +00:00
2016-07-02 00:42:04 +00:00
class ListRight ( models . Model ) :
2016-11-01 01:14:06 +00:00
PRETTY_NAME = " Liste des droits existants "
2016-07-08 01:12:28 +00:00
listright = models . CharField ( max_length = 255 , unique = True )
2016-07-26 00:54:32 +00:00
gid = models . IntegerField ( unique = True , null = True )
2016-11-21 00:49:45 +00:00
details = models . CharField ( help_text = " Description " , max_length = 255 , blank = True )
2016-07-02 00:42:04 +00:00
def __str__ ( self ) :
return self . listright
2016-07-26 00:54:32 +00:00
def ldap_sync ( self ) :
try :
group_ldap = LdapUserGroup . objects . get ( gid = self . gid )
except LdapUserGroup . DoesNotExist :
group_ldap = LdapUserGroup ( gid = self . gid )
group_ldap . name = self . listright
group_ldap . members = [ right . user . pseudo for right in Right . objects . filter ( right = self ) ]
group_ldap . save ( )
def ldap_del ( self ) :
try :
group_ldap = LdapUserGroup . objects . get ( gid = self . gid )
group_ldap . delete ( )
except LdapUserGroup . DoesNotExist :
pass
@receiver ( post_save , sender = ListRight )
def listright_post_save ( sender , * * kwargs ) :
right = kwargs [ ' instance ' ]
2016-11-20 15:53:59 +00:00
right . ldap_sync ( )
2016-07-26 00:54:32 +00:00
@receiver ( post_delete , sender = ListRight )
def listright_post_delete ( sender , * * kwargs ) :
right = kwargs [ ' instance ' ]
2016-11-20 15:53:59 +00:00
right . ldap_del ( )
2016-07-26 00:54:32 +00:00
class ListShell ( models . Model ) :
2016-11-01 01:14:06 +00:00
PRETTY_NAME = " Liste des shells disponibles "
2016-07-26 00:54:32 +00:00
shell = models . CharField ( max_length = 255 , unique = True )
def __str__ ( self ) :
return self . shell
2016-07-08 01:12:28 +00:00
2016-07-02 19:57:31 +00:00
class Ban ( models . Model ) :
2016-11-01 01:14:06 +00:00
PRETTY_NAME = " Liste des bannissements "
2017-03-06 01:28:16 +00:00
STATE_HARD = 0
STATE_SOFT = 1
STATE_BRIDAGE = 2
STATES = (
( 0 , ' HARD (aucun accès) ' ) ,
( 1 , ' SOFT (accès local seulement) ' ) ,
( 2 , ' BRIDAGE (bridage du débit) ' ) ,
)
2016-07-02 19:57:31 +00:00
user = models . ForeignKey ( ' User ' , on_delete = models . PROTECT )
raison = models . CharField ( max_length = 255 )
2016-07-02 23:29:26 +00:00
date_start = models . DateTimeField ( auto_now_add = True )
2016-07-08 01:12:28 +00:00
date_end = models . DateTimeField ( help_text = ' %d / % m/ % y % H: % M: % S ' )
2017-03-06 01:28:16 +00:00
state = models . IntegerField ( choices = STATES , default = STATE_HARD )
2016-07-02 19:57:31 +00:00
2017-08-28 19:51:12 +00:00
def notif_ban ( self ) :
""" Prend en argument un objet ban, envoie un mail de notification """
general_options , created = GeneralOption . objects . get_or_create ( )
t = loader . get_template ( ' users/email_ban_notif ' )
options , created = AssoOption . objects . get_or_create ( )
c = Context ( {
' name ' : str ( self . user . name ) + ' ' + str ( self . user . surname ) ,
' raison ' : self . raison ,
' date_end ' : self . date_end ,
' asso_name ' : options . name ,
} )
send_mail ( ' Deconnexion disciplinaire ' , t . render ( c ) ,
general_options . email_from , [ self . user . email ] , fail_silently = False )
return
2016-07-02 19:57:31 +00:00
def __str__ ( self ) :
return str ( self . user ) + ' ' + str ( self . raison )
2016-11-20 15:53:59 +00:00
@receiver ( post_save , sender = Ban )
def ban_post_save ( sender , * * kwargs ) :
ban = kwargs [ ' instance ' ]
2017-08-28 19:51:12 +00:00
is_created = kwargs [ ' created ' ]
2016-11-20 15:53:59 +00:00
user = ban . user
user . ldap_sync ( base = False , access_refresh = True , mac_refresh = False )
2017-08-28 19:51:12 +00:00
if is_created :
ban . notif_ban ( )
2017-09-01 01:15:54 +00:00
regen ( ' dhcp ' )
regen ( ' mac_ip_list ' )
if user . has_access ( ) :
regen ( ' dhcp ' )
regen ( ' mac_ip_list ' )
2016-11-20 15:53:59 +00:00
@receiver ( post_delete , sender = Ban )
def ban_post_delete ( sender , * * kwargs ) :
user = kwargs [ ' instance ' ] . user
user . ldap_sync ( base = False , access_refresh = True , mac_refresh = False )
2017-09-01 01:15:54 +00:00
regen ( ' dhcp ' )
regen ( ' mac_ip_list ' )
2016-07-08 01:12:28 +00:00
2016-07-04 18:04:11 +00:00
class Whitelist ( models . Model ) :
2016-11-01 01:14:06 +00:00
PRETTY_NAME = " Liste des accès gracieux "
2016-07-04 18:04:11 +00:00
user = models . ForeignKey ( ' User ' , on_delete = models . PROTECT )
raison = models . CharField ( max_length = 255 )
date_start = models . DateTimeField ( auto_now_add = True )
2016-07-05 14:30:46 +00:00
date_end = models . DateTimeField ( help_text = ' %d / % m/ % y % H: % M: % S ' )
2016-07-04 18:04:11 +00:00
def __str__ ( self ) :
return str ( self . user ) + ' ' + str ( self . raison )
2016-11-20 15:53:59 +00:00
@receiver ( post_save , sender = Whitelist )
def whitelist_post_save ( sender , * * kwargs ) :
whitelist = kwargs [ ' instance ' ]
user = whitelist . user
user . ldap_sync ( base = False , access_refresh = True , mac_refresh = False )
2017-09-01 01:15:54 +00:00
is_created = kwargs [ ' created ' ]
if is_created :
regen ( ' dhcp ' )
regen ( ' mac_ip_list ' )
if user . has_access ( ) :
regen ( ' dhcp ' )
regen ( ' mac_ip_list ' )
2016-11-20 15:53:59 +00:00
@receiver ( post_delete , sender = Whitelist )
def whitelist_post_delete ( sender , * * kwargs ) :
user = kwargs [ ' instance ' ] . user
user . ldap_sync ( base = False , access_refresh = True , mac_refresh = False )
2017-09-01 01:15:54 +00:00
regen ( ' dhcp ' )
regen ( ' mac_ip_list ' )
2016-11-20 15:53:59 +00:00
2016-07-20 01:53:46 +00:00
class Request ( models . Model ) :
PASSWD = ' PW '
EMAIL = ' EM '
TYPE_CHOICES = (
( PASSWD , ' Mot de passe ' ) ,
( EMAIL , ' Email ' ) ,
)
type = models . CharField ( max_length = 2 , choices = TYPE_CHOICES )
token = models . CharField ( max_length = 32 )
user = models . ForeignKey ( ' User ' , on_delete = models . PROTECT )
created_at = models . DateTimeField ( auto_now_add = True , editable = False )
expires_at = models . DateTimeField ( )
def save ( self ) :
if not self . expires_at :
2017-08-26 14:04:51 +00:00
options , created = GeneralOption . objects . get_or_create ( )
2016-07-20 01:53:46 +00:00
self . expires_at = timezone . now ( ) \
2017-08-26 14:04:51 +00:00
+ datetime . timedelta ( hours = options . req_expire_hrs )
2016-07-20 01:53:46 +00:00
if not self . token :
self . token = str ( uuid . uuid4 ( ) ) . replace ( ' - ' , ' ' ) # remove hyphens
super ( Request , self ) . save ( )
2016-07-26 00:54:32 +00:00
class LdapUser ( ldapdb . models . Model ) :
"""
Class for representing an LDAP user entry .
"""
# LDAP meta-data
2016-07-27 00:39:19 +00:00
base_dn = LDAP [ ' base_user_dn ' ]
2017-06-26 20:23:58 +00:00
object_classes = [ ' inetOrgPerson ' , ' top ' , ' posixAccount ' , ' sambaSamAccount ' , ' radiusprofile ' , ' shadowAccount ' ]
2016-07-26 00:54:32 +00:00
# attributes
gid = ldapdb . models . fields . IntegerField ( db_column = ' gidNumber ' )
name = ldapdb . models . fields . CharField ( db_column = ' cn ' , max_length = 200 , primary_key = True )
uid = ldapdb . models . fields . CharField ( db_column = ' uid ' , max_length = 200 )
uidNumber = ldapdb . models . fields . IntegerField ( db_column = ' uidNumber ' , unique = True )
sn = ldapdb . models . fields . CharField ( db_column = ' sn ' , max_length = 200 )
2016-07-31 03:03:07 +00:00
login_shell = ldapdb . models . fields . CharField ( db_column = ' loginShell ' , max_length = 200 , blank = True , null = True )
2016-07-26 00:54:32 +00:00
mail = ldapdb . models . fields . CharField ( db_column = ' mail ' , max_length = 200 )
given_name = ldapdb . models . fields . CharField ( db_column = ' givenName ' , max_length = 200 )
home_directory = ldapdb . models . fields . CharField ( db_column = ' homeDirectory ' , max_length = 200 )
2016-07-27 00:39:19 +00:00
display_name = ldapdb . models . fields . CharField ( db_column = ' displayName ' , max_length = 200 , blank = True , null = True )
2016-07-26 00:54:32 +00:00
dialupAccess = ldapdb . models . fields . CharField ( db_column = ' dialupAccess ' )
sambaSID = ldapdb . models . fields . IntegerField ( db_column = ' sambaSID ' , unique = True )
user_password = ldapdb . models . fields . CharField ( db_column = ' userPassword ' , max_length = 200 , blank = True , null = True )
sambat_nt_password = ldapdb . models . fields . CharField ( db_column = ' sambaNTPassword ' , max_length = 200 , blank = True , null = True )
macs = ldapdb . models . fields . ListField ( db_column = ' radiusCallingStationId ' , max_length = 200 , blank = True , null = True )
2017-06-26 20:23:58 +00:00
shadowexpire = ldapdb . models . fields . CharField ( db_column = ' shadowExpire ' , blank = True , null = True )
2016-07-26 00:54:32 +00:00
def __str__ ( self ) :
return self . name
def __unicode__ ( self ) :
return self . name
def save ( self , * args , * * kwargs ) :
self . sn = self . name
self . uid = self . name
self . sambaSID = self . uidNumber
super ( LdapUser , self ) . save ( * args , * * kwargs )
class LdapUserGroup ( ldapdb . models . Model ) :
"""
Class for representing an LDAP user entry .
"""
# LDAP meta-data
2016-07-27 00:39:19 +00:00
base_dn = LDAP [ ' base_usergroup_dn ' ]
2016-07-26 00:54:32 +00:00
object_classes = [ ' posixGroup ' ]
# attributes
gid = ldapdb . models . fields . IntegerField ( db_column = ' gidNumber ' )
members = ldapdb . models . fields . ListField ( db_column = ' memberUid ' , blank = True )
name = ldapdb . models . fields . CharField ( db_column = ' cn ' , max_length = 200 , primary_key = True )
def __str__ ( self ) :
return self . name
2016-07-31 01:36:54 +00:00
class LdapServiceUser ( ldapdb . models . Model ) :
"""
Class for representing an LDAP userservice entry .
"""
# LDAP meta-data
base_dn = LDAP [ ' base_userservice_dn ' ]
object_classes = [ ' applicationProcess ' , ' simpleSecurityObject ' ]
# attributes
name = ldapdb . models . fields . CharField ( db_column = ' cn ' , max_length = 200 , primary_key = True )
user_password = ldapdb . models . fields . CharField ( db_column = ' userPassword ' , max_length = 200 , blank = True , null = True )
2017-06-18 12:59:53 +00:00
def __str__ ( self ) :
return self . name
class LdapServiceUserGroup ( ldapdb . models . Model ) :
"""
Class for representing an LDAP userservice entry .
"""
# LDAP meta-data
base_dn = LDAP [ ' base_userservicegroup_dn ' ]
object_classes = [ ' groupOfNames ' ]
# attributes
name = ldapdb . models . fields . CharField ( db_column = ' cn ' , max_length = 200 , primary_key = True )
members = ldapdb . models . fields . ListField ( db_column = ' member ' , blank = True )
def __str__ ( self ) :
return self . name