zephir.backend.etabs_rpc

Package zephir :: Package backend :: Module etabs_rpc |
[frames] | no frames]

# Source Code for Module zephir.backend.etabs_rpc

      1  # -*- coding: UTF-8 -*-
      2  ###########################################################################
      3  # Eole NG - 2007
      4  # Copyright Pole de Competence Eole  (Ministere Education - Academie Dijon)
      5  # Licence CeCill  cf /root/LicenceEole.txt
      6  # eole@ac-dijon.fr
      7  #
      8  # etabs_rpc.py
      9  #
     10  # fonctions xmlrpc pour la gestion des etablissement sous Zephir
     11  #
     12  ###########################################################################
     13  from zephir.backend import config
     14  from zephir.backend.config import u, log
     15  from zephir.backend.db_utils import *
     16  from zephir.backend.xmlrpceole import XMLRPCEole as XMLRPC
     17
     18  # import relatifs aux tables
     19  import psycopg2 as PgSQL
     20
     21  import sys,os,shutil
     22
     23 -class RPCEtabs(XMLRPC):
     24      """serveur XMLRPC zephir pour la gestion des établissements
     25      """
     26
     27 -    def __init__(self,parent):
     28          # connexion à la base de données zephir
     29          self.dbpool = db_connect()
     30          self.dbpool.noisy = 0
     31          XMLRPC.__init__(self)
     32          self.parent = parent
     33
     34
     35 -    def _got_etabs(self, etabs, cred_user):
     36          """formate la sortie de la table etablissements
     37          """
     38          l=[]
     39          for etab in etabs:
     40              try:
     41                  self.parent.s_pool.check_etab_credential(cred_user, etab[0])
     42              except:
     43                  continue
     44              l.append({'rne':etab[0],
     45                      'libelle':etab[1],
     46                      'adresse':etab[2],
     47                      'ville':etab[9],
     48                      'cp':etab[10],
     49                      'tel':etab[3],
     50                      'fax':etab[4],
     51                      'mail':etab[5],
     52                      'responsable':etab[6],
     53                      'remarques':etab[7],
     54                      'type':etab[8]
     55                      })
     56          return 1,u(l)
     57
     58 -    def _got_libelle_ville_etabs(self,etabs):
     59          """formate la sortie de la table etablissements
     60          """
     61          l1=[]
     62          l2=[]
     63          for etab in etabs:
     64              l1.append(etab[0])
     65              if etab[1] not in l2:
     66                  l2.append(etab[1])
     67          return 1,u([l1,l2])
     68
     69 -    def _got_types(self,types_etab):
     70          """formate la sortie des types d'établissement
     71          """
     72          d={}
     73          for t in types_etab:
     74              d[str(t[0])]=u(t[1])
     75          return 1,[d]
     76
     77 -    def xmlrpc_get_etab(self,cred_user, rne=None):
     78          """Récupération des données d'un établissement (ou de tous)
     79          """
     80          if rne:
     81              query = """select * from etablissements where rne ilike %s"""
     82              return self.dbpool.runQuery(query, (rne,)).addCallbacks(self._got_etabs,db_client_failed,callbackArgs=[cred_user])
     83          else:
     84              # si pas de rne demandé, on renvoie tous les établissements connus
     85              query = """select * from etablissements"""
     86              return self.dbpool.runQuery(query).addCallbacks(self._got_etabs,db_client_failed,callbackArgs=[cred_user])
     87
     88 -    def xmlrpc_get_libelle_etab(self,cred_user):
     89          """Récupération des données d'un établissement (ou de tous)
     90          """
     91          query = """select libelle, ville from etablissements order by ville"""
     92          return self.dbpool.runQuery(query).addCallbacks(self._got_libelle_ville_etabs,db_client_failed)
     93
     94 -    def _load_types(self,cx):
     95          """lit les types établissement et renvoie un dictionnaire
     96          """
     97          cursor=cx.cursor()
     98          # on lit la base
     99          cursor.execute("""select id,libelle from types_etab""")
    100          result = cursor.fetchall()
    101          cursor.close()
    102          num_types = {}
    103          # correspondance libelle -> n°
    104          for row in result:
    105              num_types[row[1].upper()]=row[0]
    106
    107          return num_types
    108
    109
    110 -    def xmlrpc_import_etab(self,cred_user,data):
    111          """importe des établissements depuis un fichier csv"""
    112          # recherche des types d'établissement
    113          # from nomenclature import nomenclature_ramses
    114          # correspondances des types etab
    115          query = """select rne from etablissements"""
    116          return self.dbpool.runQuery(query).addCallbacks(self._import_etab,db_client_failed,callbackArgs=[cred_user,data])
    117
    118 -    def _import_etab(self,liste_rne,cred_user,data):
    119          # mise à plat de la liste des rnes existants
    120          existants = [rne[0] for rne in liste_rne]
    121          nouveaux = []
    122          cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD)
    123          num_types = self._load_types(cx)
    124          cx.close()
    125          errors=[]
    126          # on commence par vérifier les types d'établissement
    127          missing=[]
    128          for etab in data:
    129              libelle = etab[3]
    130              if libelle.strip() == "":
    131                  libelle = "INDEFINI"
    132                  etab[3] = libelle
    133              if libelle.upper() not in num_types.keys():
    134                  if libelle.upper() not in missing:
    135                      missing.append(libelle.upper())
    136
    137          if missing != []:
    138              dict_miss = []
    139              for miss in missing:
    140                  dict_miss.append({'miss':miss})
    141              cx = PgSQL.connect(database=config.DB_NAME,user=config.DB_USER,password=config.DB_PASSWD)
    142              cursor=cx.cursor()
    143              # on ajoute les types non existants
    144              cursor.executemany("insert into types_etab (libelle) values (%(miss)s)", dict_miss)
    145              cursor.close()
    146              cx.commit()
    147              # on relit la base
    148              num_types = self._load_types(cx)
    149              cx.close()
    150
    151          # on ajoute/met à jour les etablissements
    152          for etab in data:
    153              rne = etab[0]
    154              # type_etab = nomenclature_ramses[etab[1] + '_' + etab[2]]
    155              libelle = etab[3] + " " + etab[4]
    156              cp = etab[5]
    157              adresse = " "
    158              ville = etab[6]
    159              telephone = etab[9]
    160              fax = etab[8]
    161              mail = etab[7]
    162              responsable = "inconnu"
    163              remarques = ""
    164              # on récupère son n° de type
    165              if num_types.has_key(etab[3].upper()):
    166                  type_etab = num_types[etab[3].upper()]
    167                  if rne in existants:
    168                      # mise à jour d'un établissement existant
    169                      update_infos = {'libelle':libelle,
    170                                       'adresse':adresse,
    171                                       'ville':ville,
    172                                       'cp':cp,
    173                                       'tel':telephone,
    174                                       'fax':fax,
    175                                       'mail':mail,
    176                                       'responsable':responsable,
    177                                       'remarques':remarques,
    178                                       'type':type_etab}
    179                      res = self.xmlrpc_edit_etab(cred_user, rne, update_infos)
    180                      # on le supprime de la liste des rnes pour conserver ceux
    181                      # qui ne sont plus dans le fichier
    182                      existants.remove(rne)
    183                  else:
    184                      try:
    185                          res = self.xmlrpc_add_etab(cred_user,rne,libelle,adresse,ville,cp,telephone,fax,mail,responsable,remarques,type_etab)
    186                          nouveaux.append([rne, libelle])
    187                      except:
    188                          log.msg("Erreur à la création de l'établissement %s" % rne)
    189                          traceback.print_exc()
    190          if errors != []:
    191              return 0,u('erreur : %s' % errors)
    192          else:
    193              return 1, u((existants, nouveaux))
    194
    195
    196 -    def xmlrpc_add_etab(self,cred_user,rne,libelle,adresse,ville,cp,telephone,fax,mail,responsable,remarques,type_etab):
    197          """ajoute un établissement"""
    198          # on vérifie que les données obligatoires sont remplies
    199          if (rne and libelle and type_etab):
    200              # objet etab
    201              query = """insert into etablissements values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""
    202              params = (rne, libelle, adresse, telephone, fax, mail, responsable, remarques, type_etab, ville.upper(), cp)
    203              # on effectue l'insertion (l'existence est à tester dans l'application cliente)
    204              return self.dbpool.runOperation(query, params).addCallbacks(self._add_etab, db_client_failed,callbackArgs=[rne, cred_user])
    205          else:
    206              # des attributs manquent
    207              return 0,u('arguments manquants')
    208
    209 -    def _add_etab(self,resultat, rne, cred_user):
    210          """met en place l'arborescence zephir de l'établissement """
    211          # si nécessaire, on donne les droits d'accès à l'établissement pour la personne qui l'a créé
    212          try:
    213              self.parent.s_pool.check_etab_credential(cred_user, rne)
    214          except:
    215              log.msg("acces non permis , ajout d'une restriction")
    216              self.parent.s_pool.add_restriction(cred_user,'rne',rne)
    217          # création de l'arborescence de l'établissement
    218          etab_dir = os.path.abspath(config.PATH_ZEPHIR)+'/conf/'+rne
    219          try:
    220              os.makedirs(etab_dir)
    221          except:
    222              return 0,u("erreur de création du répertoire de l'établissement")
    223          else:
    224              return 1,u(rne)
    225
    226 -    def xmlrpc_del_etab(self,cred_user,rne):
    227          """supprime un établissement"""
    228          self.parent.s_pool.check_etab_credential(cred_user, rne)
    229          # on vérifie qu'il ne reste pas de serveurs
    230          query = """select id from serveurs where rne=%s"""
    231          return self.dbpool.runQuery(query, (rne,)).addCallbacks(self._del_etab, db_client_failed,callbackArgs=[rne])
    232
    233 -    def _del_etab(self,data,rne):
    234          """supprime l'établissement dans la base de données"""
    235          if len(data) > 0:
    236              # on n'autorise pas la supression si il reste des serveurs
    237              return 0, u("Suppression impossible, il existe des serveurs rattachés à cet établissement")
    238
    239          # on supprime la configuration uucp de tous les serveurs correspondants
    240          try:
    241              file_conf = open('/etc/uucp/config_zephir','r')
    242              conf_uucp = file_conf.readlines()
    243              file_conf.close()
    244          except:
    245              return 0, u("""erreur de lecture de /etc/uucp/config_zephir""")
    246          try:
    247              for sysfile in os.listdir('/etc/uucp/serveurs'):
    248                  if sysfile.startswith(rne+'-'):
    249                      # on supprime le fichier de définition  du serveur
    250                      os.unlink('/etc/uucp/serveurs'+os.sep+sysfile)
    251                      # on supprime la référence à ce fichier dans /etc/uucp/config
    252                      conf_uucp.remove('sysfile /etc/uucp/serveurs/'+sysfile+'\n')
    253          except:
    254              # si pas encore de serveurs -> pas de répertoire
    255              pass
    256
    257          # supression des logins/mots de passes correpondants
    258          try:
    259              # lecture des infos de login
    260              file_pwd = open('/etc/uucp/passwd_zephir','r')
    261              pwd_uucp = file_pwd.readlines()
    262              file_pwd.close()
    263              # supression des lignes pour cet étab
    264              for line in pwd_uucp:
    265                  if line.startswith(rne+'-'):
    266                      pwd_uucp.remove(line)
    267              # sauvegarde de la liste
    268              file_pwd = open('/etc/uucp/passwd_zephir','w')
    269              file_pwd.writelines(pwd_uucp)
    270              file_pwd.close()
    271          except:
    272              return 0, u("""erreur de mise à jour du fichier des mots de passe""")
    273
    274          # mise à jour du fichier /etc/uucp/config_zephir
    275          try:
    276              file_conf = open('/etc/uucp/config_zephir','w')
    277              file_conf.writelines(conf_uucp)
    278              file_conf.close()
    279          except:
    280              return 0, u("""erreur d'écriture dans /etc/uucp/config_zephir""")
    281
    282          query = """delete from etablissements where rne=%s"""
    283          return self.dbpool.runOperation(query, (rne,)).addCallbacks(self._del_etab2, db_client_failed,callbackArgs=[rne])
    284
    285 -    def _del_etab2(self,resultat,rne):
    286          """supprime l'arborescence de l'établissement"""
    287          etab_dir = os.path.abspath(config.PATH_ZEPHIR)+'/conf/'+rne
    288          # supression de ce répertoire ?
    289          try:
    290              shutil.rmtree(etab_dir)
    291          except:
    292              return 0,u("""erreur de supression du répertoire de l'établissement""")
    293          else:
    294              log.msg("établissement %s supprimé" % rne)
    295              return 1,u('ok')
    296
    297      # modification d'un etablissement
    298 -    def xmlrpc_edit_etab(self,cred_user,rne,dico_modifs):
    299          """modification d'un établissement
    300          cette fonction prend en compte un dictionnaire qui indique les
    301          champs à modifier et leur nouvelle valeur. l'application cliente
    302          doit s'assurer que ces champs existent dans la base
    303          ex: zephir.etabs.edit_etab('R620001X',{'libelle':'bla bla','type':1})"""
    304          self.parent.s_pool.check_etab_credential(cred_user, rne)
    305          # on vérifie que l'identifiant n'est pas modifié
    306          if dico_modifs == {}:
    307              return 1,u('ok')
    308          if 'rne' in dico_modifs.keys():
    309              return 0,u('modification du rne interdit')
    310          # construction de la requête SQL de modification
    311          query=["update etablissements set "]
    312          params = []
    313          for cle in dico_modifs.keys():
    314              query.append(str(cle))
    315              query.append("=%s")
    316              params.append(str(dico_modifs[cle]))
    317              query.append(", ")
    318          string_fin=""" where rne=%s"""
    319          params.append(rne)
    320          query="".join(query)[:-2]
    321          query += string_fin
    322          return self.dbpool.runOperation(query, params).addCallbacks(lambda x:(1,'ok'), db_client_failed)
    323
    324 -    def xmlrpc_rech_etab(self,cred_user,d):
    325          """Recherche multi-critères d'un établissement
    326          select * from etablissements where nom_champ like '%%libelle%%'
    327          { rne, libelle, cp, type, ville }
    328          """
    329          # construction de la requête SQL de recherche
    330          query=["select * from etablissements where "]
    331          params = []
    332          for nom_champ in d.keys():
    333              if d[nom_champ] != "":
    334                  if nom_champ == 'type':
    335                      query.append(str(nom_champ) + " = %s and ")
    336                      params.append(int(d[nom_champ]))
    337                  else:
    338                      query.append(str(nom_champ) + " ilike %s and ")
    339                      params.append(str(d[nom_champ]))
    340
    341          query = "".join(query)[:-4]
    342          query += "order by RNE"
    343          return self.dbpool.runQuery(query, params).addCallbacks(self._got_etabs, db_client_failed, callbackArgs=[cred_user])
    344
    345 -    def xmlrpc_get_types(self,cred_user):
    346          """Récupération des types d'établissement existants
    347          """
    348          query = """select * from types_etab order by libelle"""
    349          return self.dbpool.runQuery(query).addCallbacks(self._got_types,db_client_failed)
    350
    351
    352 -    def xmlrpc_add_type(self,cred_user,libelle):
    353          """ajoute un type d'établissement dans la base de données"""
    354          # on vérifie que les données obligatoires sont remplies
    355          if (libelle):
    356              query = """insert into types_etab (libelle) values (%s)"""
    357              # on effectue l'insertion (l'existence est à tester dans l'application cliente)
    358              return self.dbpool.runOperation(query, (libelle,)).addCallbacks(lambda x:(1,'ok'), db_client_failed)
    359          else:
    360              # des attributs manquent
    361              return 0,u('libellé manquant')
    362
    363 -    def xmlrpc_del_type(self,cred_user,id_type):
    364          """ajoute un type d'établissement dans la base de données"""
    365          # on vérifie que les données obligatoires sont remplies
    366          if (id_type):
    367              query = """delete from types_etab where id=%s"""
    368              # on effectue l'insertion (l'existence est à tester dans l'application cliente)
    369              return self.dbpool.runOperation(query, (int(id_type),)).addCallbacks(lambda x:(1,'ok'), db_client_failed)
    370          else:
    371              # des attributs manquent
    372              return 0,u('identifiant manquant')
    373