[gestion] Ajout d'un début de gest_crans utilisant lc_ldap

This commit is contained in:
Valentin Samir 2014-03-03 11:22:20 +01:00
parent 8962c3b33d
commit 21341577a5

305
gestion/gest_crans_lc.py Executable file
View file

@ -0,0 +1,305 @@
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
u"""
Interface utilisateur du système de gestion des machines
et adhérents du crans
Copyright (C) Valentin Samir
Licence : GPLv3
"""
import os
import sys
import signal
from pythondialog import Dialog
from gestion.affich_tools import get_screen_size, coul
import lc_ldap.shortcuts
import lc_ldap.printing as printing
def handle_exit_code(d, code):
if code in (d.DIALOG_CANCEL, d.DIALOG_ESC):
if code == d.DIALOG_CANCEL:
msg = "Vous avez choisi Annuler dans la dernière fenêtre de dialogue.\n\n" \
"Voulez vous quitter le programme ?"
os.system('clear')
sys.exit(0)
else:
msg = "Vous avez appuyer sur ESC dans la dernière fenêtre de dialogue.\n\n" \
"Voulez vous quitter le programme ?"
if d.yesno(msg, width=60) == d.DIALOG_OK:
os.system('clear')
sys.exit(0)
return False
else:
return True # code est d.DIALOG_OK
def search(dialog, objectClassS, title, values={}):
"""
Rechercher des adhérents ou des machines dans la base ldap
retourne le tuple (code de retour dialog, valeurs entrée par l'utilisateur, liste d'objets trouvés)
La fonction est découpé en trois partie :
* affichage dialog et récupération du résultat
* construction de filtres de recherche ldap et recherches ldap
* filtre sur les résultats des recherches ldap
"""
select_dict = {
#label attribut ldap search for substring param dialog: line col valeur input-line icol len max-chars
'Nom' : {'ldap':'nom', 'sub':True, 'params' : [ 1, 1, values.get('nom', ""), 1, 13, 20, 20]},
'Prenom' : {'ldap':'prenom', 'sub':True, 'params' : [ 2, 1, values.get('prenom', ""), 2, 13, 20, 20]},
'Téléphone' : {'ldap':'tel', 'sub':True, 'params' : [ 3, 1, values.get('tel', ""), 3, 13, 10, 00]},
'Chambre' : {'ldap':'chbre','sub':True, 'params' : [ 4, 1, values.get('chbre',""), 4, 13, 05, 00]},
'aid' : {'ldap' : 'aid', 'sub':False, 'params' : [ 5, 1, values.get('aid',""), 5, 13, 05, 05]},
'mail' : {'ldap' : 'mail', 'sub':True, 'params' : [ 6, 1, values.get('mail',""), 6, 13, 20, 00]},
# seconde colone
'Machine' : {'ldap' : '*', 'sub':True, 'params' : [1, 35, "", 1, 43, 0, 0]},
'Host' : {'ldap' : 'host', 'sub':True, 'params' : [2, 37, values.get('host',""), 2, 43, 17, 17]},
'Mac' : {'ldap' : 'macAddress', 'sub':False, 'params' : [3, 37, values.get('macAddress',""), 3, 43, 17, 17]},
'IP' : {'ldap' : 'ipHostNumber', 'sub':False,'params' : [4, 37, values.get('ipHostNumber',""), 4, 43, 15, 15]},
'mid' : {'ldap' : 'mid', 'sub':False, 'params' : [5, 37, values.get('mid',""), 5, 43, 5, 5]},
}
# On a besoin de l'ordre pour récupérer les valeurs ensuite
select_adherent = ['Nom', 'Prenom', 'Téléphone', 'Chambre', 'aid', 'mail']
select_machine = ['Host', 'Mac', 'IP', 'mid']
def box():
# On met les argument à dialog à la main ici, sinon, c'est difficile de choisir comment mettre une seconde colone
cmd = ["--form", "Entrez vos paramètres de recherche", '0', '0', '0']
for key in select_adherent:
cmd.extend(['%s :' % key] + [str(e) for e in select_dict[key]['params']])
cmd.extend(['Machine :'] + [str(e) for e in select_dict['Machine']['params']])
for key in select_machine:
cmd.extend(['%s :' % key] + [str(e) for e in select_dict[key]['params']])
cmd.extend(["Les champs vides sont ignorés.", '7', '1', "", '0', '0', '0', '0'])
# On utilise quand même la fonction de la bibliothèques pour passer les arguments
(code, output) = dialog._perform(*(cmd,), title=title, backtitle="Entrez vos paramètres de recherche")
if output:
return (code, output.split('\n')[:-1])
else: # empty selection
return (code, [])
(code, dialog_values) = box()
if code in (dialog.DIALOG_CANCEL, dialog.DIALOG_ESC):
return code, values, []
else:
# Transformation de la liste des valeures entrée en dictionnnaire
dialog_values = dict(zip(select_adherent + select_machine, dialog_values))
ldap_values = dict([(select_dict[key]['ldap'], value) for key, value in dialog_values.items()])
# Construction des filtres ldap pour les adhérents et les machines
filter_adherent = []
filter_machine = []
for (key, value) in dialog_values.items():
if value:
if key in select_adherent:
filter_adherent.append((u"(%s=*%s*)" if select_dict[key]['sub'] else u"(%s=%s)") % (select_dict[key]['ldap'], unicode(value, 'utf-8')))
elif key in select_machine:
filter_machine.append((u"(%s=*%s*)" if select_dict[key]['sub'] else u"(%s=%s)") % (select_dict[key]['ldap'], unicode(value, 'utf-8')))
if filter_adherent:
filter_adherent=u"(&%s)" % "".join(filter_adherent)
if filter_machine:
filter_machine=u"(&%s)" % "".join(filter_machine)
# Récupération des adhérents et des machines
adherents=conn.search(filter_adherent) if filter_adherent else []
machines=conn.search(filter_machine) if filter_machine else []
# Filtrage des machines en fonction des adhérents
if filter_adherent:
if filter_machine:
# Si on filtre sur des adhérent et des machines, on calcule l'intersection
adherents_dn = set([a.dn for a in adherents])
machines_f = [m for m in machines if m.parent_dn in adherents_dn]
else:
# Sinon on filtre seulement sur les adhérents, récupère les machines des adhérents trouvés
machines_f = [m for a in adherents for m in a.machines()]
else:
# Sinon si on filtre seulement sur des machines
machines_f = machines
# Filtrage des adhérents en fonction des machines
if filter_machine:
if filter_adherent:
# Si on filtre sur des adhérents et des machines, on calcule l'intersection
machines_dn = set([m.parent_dn for m in machines])
adherents_f = [a for a in adherents if a.dn in machines_dn]
else:
# Sinon on récupères les proprios des machines trouvées
adherents_f = [m.proprio() for m in machines]
else:
# Sinon si on filtre seulement sur des adhérents
adherents_f = adherents
# On filtre sur les objectClassS
return code, ldap_values, [ o for objectClass in objectClassS for o in machines_f+adherents_f if objectClass in o['objectClass'] ]
def select_one(dialog, items, default_item=None):
"""Fait selectionner un item parmis une liste d'items à l'utisateur"""
### TODO afficher correctement les objets dans items
choices=[]
count = 0
default_tag = items.index(default_item) if default_item in items else default_item
for i in items:
choices.append((str(count), str(i), 1 if default_tag == count else 0))
count+=1
tag=''
while not tag:
(line, col) = get_screen_size()
(code, tag) = dialog.radiolist(
"Choisir",
choices=choices,
default_item=str(default_tag),
width=col-4,
height=line-3,
list_height=line-3,
scrollbar=True)
if code in (dialog.DIALOG_CANCEL, dialog.DIALOG_ESC):
return code, None
if not tag:
dialog.msgbox("Merci de choisir l'un des item de la liste ou d'annuler", title="Sélection", width=0, height=0)
return code, items[int(tag)]
def select_confirm(dialog, item, title):
"""Affiche un item et demande si c'est bien celui là que l'on veux (supprimer, éditer, créer,...)"""
return dialog.yesno(printing.sprint(item), no_collapse=True, colors=True, title=title, width=0, height=0, backtitle="Appuyez sur MAJ pour selectionner du texte") == dialog.DIALOG_OK
def select(dialog, objectClassS, title, values={}):
"""Permet de choisir un objet adhérent ou machine dans la base ldap"""
while True:
try:
# On fait effectuer une recherche à l'utilisateur
code, values, items = search(dialog, objectClassS, title, values)
# Si il a appuyé sur annuler ou sur escape, on annule
if code in (dialog.DIALOG_CANCEL, dialog.DIALOG_ESC):
return code, None
# S'il n'y a pas de résultas, on recommence
elif not items:
dialog.msgbox("Aucun Résultat", title="Recherche", width=0, height=0)
# S'il y a plusieurs résultats
elif len(items)>1:
item = None
while True:
# On en fait choisir un
code, item = select_one(dialog, items, item)
# Si il à appuyer sur annuler ou sur escape, on recommence la recherche
if code in (dialog.DIALOG_CANCEL, dialog.DIALOG_ESC):
break
# Sinon, on fait confirmer son choix à l'utilisateur
elif select_confirm(dialog, item, title):
return code, item
# S'il y a exactement 1 résultat à la recherche, on fait confirmer son choix à l'utilisateur
elif len(items) == 1 and select_confirm(dialog, items[0], title):
return code, items[0]
except Exception as e:
dialog.msgbox("%r" % e, title="Erreur rencontrée", width=0, height=0)
def modif_adherent(dialog):
code, adherent = select(dialog, ["adherent"], "Recherche d'un adhérent")
if code in (dialog.DIALOG_CANCEL, dialog.DIALOG_ESC):
return code
dialog.msgbox("todo", width=0, height=0)
def create_adherent(dialog):
dialog.msgbox("todo", width=0, height=0)
def delete_adherent(dialog):
code, adherent = select(dialog, ["adherent"], "Recherche d'un adhérent")
if code in (dialog.DIALOG_CANCEL, dialog.DIALOG_ESC):
return code
dialog.msgbox("todo", width=0, height=0)
def modif_machine(dialog):
code, machine = select(dialog, ["machineFixe", "machineWifi", "machineCrans", "borneWifi"], "Recherche d'une machine")
if code in (dialog.DIALOG_CANCEL, dialog.DIALOG_ESC):
return code
dialog.msgbox("todo", width=0, height=0)
def create_machine_adherent(dialog):
dialog.msgbox("todo", width=0, height=0)
def delete_machine(dialog):
code, machine = select(dialog, ["machineFixe", "machineWifi", "machineCrans", "borneWifi"], "Recherche d'une machine")
if code in (dialog.DIALOG_CANCEL, dialog.DIALOG_ESC):
return code
dialog.msgbox("todo", width=0, height=0)
def create_club(dialog):
dialog.msgbox("todo", width=0, height=0)
def delete_club(dialog):
dialog.msgbox("todo", width=0, height=0)
def modif_club(dialog):
dialog.msgbox("todo", width=0, height=0)
def create_machine_club(dialog):
dialog.msgbox("todo", width=0, height=0)
def create_machine_crans(dialog):
dialog.msgbox("todo", width=0, height=0)
def create_borne(dialog):
dialog.msgbox("todo", width=0, height=0)
def menu_principal(dialog):
menu = {
'aA' : {'text':"Inscrire un nouvel adhérent", 'callback': create_adherent},
'mA' : {'text':"Modifier l'inscription d'un adhérent", 'callback': modif_adherent, 'help':"Changer la chambre, la remarque, la section, la carte d'étudiant ou précâbler."},
'aMA': {'text':"Ajouter une machine à un adhérent", 'callback': create_machine_adherent},
'dA' : {'text':"Détruire un adhérent", 'callback': delete_adherent, 'help':"Suppression de l'adhérent ainsi que de ses machines"},
'mM' : {'text':"Modifier une machine existante", 'callback': modif_machine, 'help':"Changer le nom ou la MAC d'une machine."},
'dM' : {'text':"Détruire une machine", 'callback': delete_machine},
'aC' : {'text':"Inscrire un nouveau club", 'callback': create_club},
'mC' : {'text':"Modifier un club", 'callback': modif_club},
'aMC': {'text':"Ajouter une machine à un club", 'callback': create_machine_club},
'dC' : {'text':"Détruire un club", 'callback': delete_club},
'aKM': {'text':"Ajouter une machine à l'association", 'callback': create_machine_crans},
'aKB': {'text':"Ajouter une borne wifi", 'callback': create_borne},
'' : {'text':"---------------------------------------",'callback': lambda x: x},
}
### Les clef qui n'existe pas sont toute renvoyé sur la clef ''
medu_order = ["aA", "mA", "aMA", "dA", "", "mM", "dM", " ", "aC", "mC", "aMC", "dC", " ", "aKM", "aKB"]
def box(default_item=None):
return dialog.menu(
"Que souhaitez vous faire ?",
width=55,
height=0,
menu_height=15,
item_help=1,
default_item=str(default_item),
title="Menu principal",
scrollbar=True,
cancel_label="Quitter",
backtitle=u"Vous êtes connecté en tant que %s" % conn.current_login,
choices=[(key, menu.get(key, menu[''])['text'], menu.get(key, menu['']).get('help', "")) for key in medu_order])
tag=None
while True:
(code, tag) = box(tag)
if handle_exit_code(dialog, code):
menu.get(tag, menu[''])['callback'](dialog)
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal.SIG_IGN)
# On initialise le moteur de rendu en spécifiant qu'on va faire du dialog
printing.template(dialog=True)
# On ouvre une connexion lc_ldap
conn = lc_ldap.shortcuts.lc_ldap_admin()
# On vérifie que l'utilisateur système existe dans ldap (pour la gestion des droits)
luser=conn.search(u"uid=%s" % conn.current_login)
if not luser:
sys.stderr.write("L'utilisateur %s n'existe pas dans la base de donnée" % conn.current_login)
sys.exit(1)
conn.droits = [str(d) for d in luser[0]['droits']]
conn.dn = luser[0].dn
dialog = Dialog()
menu_principal(dialog)
os.system('clear')