zephir.backend.users_rpc

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

# Source Code for Module zephir.backend.users_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  # users_rpc.py
      9  #
     10  # fonctions xmlrpc pour la gestion des utilisateurs et permissions
     11  #
     12  ###########################################################################
     13  """module de gestion des utilisateurs de l'application
     14  """
     15  from zephir.backend import config
     16  from zephir.backend.config import u, log
     17  from zephir.backend.db_utils import *
     18  from zephir.backend.entid import IdPoolManager
     19  from zephir.backend.lib_backend import serveur_pool
     20  from zephir.backend.schedule import TaskScheduler
     21  from zephir.backend.dictpool import init_dictpool
     22  from zephir.backend.xmlrpceole import XMLRPCEole as XMLRPC
     23
     24  import sys,base64,ldap,os
     25  import traceback
     26  import apt_pkg
     27
     28 -class RPCUsers(XMLRPC):
     29      """serveur XMLRPC zephir pour la gestion des utilisateurs de l'application
     30      """
     31
     32 -    def __init__(self):
     33          self.dbpool = db_connect()
     34          self.dbpool.noisy = 0
     35          # pool de représentation des serveurs et dictionnaires Creole
     36          self.s_pool = serveur_pool()
     37          self.dictpool = init_dictpool(self.s_pool)
     38          # planificateur de tâche (non fonctionnel)
     39          # self.scheduler = TaskScheduler(self.s_pool)
     40          self.maj_checker = None
     41          XMLRPC.__init__(self)
     42          self.reload_perms=0
     43
     44 -    def xmlrpc_get_stats(self, cred_user):
     45          """renvoie des statistiques générales sur les serveurs"""
     46          return 1, u(self.s_pool.get_stats())
     47
     48 -    def xmlrpc_get_rights(self,cred_user):
     49          """liste des groupes de droits"""
     50          # on précharge les groupes de droits
     51          query = """select * from groupes_droits"""
     52          return self.dbpool.runQuery(query).addCallbacks(self._load_rights,db_client_failed)
     53
     54 -    def _load_rights(self,data):
     55          """formattage des groupes de droits
     56          """
     57          # on crée en mémoire un dictionnaire des groupes de droits
     58          droits=[]
     59          for groupe in data:
     60              # dictionnaire du type : {id:[droits,libelle]}
     61              droits.append([groupe[0],groupe[1],eval(groupe[2])])
     62          return 1, u(droits)
     63
     64 -    def xmlrpc_get_permissions(self,cred_user,username):
     65          """liste des permissions de l'application pour un utilisateur précis"""
     66          # on récupère la liste des groupes de permissions pour l'utilisateur
     67          query = """select login, droits from users where login = %s"""
     68          return self.dbpool.runQuery(query, (username,)).addCallbacks(self._get_permissions,db_client_failed)
     69
     70 -    def _get_permissions(self,data):
     71          try:
     72              # si l'utilisateur existe, on récupère ses groupes de droits
     73              username = data[0][0]
     74              groupes = eval(data[0][1])
     75          except:
     76              # aucun groupe autorisé pour cet utilisateur
     77              return 1, []
     78
     79          return 1, u(groupes)
     80
     81 -    def xmlrpc_save_permissions(self,cred_user,username,user_auths):
     82          """sauvegarde les autorisations de l'utilisateur"""
     83
     84          # on regarde si l'utilisateur existe dans la base de données
     85          query = """select login,nom,prenom,mail from users where login = %s"""
     86          return self.dbpool.runQuery(query, (username,)).addCallbacks(self._save_permissions,db_client_failed,callbackArgs=[username,user_auths])
     87
     88 -    def _save_permissions(self,data,username,user_auths):
     89          # on tente de récupèrer certaines valeurs dans l'annuaire (mail, nom, prenom)
     90          if data!=[]:
     91              nom=data[0][1]
     92              prenom=data[0][2]
     93              mail=data[0][3]
     94          else:
     95              nom=""
     96              prenom=""
     97              mail=""
     98          try:
     99              l=ldap.open(config.ADRESSE_LDAP)
    100              if config.LDAP_TLS == "oui":
    101                  l.start_tls_s()
    102              # on récupère le dn complet de l'utilisateur
    103              result=l.search_s(config.BASE_LDAP, ldap.SCOPE_SUBTREE, "(uid="+username+")")
    104              res_ldap = result[0][1]
    105              l.unbind()
    106              if nom == "":
    107                  try:
    108                      nom=res_ldap['sn'][0]
    109                  except KeyError:
    110                      pass
    111              if prenom == "":
    112                  try:
    113                      prenom=res_ldap['givenName'][0]
    114                  except KeyError:
    115                      pass
    116              if mail == "":
    117                  try:
    118                      mail=res_ldap['mail'][0]
    119                  except KeyError:
    120                      pass
    121          except:
    122              pass
    123          if data != []:
    124              # si utilisateur existant, on le met à jour
    125              query = """update users set droits=%s,nom=%s,prenom=%s,mail=%s where login=%s"""
    126              params = (str(user_auths), nom, prenom, mail, username)
    127          else:
    128              # sinon on le crée avec des valeurs par défaut
    129              query = """insert into users (login,mail_actif,sms_actif,droits,nom,prenom,mail)  \
    130                      values (%s,%s,%s,%s,%s,%s,%s)"""
    131              params = (username, 0, 0, str(user_auths), nom, prenom, mail)
    132
    133          return self.dbpool.runOperation(query, params).addCallbacks(lambda x : [1,'ok'],db_client_failed)
    134
    135 -    def xmlrpc_get_restrictions(self, cred_user, login, type_res=None):
    136          """ajoute des restrictions sur les serveurs accessibles à un utilisateur
    137          """
    138          try:
    139              res = self.s_pool.get_restrictions(login, type_res)
    140          except KeyError:
    141              return 0, u("utilisateur ou type de contrainte non valides")
    142          return 1, u(res)
    143
    144 -    def xmlrpc_add_restriction(self, cred_user, login, type_res, id_res):
    145          """ajoute des restrictions sur les serveurs accessibles à un utilisateur
    146          """
    147          # on regarde si l'utilisateur existe
    148          query = """select login,nom,prenom,mail from users where login = %s"""
    149          return self.dbpool.runQuery(query, (login,)).addCallbacks(self._add_restriction,db_client_failed,callbackArgs=[login, type_res, id_res])
    150
    151 -    def _add_restriction(self,data,login,type_res,id_res):
    152          # on tente de récupèrer certaines valeurs dans l'annuaire (mail, nom, prenom)
    153          if data!=[]:
    154              nom=data[0][1]
    155              prenom=data[0][2]
    156              mail=data[0][3]
    157          else:
    158              nom=""
    159              prenom=""
    160              mail=""
    161          try:
    162              l=ldap.open(config.ADRESSE_LDAP)
    163              if config.LDAP_TLS == "oui":
    164                  l.start_tls_s()
    165              # on récupère le dn complet de l'utilisateur
    166              result=l.search_s(config.BASE_LDAP, ldap.SCOPE_SUBTREE, "(uid="+login+")")
    167              res_ldap = result[0][1]
    168              l.unbind()
    169              if nom == "":
    170                  try:
    171                      nom=res_ldap['sn'][0]
    172                  except KeyError:
    173                      pass
    174              if prenom == "":
    175                  try:
    176                      prenom=res_ldap['givenName'][0]
    177                  except KeyError:
    178                      pass
    179              if mail == "":
    180                  try:
    181                      mail=res_ldap['mail'][0]
    182                  except KeyError:
    183                      pass
    184          except:
    185              pass
    186          if data == []:
    187              user_auths = []
    188              # si l'utilisateur n'existe pas encore, on le crée avec des valeurs par défaut
    189              query = """insert into users (login,mail_actif,sms_actif,droits,nom,prenom,mail) \
    190              values (%s,%s,%s,%s,%s,%s,%s)"""
    191              params = (login, 0, 0, user_auths, nom, prenom, mail)
    192              return self.dbpool.runOperation(query, params).addCallbacks(self._add_restriction2,db_client_failed,callbackArgs=[login, type_res, id_res])
    193          else:
    194              return self._add_restriction2(None, login, type_res, id_res)
    195
    196 -    def _add_restriction2(self,retour,login,type_res,id_res):
    197          # ajout réel de la restriction demandée
    198          if self.s_pool.add_restriction(login, type_res, id_res):
    199              return 1, "ok"
    200          else:
    201              return 0, u("erreur lors de l'ajout de la contrainte")
    202
    203 -    def xmlrpc_del_restriction(self, cred_user, login, type_res, id_res):
    204          """ajoute des restrictions sur les serveurs accessibles à un utilisateur
    205          """
    206          if self.s_pool.del_restriction(login, type_res, id_res):
    207              return 1, "ok"
    208          else:
    209              return 0, u("erreur, contrainte non retrouvée")
    210
    211 -    def xmlrpc_get_allowed_servers(self, cred_user, login):
    212          """renvoie la liste des serveurs accessibles pour un utilisateur (login)
    213          """
    214          try:
    215              return 1, u(self.s_pool.get_allowed_servers(login))
    216          except Exception, e:
    217              return 0, u("Erreur lors de la recherche des serveurs accessibles pour %s" % login)
    218
    219 -    def xmlrpc_user_group(self,cred_user,username,groupes):
    220          """met à jour la liste des groupes surveillés par l'utilisateur"""
    221          query = """update users set groupes = %s where login = %s"""
    222          params = (str(groupes),username)
    223          return self.dbpool.runOperation(query, params).addCallbacks(lambda x : [1,'ok'],db_client_failed)
    224
    225 -    def xmlrpc_get_user(self,cred_user,username):
    226          """renvoie les informations d'un utilisateur
    227          """
    228          query = """select login,mail,nom,prenom,sms,mail_actif,sms_actif,droits,groupes,cle from users where login = %s"""
    229          return self.dbpool.runQuery(query, (username,)).addCallbacks(self._get_user,db_client_failed)
    230
    231 -    def xmlrpc_list_users(self,cred_user):
    232          """retourne la liste des utilisateurs"""
    233          query = """select login from users order by login asc"""
    234          return self.dbpool.runQuery(query).addCallbacks(self._list_users,db_client_failed)
    235
    236 -    def _list_users(self,data):
    237          """formate la sortie de la base de données"""
    238          logins=[]
    239          for user in data:
    240              logins.append(user[0])
    241          return 1,u(logins)
    242
    243 -    def xmlrpc_del_user(self,cred_user,login):
    244          """suppression d'un utilisateur"""
    245          if login:
    246              # on interdit la suppression si des variantes appartiennent à l'utilisateur
    247              query = """select libelle from variantes where owner=%s"""
    248              return self.dbpool.runQuery(query, (login,)).addCallbacks(self._del_user,db_client_failed,callbackArgs=[cred_user, login])
    249          else:
    250              return 0,u("""donnez un identifiant""")
    251
    252 -    def _del_user(self, data, cred_user, login):
    253          """suppression de l'utilisateur dans la base de données
    254          """
    255          query = """delete from restrictions where login=%s"""
    256          self.dbpool.runOperation(query, (login,))
    257          query = """delete from serveur_auth where login=%s"""
    258          self.dbpool.runOperation(query, (login,))
    259          query = """delete from users where login=%s"""
    260          return self.dbpool.runOperation(query, (login,)).addCallbacks(self._update_variantes, db_client_failed, callbackArgs=[data, cred_user, login])
    261
    262 -    def _update_variantes(self, res_query, var_data, cred_user, login):
    263          """réassignation des variantes si besoin
    264          """
    265          if len(var_data) > 0:
    266              # des variantes appartiennent à cet utilisateur, on les attribue à l'utilisateur courant
    267              log.msg("""Utilisateur %s supprimé, réattribution des variantes suivantes à %s : %s""" % (login, cred_user, ", ".join([lib[0] for lib in var_data])))
    268              query = """update variantes set owner=%s where owner=%s"""
    269              return self.dbpool.runOperation(query, (cred_user, login)).addCallbacks(lambda x : [1,'OK'], db_client_failed)
    270          return 1, "OK"
    271
    272 -    def xmlrpc_edit_user(self,cred_user,username,nom,prenom,mail,sms,mail_actif,sms_actif):
    273          """édite les informations d'un utilisateur
    274          """
    275          query = """select * from users where login=%s"""
    276          return self.dbpool.runQuery(query, (username,)).addCallbacks(self._edit_user,db_client_failed,callbackArgs=[username,nom,prenom,mail,sms,mail_actif,sms_actif])
    277
    278 -    def _edit_user(self,data,username,nom,prenom,mail,sms,mail_actif,sms_actif):
    279          """
    280          """
    281          if data == []:
    282              # utilisateur inexistant
    283              query = """insert into users (login, nom, prenom, mail, sms, mail_actif, sms_actif, droits, \
    284                      groupes, cle) values (%s,%s,%s,%s,%s,%s,%s,'','','')"""
    285              params = (username, nom, prenom, mail, sms, int(mail_actif), int(sms_actif))
    286          else:
    287              query = """update users set nom=%s, prenom=%s, mail=%s, sms=%s, mail_actif=%s, sms_actif=%s where login=%s"""
    288              params = (nom, prenom, mail, sms, int(mail_actif), int(sms_actif), username)
    289
    290          return self.dbpool.runOperation(query, params).addCallbacks(lambda x : [1,'ok'],db_client_failed)
    291
    292 -    def _get_user(self,data):
    293          """formate la sortie de la base de données"""
    294          user=[]
    295          if data != []:
    296              for field in data[0]:
    297                  if field in [None, 'None']:
    298                      user.append("")
    299                  else:
    300                      user.append(field)
    301
    302              if user[7] == "":
    303                  user[7] = "[]"
    304              if user[8] == "":
    305                  user[8] = "[]"
    306              if user[9] != "":
    307                  user[9] = 1
    308              else:
    309                  user[9] = 0
    310
    311              return 1, u([user[0],user[1],user[2],user[3],user[4],int(user[5]),int(user[6]),eval(user[7]),eval(user[8]),user[9]])
    312          else:
    313              return 1, []
    314
    315 -    def xmlrpc_save_key(self,cred_user,cle):
    316          """sauvegarde la cle ssh de l'utilisateur"""
    317          query = """update users set cle=%s where login=%s"""
    318          params = (cle, cred_user)
    319          return self.dbpool.runOperation(query, params).addCallbacks(lambda x : [1,'ok'], db_client_failed)
    320
    321 -    def xmlrpc_update_client(self,cred_user,name,content=""):
    322          """fonction de mise à jour du client disponible sur zephir"""
    323          # on supprime l'ancienne version du fichier.
    324          try:
    325              rpm_dir = os.path.abspath(config.PATH_ZEPHIR)+"/sites/client/"
    326              if not os.path.isdir(rpm_dir):
    327                  os.makedirs(rpm_dir)
    328              b_name = os.path.basename(name)
    329              rpms = os.listdir(rpm_dir)
    330              for rpm in rpms:
    331                  # on enlève les rpm avec même version (majeure+mineure)
    332                  if rpm.startswith(b_name[:b_name.rindex('-')]) and rpm.endswith(os.path.splitext(b_name)[1]):
    333                      os.unlink(rpm_dir+rpm)
    334              # on écrit le nouveau paquet
    335              # si pas de contenu, on essaye de télécharger la version officielle du dépôt (EoleNG seulement)
    336              if content == "":
    337                  import urllib
    338                  arch_url = ''
    339                  version = b_name.replace('zephir-client', '')[1:4]
    340                  if version not in ('2.0', '2.1'):
    341                      arch_url = 'all/'
    342                  f_name, message = urllib.urlretrieve('http://' + config.CLIENT_UPDATE_HOST + \
    343                          config.CLIENT_NG_URL % (version, arch_url) + b_name, rpm_dir + b_name)
    344              else:
    345                  content = base64.decodestring(content)
    346                  fic_rpm=file(rpm_dir + b_name,'w')
    347                  fic_rpm.write(content)
    348                  fic_rpm.close()
    349              return 1, "OK"
    350          except Exception, e:
    351              traceback.print_exc()
    352              return 0, u("Erreur de mise a jour du client")
    353
    354 -    def xmlrpc_remove_client(self,cred_user,name):
    355          """suppression d'un client disponible sur zephir"""
    356          try:
    357              rpm_dir = os.path.abspath(config.PATH_ZEPHIR)+"/sites/client/"
    358              rpm = os.path.join(rpm_dir,name)
    359              if not os.path.isfile(rpm):
    360                  return 0, u("Fichier non trouvé %s" % name)
    361              os.unlink(rpm)
    362              return 1, "OK"
    363          except Exception, e:
    364              return 0, u("Erreur de suppression du fichier")
    365
    366 -    def xmlrpc_maj_client(self,cred_user,version):
    367          """fonction de vérification de la version du client"""
    368          # hack pour éviter les problèmes avec une version du client qui peut renvoyer
    369          # 2 lignes (Version et Python-Version, ref #3658)
    370          version = version.split('\n')[0]
    371          # on regarde la version actuelle du client sur zephir
    372          vers_majmin=version[:version.rindex('-')]
    373          try:
    374              version_locale = ""
    375              if os.path.isdir(os.path.abspath(config.PATH_ZEPHIR)+"/sites/client"):
    376                  rpms=os.listdir(os.path.abspath(config.PATH_ZEPHIR)+"/sites/client")
    377                  for rpm in rpms:
    378                      # on regarde si on a un paquet correspondant (mm version globale du client)
    379                      if rpm.startswith(vers_majmin):
    380                          version_locale=rpm
    381                          break
    382              if version_locale == "":
    383                  # on a pas trouvé de rpm de mise à jour
    384                  return 1,"OK"
    385          except Exception,e:
    386              return 0,u('erreur lors de la lecture de la version sur zephir : %s' % str(e))
    387          # on compare avec la version envoyée par le client
    388          vers_loc = version_locale.replace(vers_majmin,"")
    389          vers_dist = version.replace(vers_majmin,"")
    390          if version.split('zephir-client')[1][1:].startswith('2'):
    391              # cas de eole2 : revision avec X ou Xeol ?
    392              vers_loc = vers_loc[1:vers_loc.index('_')].replace('eole','')
    393              vers_dist = vers_dist[1:].replace('eole','')
    394          else:
    395              vers_loc = vers_loc[1:vers_loc.index('eol')]
    396              vers_dist = vers_dist[1:vers_dist.index('eol')]
    397          # comparaison de la révision
    398          maj=0
    399          apt_pkg.InitSystem()
    400          if apt_pkg.VersionCompare(vers_loc, vers_dist) > 0:
    401              maj=1
    402          if maj == 1:
    403              return 1,u(version_locale.strip())
    404          else:
    405              return 1,"OK"
    406
    407 -    def xmlrpc_list_client(self,cred_user):
    408          """liste les clients disponibles sur zephir"""
    409          try:
    410              rpms = []
    411              rpm_dir = os.path.abspath(config.PATH_ZEPHIR)+"/sites/client/"
    412              if os.path.isdir(rpm_dir):
    413                  for rpm in os.listdir(rpm_dir):
    414                      if rpm.startswith('zephir-client'):
    415                          rpms.append(rpm)
    416              return 1, u(rpms)
    417          except Exception, e:
    418              return 0, u("Erreur de lecture du répertoire")
    419