diff --git a/gestion/gest_crans_lc.py b/gestion/gest_crans_lc.py index 0bf6bb84..d1bdc06a 100755 --- a/gestion/gest_crans_lc.py +++ b/gestion/gest_crans_lc.py @@ -12,6 +12,7 @@ Licence : GPLv3 import os import sys import signal +import collections from pythondialog import Dialog from gestion.affich_tools import get_screen_size, coul @@ -19,6 +20,49 @@ from gestion.affich_tools import get_screen_size, coul import lc_ldap.shortcuts import lc_ldap.printing as printing +# Implémentation "à la main" de la tail récursion en python +# voir http://kylem.net/programming/tailcall.html +# je trouve ça assez sioux +class TailCaller(object) : + def __init__(self, f) : + self.f = f + def __call__(self, *args, **kwargs) : + ret = self.f(*args, **kwargs) + while isinstance(ret, TailCall) : + ret = ret.handle() + return ret + +def tailCaller(f): + f.tailCaller = True + return f + +class TailCall(object) : + def __init__(self, call, *args, **kwargs) : + if isinstance(call, TailCall): + call.update(**kwargs) + kwargs = call.kwargs + args = call.args + args + call = call.call + + self.call = call + self.args = args + self.kwargs = kwargs + + def __call__(self, *args, **kwargs): + self.kwargs.update(kwargs) + self.args = self.args + args + return self + + def update(self, **d): + self.kwargs.update(d) + return self + + def handle(self) : + if isinstance(self.call, TailCaller) : + return self.call.f(*self.args, **self.kwargs) + else : + return self.call(*self.args, **self.kwargs) + def handle_exit_code(d, code): if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): if code == d.DIALOG_CANCEL: @@ -37,269 +81,422 @@ def handle_exit_code(d, code): return True # code est d.DIALOG_OK +class GestCrans(object): + + def __getattribute__(self, attr): + ret = super(GestCrans, self).__getattribute__(attr) + if getattr(ret, 'tailCaller', False) and not isinstance(ret, TailCaller): + ret = TailCaller(ret) + setattr(self, attr, ret) + return ret + + def __init__(self): + 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) -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, []) + # On ouvre une connexion lc_ldap + self.conn = lc_ldap.shortcuts.lc_ldap_admin() + # On vérifie que l'utilisateur système existe dans ldap (pour la gestion des droits) + luser=self.conn.search(u'(&(uid=%s)(objectClass=cransAccount))' % self.conn.current_login) + if not luser: + sys.stderr.write("L'utilisateur %s n'existe pas dans la base de donnée" % self.conn.current_login) + sys.exit(1) + self.conn.droits = [str(d) for d in luser[0]['droits']] + self.conn.dn = luser[0].dn - (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()]) + self.dialog = Dialog() + self.menu_principal() + + @tailCaller + def search(self, objectClassS, title, values={}, cont=None): + """ + 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) = self.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, []) - # 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()] + (code, dialog_values) = box() + # Si il a appuyé sur annuler ou sur escape, on saute sur la continuation + if code in (self.dialog.DIALOG_CANCEL, self.dialog.DIALOG_ESC): + return cont else: - # Sinon si on filtre seulement sur des machines - machines_f = machines + # 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()]) - # Filtrage des adhérents en fonction des machines - if filter_machine: + # 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: - # 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] + 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=self.conn.search(filter_adherent) if filter_adherent else [] + machines=self.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 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 + # Sinon si on filtre seulement sur des machines + machines_f = machines - # 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'] ] + # 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 -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: + # On filtre sur les objectClassS + return ldap_values, [ o for objectClass in objectClassS for o in machines_f+adherents_f if objectClass in o['objectClass'] ] + + # select_one n'est pas un tailcaller, les continuations sont traitée par les fonctions appelantes + def select_one(self, items, title, default_item=None, cont=None): + """Fait selectionner un item parmis une liste d'items à l'utisateur""" + choices=[] + olist={} + count = 0 + + # On sépare les item d'items en fonction de leur type + for o in items: + olist[o.__class__] = olist.get(o.__class__, []) + [o] + default_tag = items.index(default_item) if default_item in items else default_item + + # On se débrouille pour faire corresponde l'ordre d'affichache des objets + # et leur ordre dans la liste items. On donne la largeur de l'affichage à la main + # pour prendre en compte la largeur du widget dialog + items=[] + items_id = {} (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)] + for c in olist.keys(): + items.extend(olist[c]) + items_s = printing.sprint_list(olist[c], col-20).encode('utf-8').split('\n') + choices.append(("", str(items_s[0]))) + choices.append(("", str(items_s[1]))) + for i in items_s[2:]: + choices.append((str(count), str(i))) + count+=1 + # On laisse une ligne vide pour séparer les listes d'objets de type différent + choices.append(("", "")) + # On supprime la dernière ligne qui est vide + del(choices[-1]) -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 + (code, tag) = self.dialog.menu( + "Que souhaitez vous faire ?", + width=0, + height=0, + menu_height=0, + item_help=0, + default_item=str(default_tag), + title=title, + scrollbar=True, + choices=choices, + colors=True) -def select(dialog, objectClassS, title, values={}): - """Permet de choisir un objet adhérent ou machine dans la base ldap""" - while True: + # Si l'utilisateur à annulé, on coninue avec la continuation + if code in (self.dialog.DIALOG_CANCEL, self.dialog.DIALOG_ESC): + return cont + # Si l'utilisateur n'a pas choisis une ligne correspondant à quelque chose + elif not tag: + self.dialog.msgbox("Merci de choisir l'un des item de la liste ou d'annuler", title="Sélection", width=0, height=0) + return TailCall(self.select_one, items, title, default_item, cont) + # Sinon on retourne l'item choisis + elif self.select_confirm(items[int(tag)], title): + return items[int(tag)] + else: + return cont + + def select_confirm(self, item, title): + """Affiche un item et demande si c'est bien celui là que l'on veux (supprimer, éditer, créer,...)""" + return self.dialog.yesno( + printing.sprint(item), + no_collapse=True, + colors=True, + title=title, + width=0, height=0, + backtitle="Appuyez sur MAJ pour selectionner du texte" + ) == self.dialog.DIALOG_OK + + @tailCaller + def select(self, objectClassS, title, values={}, cont=None): + """Permet de choisir un objet adhérent ou machine dans la base ldap""" 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 + values, items = self.search(objectClassS, title, values, cont=cont) # 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) + if not items: + self.dialog.msgbox("Aucun Résultat", title="Recherche", width=0, height=0) + return TailCall(self.select, objectClassS, title, values, cont=cont) # 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 + # On en fait choisir un, si c'est une continuation qui est renvoyé, elle est gérée par select + return self.select_one(items, title, cont=TailCall(self.select, objectClassS, title, values, cont)) # 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] + elif len(items) == 1: + item=items[0] + # On fait confirmer son choix à l'utilisateur + if self.select_confirm(item, title): + return item + else: + return TailCall(self.select, objectClassS, title, values, cont=cont) except Exception as e: - dialog.msgbox("%r" % e, title="Erreur rencontrée", width=0, height=0) + self.dialog.msgbox("%r" % e, title="Erreur rencontrée", width=0, height=0) + return TailCall(self.select, objectClassS, title, values, cont=cont) -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) + @tailCaller + def modif_adherent(self, cont, adherent=None): + if adherent is None: + adherent = self.select(["adherent"], "Recherche d'un adhérent pour modification", cont=cont) + self.dialog.msgbox("todo", width=0, height=0) + return cont(proprio=adherent) -def create_adherent(dialog): - dialog.msgbox("todo", width=0, height=0) + @tailCaller + def create_adherent(self, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont -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) + @tailCaller + def delete_adherent(self, cont): + adherent = self.select(["adherent"], "Recherche d'un adhérent pour supression", cont=cont) + self.dialog.msgbox("todo", width=0, height=0) + return cont -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 modif_machine_information(self, machine, cont): + self.dialog.msgbox("todo", width=0, height=0) + (code, tag) = self.dialog.form( + text="", + height=0, width=0, form_height=0, + fields=[("Nom de machine :", "", 10, 30), + ("Rugby Team", "", 20), + ("Car", "", 20), + ("Celebrity", "", 20)], + title="A demo of the form dialog.", + backtitle="And now, for something " + "completely different...") + return cont -def create_machine_adherent(dialog): - dialog.msgbox("todo", width=0, height=0) + def modif_machine_blacklist(self, machine, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont -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 modif_machine_alias(self, machine, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont + def modif_machine_exemption(self, machine, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont -def create_club(dialog): - dialog.msgbox("todo", width=0, height=0) + def modif_machine_remarque(self, machine, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont - -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: + @tailCaller + def modif_machine(self, cont, machine=None, tag=None): + if machine is None: + machine = self.select(["machineFixe", "machineWifi", "machineCrans", "borneWifi"], "Recherche d'une machine pour modification", cont=cont) + menu = { + 'Information' : {'text' : "Modifier le nom de machine, l'IP, adresse MAC", "callback":self.modif_machine_information}, + 'Blackliste' : {'text': 'Modifier les blacklist de la machine', 'callback':self.modif_machine_blacklist}, + 'Alias' : {'text': 'Créer ou supprimer un alias de la machine', 'callback':self.modif_machine_alias}, + 'Exemption' : {'text':"Modifier la liste d'exemption d'upload de la machine", 'callback':self.modif_machine_exemption}, + 'Remarques' : {'text':'Ajouter ou supprimer une remarque de la machine', 'callback':self.modif_machine_remarque}, + } + menu_order = ['Information', 'Blackliste', 'Alias', 'Exemption', 'Remarques'] + def box(default_item=None): + return self.dialog.menu( + "Que souhaitez vous modifier ?", + width=0, + height=0, + menu_height=0, + item_help=0, + default_item=str(default_item), + title="Modification de %s" % machine['host'][0], + scrollbar=True, + cancel_label="Retour", + backtitle=u"Vous êtes connecté en tant que %s" % self.conn.current_login, + choices=[(key, menu[key]['text']) for key in menu_order]) (code, tag) = box(tag) - if handle_exit_code(dialog, code): - menu.get(tag, menu[''])['callback'](dialog) + if code in (self.dialog.DIALOG_CANCEL, self.dialog.DIALOG_ESC): + return cont(machine=machine) + elif not tag in menu_order: + return TailCall(self.modif_machine, cont=cont, machine=machine, tag=tag) + else: + return TailCall(menu[tag]['callback'], machine=machine, cont=TailCall(self.modif_machine, cont=cont, machine=machine, tag=tag)) + @tailCaller + def create_machine_adherent(self, cont, adherent=None): + if adherent is None: + adherent = self.select(["adherent"], "Recherche d'un adhérent pour lui ajouter une machine", cont=cont) + self.dialog.msgbox("todo", width=0, height=0) + return cont(proprio=adherent) + + @tailCaller + def delete_machine(self, cont): + machine = self.select(["machineFixe", "machineWifi", "machineCrans", "borneWifi"], "Recherche d'une machine pour supression", cont=cont) + self.dialog.msgbox("todo", width=0, height=0) + return cont + + + @tailCaller + def create_club(self, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont + + + @tailCaller + def delete_club(self, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont + + @tailCaller + def modif_club(self, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont + + @tailCaller + def create_machine_club(self, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont + + @tailCaller + def create_machine_crans(self, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont + + @tailCaller + def create_borne(self, cont): + self.dialog.msgbox("todo", width=0, height=0) + return cont + + @tailCaller + def menu_principal(self, tag=None, machine=None, proprio=None): + menu = { + 'aA' : {'text':"Inscrire un nouvel adhérent", 'callback': self.create_adherent}, + 'mA' : {'text':"Modifier l'inscription d'un adhérent", 'callback': self.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': self.create_machine_adherent}, + 'dA' : {'text':"Détruire un adhérent", 'callback': self.delete_adherent, 'help':"Suppression de l'adhérent ainsi que de ses machines"}, + 'mM' : {'text':"Modifier une machine existante", 'callback': self.modif_machine, 'help':"Changer le nom ou la MAC d'une machine."}, + 'dM' : {'text':"Détruire une machine", 'callback': self.delete_machine}, + 'aC' : {'text':"Inscrire un nouveau club", 'callback': self.create_club}, + 'mC' : {'text':"Modifier un club", 'callback': self.modif_club}, + 'aMC': {'text':"Ajouter une machine à un club", 'callback': self.create_machine_club}, + 'dC' : {'text':"Détruire un club", 'callback': self.delete_club}, + 'aKM': {'text':"Ajouter une machine à l'association", 'callback': self.create_machine_crans}, + 'aKB': {'text':"Ajouter une borne wifi", 'callback': self.create_borne}, + '' : {'text':"---------------------------------------",'callback': None}, + } + ### Les clef qui n'existe pas sont toute renvoyé sur la clef '' + menu_order = ["aA", "mA", "aMA", "dA", "", "mM", "dM", " ", "aC", "mC", "aMC", "dC", " ", "aKM", "aKB"] + + if machine and not proprio: + proprio = machine.proprio() + if machine or proprio: + menu_order = [' '] + menu_order + if machine: + menu_machine = { + 'mMc' : { + 'text':"Modifier la machine %s" % machine['host'][0], + 'callback': TailCall(self.modif_machine, machine=machine), + 'help':"Changer le nom ou la MAC d'une machine." + }, + } + menu_machine_order = ['mMc'] + menu.update(menu_machine) + menu_order = menu_machine_order + menu_order + if proprio: + menu_proprio = { + 'mAc' : { + 'text':"Modifier l'inscription de %s" % proprio.get("cn", proprio["nom"])[0], + 'callback': TailCall(self.modif_adherent, adherent=proprio) + }, + 'aMc' : { + 'text':"Ajouter une machine à %s" % proprio.get("cn", proprio["nom"])[0], + 'callback': TailCall(self.create_machine_adherent, adherent=proprio) + }, + } + menu_proprio_order = ['mAc', 'aMc'] + menu.update(menu_proprio) + menu_order = menu_proprio_order + menu_order + def box(default_item=None): + return self.dialog.menu( + "Que souhaitez vous faire ?", + width=0, + height=0, + menu_height=0, + 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" % self.conn.current_login, + choices=[(key, menu.get(key, menu[''])['text'], menu.get(key, menu['']).get('help', "")) for key in menu_order]) + + (code, tag) = box(tag) + callback = menu.get(tag, menu[''])['callback'] + if handle_exit_code(self.dialog, code) and callback: + return TailCall(callback, cont=TailCall(self.menu_principal, tag, machine=machine, proprio=proprio)) + else: + return TailCall(self.menu_principal, tag, proprio=proprio, machine=machine) 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) + GestCrans() os.system('clear')