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