Proyecto

General

Perfil

« Anterior | Siguiente » 

Revisión 245

Añadido por jredrejo hace más de 13 años

creada rama de tags a partir de la versión estable 0.6 de controlies

Ver diferencias:

controlies/tags/0.6/debian/changelog
controlies (0.6-1) unstable; urgency=low
* Validacion de los logins de Rayuela para Rayuela2Ldap
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Tue, 25 Oct 2011 10:44:10 +0200
controlies (0.5-2) unstable; urgency=low
* Creación del directorio personal en el NFS al crear un nuevo usuario
* Corregido un bug en la paginación
* Corregido un bug en la modificación de la MAC en el nodo DHCP Config
-- Manuel Mora Gordillo <manuito@gmail.com> Thu, 13 Oct 2011 16:30:00 +0200
controlies (0.5-1) unstable; urgency=low
* Añade LTSP Servers y Workstations a la rama ARPA
* Ya no gestiona los equipos que cuelgan directamente de la rama Hosts
* Selector de IPs en el formulario de LTSP Servers y Workstations
* Añadida funcionalidad de búsqueda en LTSP Servers, Workstations y Thinclients
* Corregidos algunos bugs debidos a las distintas estructuras de distintos LDAPs
-- Manuel Mora Gordillo <manuito@gmail.com> Thu, 13 Oct 2011 16:30:00 +0200
controlies (0.4-9) unstable; urgency=low
* Añadida la funcionalidad de LTSP Servers, Workstations y Thinclients
-- Manuel Mora Gordillo <manuito@gmail.com> Wed, 5 Oct 2011 19:30:00 +0200
controlies (0.4-8) unstable; urgency=low
* Se elimininan de los nombres las vocales con diéresis y las comas
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Tue, 20 Sep 2011 14:41:47 +0200
controlies (0.4-7) unstable; urgency=low
* Corregido bug que podía producir repetición de algún login
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Fri, 16 Sep 2011 12:38:09 +0200
controlies (0.4-6) unstable; urgency=low
* Eliminados timeout de apache para permitir el proceso de ficheros con
muchos usuarios (probado con hasta 900 usuarios, tardando 5 minutos)
* Contempla que haya grupos con nombre en blanco
* Reinicia apache2 después de instalar o actualizar el paquete
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Wed, 14 Sep 2011 10:09:01 +0200
controlies (0.4-5) unstable; urgency=low
* Corregido problema cuando no hay segundo apellido
* Elimina espacios de los nombres de los grupos
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Tue, 13 Sep 2011 10:51:28 +0200
controlies (0.4-4) unstable; urgency=low
* Actualizada versión de jquery
* Añade apellidos al campo cn de ldap
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Mon, 12 Sep 2011 13:51:34 +0200
controlies (0.4-2) unstable; urgency=low
* No limpia los grupos a no ser que se marque la casilla de principio de curso
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Mon, 12 Sep 2011 10:09:35 +0200
controlies (0.4-1) unstable; urgency=low
* Añadida funcionalidad de rayuela a ldap
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Thu, 30 Jun 2011 14:03:14 +0200
controlies (0.3-3) unstable; urgency=low
* Añade profesores al grupo teachers y alumnos al students
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Tue, 31 May 2011 13:52:41 +0200
controlies (0.3-1) unstable; urgency=low
* Terminado de implementar en web2py todo lo que había con twisted
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Tue, 17 May 2011 13:08:40 +0200
controlies (0.2-2) unstable; urgency=low
* Cambios en la configuración de apache: directorio en vez de vhost
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Mon, 16 May 2011 14:23:55 +0200
controlies (0.2-1) unstable; urgency=low
* Completando funcionalidades
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Fri, 13 May 2011 14:37:17 +0200
controlies (0.1-1) unstable; urgency=low
* First Debian package
-- José L. Redrejo Rodríguez <jredrejo@debian.org> Wed, 04 May 2011 19:20:55 +0200
controlies/tags/0.6/debian/control
Source: controlies
Section: python
Priority: extra
Maintainer: José L. Redrejo Rodríguez <jredrejo@debian.org>,Manuel Mora Gordillo <manuito@gmail.com>
Build-Depends: debhelper (>= 7.0.50~)
Standards-Version: 3.8.4
Package: controlies
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, python-gluon, python-paramiko, python-ldap, python-imaging, python-dev, libapache2-mod-wsgi, libapache2-mod-python, libapache2-mod-gnutls, openssl, ssl-cert
Description: Gestión de LDAP para un centro educativo
ControlIES gestiona cuentas de usuarios, grupos, aulas, departamentos,
distintos tipos de ordenadores, importación de Rayuela, etc.
controlies/tags/0.6/debian/postinst
#!/bin/sh
# postinst script for controlies
#
# see: dh_installdeb(1)
set -e
case "$1" in
configure)
chown -R www-data:www-data /var/web2py
a2enmod ssl
a2enmod wsgi
a2ensite default-ssl
service apache2 --full-restart
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0
controlies/tags/0.6/debian/links
var/web2py/applications/controlies var/web2py/applications/init
controlies/tags/0.6/debian/dirs
var/web2py
etc/apache2/conf.d
etc/ldap/ssl
controlies/tags/0.6/debian/install
applications var/web2py
wsgihandler.py var/web2py
subwsgihandler.py var/web2py
VERSION var/web2py
controlies-apache etc/apache2/conf.d
applications/__init__.py var/web2py
controlies/tags/0.6/debian/copyright
This work was packaged for Debian by:
José L. Redrejo Rodríguez <jredrejo@debian.org> on Tue, 29 Jun 2010 20:40:58 +0200
Upstream Author(s):
Manuel Mora Gordillo <manuito @no-spam@ gmail.com>
Francisco Mendez Palma <fmendezpalma @no-spam@ gmail.com>
Copyright:
Copyright (C) 2011 Manuel Mora Gordillo
Francisco Mendez Palma
License:
ControlIES is Licensed under the LGPL license version 3
see "/usr/share/common-licenses/LGPL-3".
The Debian packaging is:
Copyright (C) 2010 José L. Redrejo Rodríguez <jredrejo@debian.org>
and is licensed under the GPL version 3,
see "/usr/share/common-licenses/GPL-3".
controlies/tags/0.6/debian/rules
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh $@
controlies/tags/0.6/debian/compat
7
controlies/tags/0.6/applications/controlies/modules/Rayuela2Ldap.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##############################################################################
# Project: ControlIES
# Module: Rayuela2Ldap.py
# Purpose: Populate corporative ldap with data from Rayuela
# Language: Python 2.5
# Date: 1-Jun-2011.
# Ver: 13-Jun-2011.
# Author: José L. Redrejo Rodríguez
# Copyright: 2011 - José L. Redrejo Rodŕiguez <jredrejo @no-spam@ debian.org>
#
#
# ControlIES is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# ControlIES is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with ControlIES. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import os
import Image #añadi
from gluon.storage import Storage
import xml.dom.minidom
import StringIO
import ldap
from Users import Users
from Groups import Groups
import Utils.LdapUtils as LdapUtils
class Rayuela(object):
def __init__(self,conexion,archivo,borrar):
self.borrando=borrar
self.esAlumnos=False
self.ldap_con =conexion
self.usuarios=[]
self.dni_usuarios=[]
self.logins=[]
self.archivo=archivo
def unzip_alumnos(self,archivo_zip):
""" Descomprime el archivo de alumnos en el directorio
/tmp/rayuela-ldap"""
from zipfile import ZipFile
try:
myzip= ZipFile(archivo_zip, 'r')
myzip.extractall(path="/tmp/rayuela-ldap")
except Exception,e:
return e
if not os.path.exists("/tmp/rayuela-ldap/Alumnos.xml"):
return "No es un archivo de importación de alumnos"
return "" #todo ha ido bien
def asegura_codigos(self,cadena):
"""Quita caracteres no válidos para los nombres de login
de los usuarios"""
resultado = cadena.replace(u"á", u"a")
resultado = resultado.replace(u"Á", u"A")
resultado = resultado.replace(u"à", u"a")
resultado = resultado.replace(u"ä", u"a")
resultado = resultado.replace(u"À", u"A")
resultado = resultado.replace(u"Ä", u"A")
resultado = resultado.replace(u"é", u"e")
resultado = resultado.replace(u"ë", u"e")
resultado = resultado.replace(u"É", u"E")
resultado = resultado.replace(u"Ë", u"E")
resultado = resultado.replace(u"è", u"e")
resultado = resultado.replace(u"È", u"E")
resultado = resultado.replace(u"í", u"i")
resultado = resultado.replace(u"Í", u"I")
resultado = resultado.replace(u"ì", u"i")
resultado = resultado.replace(u"ï", u"i")
resultado = resultado.replace(u"Ì", u"I")
resultado = resultado.replace(u"Ï", u"I")
resultado = resultado.replace(u"ó", u"o")
resultado = resultado.replace(u"Ó", u"O")
resultado = resultado.replace(u"Ö", u"O")
resultado = resultado.replace(u"ò", u"o")
resultado = resultado.replace(u"ö", u"o")
resultado = resultado.replace(u"Ò", u"O")
resultado = resultado.replace(u"ú", u"u")
resultado = resultado.replace(u"Ú", u"U")
resultado = resultado.replace(u"ü", u"u")
resultado = resultado.replace(u"Ü", u"U")
resultado = resultado.replace(u"ù", u"u")
resultado = resultado.replace(u"Ù", u"U")
resultado = resultado.replace(u"ª", u"a")
resultado = resultado.replace(u"º", u"o")
resultado = resultado.replace(u"ñ", u"n")
resultado = resultado.replace(u"Ñ", u"N")
resultado = resultado.replace(u"ç", u"c")
resultado = resultado.replace(u"(", u"")
resultado = resultado.replace(u")", u"")
resultado = resultado.replace(u".", u"")
resultado = resultado.replace(u",", u"")
resultado = resultado.replace(u"&", u"")
return str(resultado).strip()
def chk_username(self,login,keep=False):
"""Comprueba si el login existe ya en la base de datos
de ldap, y si existe le va aumentando el número del final"""
if not keep:
nuevo_login= login + "01"
else:
nuevo_login=login
result = self.ldap_con.search("ou=People","uid="+ nuevo_login,["uid"])
if len(result)==0 and nuevo_login not in self.logins:
return nuevo_login
else:
i=2
while len(result)>0 or nuevo_login in self.logins:
nuevo_login=login + "%02d" % (i)
result = self.ldap_con.search("ou=People","uid="+ nuevo_login,["uid"])
i += 1
return nuevo_login
def crea_logins(self):
"""Revisa la lista de usuarios y le asigna nuevo login al que
no está ya en ldap o no lo trae de Rayuela"""
for usuario in self.usuarios:
usuario["nuevo"]=True
if "dni" in usuario.keys():
#contraseña del usuario:
if self.esAlumnos:
usuario["passwd"]=usuario["fecha-nacimiento"].replace("/","")
if usuario["passwd"]=="": usuario["passwd"]=usuario["dni"]
else:
usuario["passwd"]=usuario["dni"]
#login del usuario, primero vemos si ya está en ldap:
result = self.ldap_con.search("ou=People","employeeNumber="+ usuario["dni"],["uid"])
if len(result) > 0:
usuario["login"]=result[0][0][1]['uid'][0]
usuario["nuevo"]=False
else: #si el usuario no está en ldap y es nuevo, hay que crearle el login
if usuario["datos-usuario-rayuela"] != "false": #esta en rayuela su login
# en Rayuela no están validando los logins, lo que provoca que pueda haber
# logins no validos. Así que nos toca hacerlo a nosotros:
login_rayuela=self.asegura_codigos(usuario["datos-usuario-rayuela"])
login_rayuela=login_rayuela.lower().replace("-","").replace(" ","")
usuario["login"]=self.chk_username(login_rayuela,True)
else: #iniciales del nombre + primer apellido + inicial segundo apellido
login=''
for i in zip(*usuario["nombre"].lower().split(" "))[0]:
login += i.strip()
for i in usuario["primer-apellido"].lower().replace("-"," ").split(" "):
login += i.strip()
if "segundo-apellido" in usuario.keys():
if len(usuario["segundo-apellido"])>0:
login += usuario["segundo-apellido"][0].lower().strip()
usuario["login"]=self.chk_username(login)
self.logins.append(usuario["login"])
else: #sin nie ni dni, no podemos gestionarlo
self.usuarios.remove(usuario)
def encode(self,grafico):
"""Convierte la foto del alumno a un tamaño pequeño y
en un formato gráfico aceptable en ldap"""
archivo=os.path.join("/tmp/rayuela-ldap/",grafico)
try:
im = Image.open(archivo)
im.thumbnail((60,80), Image.ANTIALIAS)
if im.mode != "RGB":
im = im.convert("RGB")
buf= StringIO.StringIO()
try:
im.save(buf, format= 'JPEG')
resultado=buf.getvalue()
except Exception,e:
return None
except:
return None
return resultado
def parse_nodo(self,nodo):
""" para cada nodo en el xml, obtiene sus datos y prepara sus grupos"""
usuario={}
for info in nodo.childNodes:
if info.nodeType!=info.TEXT_NODE:
if info.nodeName in ("datos-usuario-rayuela","foto","grupos"):
dato=info.childNodes[1].firstChild.nodeValue
if info.nodeName=="foto" and dato=="true":
dato=info.getElementsByTagName("nombre-fichero")[0].firstChild.nodeValue
if info.nodeName=="datos-usuario-rayuela" and dato=="true":
dato=info.getElementsByTagName("login")[0].firstChild.nodeValue
else:
try:
dato=info.firstChild.nodeValue
except : # no hay dato en este nodo, p. ej. segundo-apellido
dato=' '
if info.nodeName == 'nie':
usuario["dni"]=self.asegura_codigos(dato)
elif info.nodeName == 'foto': #no paso asegura_codigos para no quitar el "."
usuario['foto']=str(dato)
elif info.nodeName == 'grupo': #no paso asegura_codigos para no quitar el "."
nombre_grupo=self.asegura_codigos(dato).replace(" ","")
if len(nombre_grupo)>0:
usuario['grupo']=nombre_grupo
else:
usuario[info.nodeName]=self.asegura_codigos(dato)
self.usuarios.append(usuario)
self.dni_usuarios.append(usuario["dni"])
def parsea_archivo(self,archivo_xml,tipo):
"""Recorre el archivo xml y va generando la lista de usuarios"""
xml_usuarios=xml.dom.minidom.parse(archivo_xml)
lista= xml_usuarios.getElementsByTagName(tipo)
for nodo in lista:
self.parse_nodo(nodo)
self.crea_logins()
def lista_grupos(self,lista,clave,sin_grupo="SIN_AULA"):
"""Devuelve una enumeración de los grupos que pertenecen a
clave, siendo normalmente clave igual a aulas o dptos"""
grupos={}
for i in lista:
if clave not in i.keys():
grupo=sin_grupo
else:
grupo=i[clave]
if grupo not in grupos.keys():
grupos[grupo]=[i["login"]]
else:
grupos[grupo].append(i["login"])
return grupos
def crea_grupos(self,listado):
"""Da de alta en ldap los grupos de alumnos"""
for grupo in listado:
nuevo=Groups(self.ldap_con ,"school_class",str(grupo),"")
nuevo.add()
def existsUsername(self,login):
"""comprueba si login existe ya en la bb.dd de ldap"""
result = self.ldap_con.search("ou=People","uid="+ login,["uid"])
if len(result) > 0:
return True
else:
return False
def crea_usuarios(self):
"""Da de alta en ldap los usuarios que están en el listado"""
lista=[]
if self.esAlumnos:
tipo="student"
else:
tipo="teacher"
for usuario in self.usuarios:
if not self.existsUsername(usuario['login']):
if self.esAlumnos:
if usuario['foto'] == 'false':
foto=None
else:
foto=self.encode(usuario['foto'])
else:
foto=None
surname=usuario['primer-apellido'] + ' ' + usuario['segundo-apellido']
nuevo=Users(self.ldap_con ,tipo,usuario['nombre'],surname.strip(),
usuario['dni'],usuario['login'],usuario['passwd'],usuario['passwd'],'','',foto)
nuevo.add()
lista.append((usuario['login'],True,usuario['passwd']))
else:
lista.append((usuario['login'],False,''))
return lista
def rellena_students(self):
"""Da de alta en el grupo students los que están en listado"""
if len(self.ldap_con.search("ou=Group","cn=students",["cn"]))==0:
attr = [
('objectclass', ['top','posixGroup','lisGroup','lisAclGroup']),
('grouptype', ["authority_group"] ),
('gidnumber', ["1100"] ),
('cn', ['students'] ),
('description', ['Lista de estudiantes del centro']),
('memberuid', ['']),
('member', [''])
]
self.ldap_con.add("cn=students,ou=Group", attr)
for usuario in self.usuarios:
attr=[(ldap.MOD_ADD, 'member', ['uid=' + usuario['login'] + ',ou=People,dc=instituto,dc=extremadura,dc=es'] ),
(ldap.MOD_ADD, 'memberUid', [usuario['login']] )]
try:
self.ldap_con.modify('cn=students,ou=Group', attr)
except Exception,e:
print e
def rellena_teachers(self):
"""Da de alta en el grupo teachers a todos los que están en el listado"""
if len(self.ldap_con.search("ou=Group","cn=teachers",["cn"]))==0:
attr = [
('objectclass', ['top','posixGroup','lisGroup','lisAclGroup']),
('grouptype', ["authority_group"] ),
('gidnumber', ["3000"] ),
('cn', ['teachers'] ),
('description', ['Lista de profesores del centro']),
('memberuid', ['']),
('member', [''])
]
self.ldap_con.add("cn=teachers,ou=Group", attr)
for usuario in self.usuarios:
attr=[(ldap.MOD_ADD, 'member', ['uid=' + usuario['login'] + ',ou=People,dc=instituto,dc=extremadura,dc=es'] ),
(ldap.MOD_ADD, 'memberUid', [usuario['login']] )]
try:
self.ldap_con.modify('cn=teachers,ou=Group', attr)
except Exception,e:
print e
def usuarios_grupos(self,lista_grupos):
"""Da de alta en cada grupo a los usuarios correspondientes"""
for grupo in lista_grupos:
for usuario in lista_grupos[grupo]:
attr=[(ldap.MOD_ADD, 'member', ['uid=' + usuario + ',ou=People,dc=instituto,dc=extremadura,dc=es'] ),
(ldap.MOD_ADD, 'memberUid', [usuario] ) ]
try:
self.ldap_con.modify('cn=' + grupo + ',ou=Group', attr)
except Exception,e:
print e
def lista_antiguos(self,grupo):
"""Devuelve el listado de los dni de los usuarios que ya estaban en ldap antes"""
lista={}
home="/home/" + grupo
comparar=home[:13]
#resultado=self.ldap_con.search("ou=Group","cn=" + grupo ,["memberuid"])
resultado=self.ldap_con.search("ou=People","objectClass=person" , ["employeeNumber","uid","homeDirectory"])
miembros=[]
for i in resultado:
if i[0][1]['homeDirectory'][0][:13]==comparar: miembros.append(i)
if len(miembros) > 0:
for dato in miembros:
if len(dato) > 0:
try:
dni=dato[0][1]['employeeNumber'][0]
uid=dato[0][1]['uid'][0]
lista[dni]=uid
except:
continue
return lista
def borra_antiguos(self,viejos):
"""Borra de la base de datos de ldap a los usuarios que estaban
en la lista de viejos y no están en la de nuevos"""
borrables={}
for usuario in viejos:
if not usuario in self.dni_usuarios:
borrables[usuario]=viejos[usuario]
for viejo in borrables:
try:
self.ldap_con.delete('uid='+ borrables[viejo] +',ou=People')
self.ldap_con.delete("cn="+ borrables[viejo] +",ou=Group")
except:
pass #algún dato ya estaba borrado
def gestiona_archivo(self):
"""Función principal que a partir del archivo hace todo en ldap"""
aulas={}
dptos={}
self.esAlumnos=(self.archivo[-4:].lower()==".zip")
if self.esAlumnos:
intento=self.unzip_alumnos(self.archivo)
if intento!="":
print "PROBLEMAS",intento
else:
usuarios_antiguos=self.lista_antiguos("alumnos")
self.parsea_archivo("/tmp/rayuela-ldap/Alumnos.xml","alumno")
aulas=self.lista_grupos(self.usuarios,"grupo")
else:
usuarios_antiguos=self.lista_antiguos("profesor")
self.parsea_archivo(self.archivo,"profesor")
dptos=self.lista_grupos(self.usuarios,"departamento","SIN_DPTO")
self.crea_grupos(aulas)
self.crea_grupos(dptos)
total=self.crea_usuarios()
if self.esAlumnos:
if self.borrando: LdapUtils.clean_students(self.ldap_con )
self.rellena_students()
self.usuarios_grupos(aulas)
else:
if self.borrando: LdapUtils.clean_teachers(self.ldap_con )
self.rellena_teachers()
self.usuarios_grupos(dptos)
if self.borrando:
self.borra_antiguos(usuarios_antiguos)
return total
if __name__ == '__main__':
#El código siguiente es sólo para depuración y desarrollo
#No tiene sentido fuera de ese contexto
import LdapConnection
session=Storage()
session.server="ldap"
session.username="admin"
session.password="linex2008"
ldap_con = LdapConnection.LdapConnection(session)
ldap_con.process()
try:
os.mkdir( "/tmp/rayuela-ldap")
except:
pass #problema de permisos o directorio ya creado
archivo="/opt/instituto/santaeulalia/ExportacionDatosAlumnado.zip"
archivo="/tmp/ExportacionDatosAlumnado.zip"
rayuela=Rayuela(ldap_con,archivo,True)
todos=rayuela.gestiona_archivo()
LdapUtils.sanea_grupos(ldap_con)
print todos
controlies/tags/0.6/applications/controlies/modules/Groups.py
##############################################################################
# -*- coding: utf-8 -*-
# Project: ControlIES
# Module: Groups.py
# Purpose: Groups class
# Language: Python 2.5
# Date: 7-Feb-2011.
# Ver: 7-Feb-2011.
# Author: Manuel Mora Gordillo
# Francisco Mendez Palma
# Copyright: 2011 - Manuel Mora Gordillo <manuito @no-spam@ gmail.com>
# 2011 - Francisco Mendez Palma <fmendezpalma @no-spam@ gmail.com>
#
# ControlIES is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# ControlIES is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with ControlIES. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import ldap
import logging
from math import floor
from operator import itemgetter
from Utils import Utils, LdapUtils
class Groups(object):
def __init__(self):
pass
def __init__(self,ldap,type,name,users):
self.ldap = ldap
self.type = type
self.name = Utils.parseToLdap(name)
self.users = users
def exists_group_name(self):
result = self.ldap.search("ou=Group","cn="+self.name,["cn"])
if len(result) > 0:
return True
return False
def validation(self,action):
if self.type == "none":
return "type"
if self.name == "":
return "name"
if self.users == "":
return "users"
return "OK"
def process(self,action):
if action == "add":
val = self.validation(action)
if val != "OK":
return val
else:
response = self.add()
return response
if action == "modify":
val = self.validation(action)
if val != "OK":
return val
else:
response = self.modify()
return response
def list(self,args):
filter = self.buildFilter(args)
search = self.ldap.search("ou=Group",filter,["cn","gidNumber","groupType","memberUid"])
# grid parameters
limit = int(args['rows'])
page = int(args['page'])
start = limit * page - limit
finish = start + limit;
# sort by field
sortBy = args['sidx']
if sortBy == "cn":
sortBy = "id"
# reverse Sort
reverseSort = False
if args['sord']== "asc":
reverseSort = True
# type of group (Classroom/Department)
try:
searchType = args['type']
except LookupError:
searchType = "none"
rows = []
for i in search:
typeRow="Aula"
if i[0][1]["groupType"][0]=="school_department":
typeRow="Departamento"
if searchType == typeRow or searchType=="none":
try:
usersNumber = len(i[0][1]["memberUid"])
except:
usersNumber = 0
row = {
"id":i[0][1]["cn"][0],
"cell":[typeRow, i[0][1]["cn"][0], i[0][1]["gidNumber"][0], usersNumber],
"type": typeRow,
"cn": i[0][1]["cn"][0],
"gidNumber": i[0][1]["gidNumber"][0],
"usersNumber": usersNumber
}
rows.append(row)
if len(rows) > 0:
totalPages = floor( len(rows) / int(limit) )
module = len(rows) % int(limit)
if module > 0:
totalPages = totalPages+1
else:
totalPages = 0
if page > totalPages:
page = totalPages
# sort rows
result = sorted(rows, key=itemgetter(sortBy), reverse=reverseSort)
return { "page":page, "total":totalPages, "records":len(search), "rows":result[start:finish] }
def listUsers(self,args):
from applications.controlies.modules.Users import Users
# grid parameters
limit = int(args['rows'])
page = int(args['page'])
start = limit * page - limit
finish = start + limit;
# sort by field
sortBy = args['sidx']
if sortBy == "cn":
sortBy = "id"
# reverse Sort
reverseSort = False
if args['sord']== "asc":
reverseSort = True
groupData = self.getGroupData()
rows = []
for i in groupData["memberuid"]:
u = Users(self.ldap,"","","","",i,"","","","")
userData = u.getUserData()
row = {
"id":userData["user"],
"cell":[userData["name"],userData["user"],userData["nif"]],
"cn": userData["name"],
"uid": userData["user"],
"employeeNumber": userData["nif"]
}
rows.append(row)
if len(rows) > 0:
totalPages = floor( len(rows) / int(limit) )
module = len(rows) % int(limit)
if module > 0:
totalPages = totalPages+1
else:
totalPages = 0
if page > totalPages:
page = totalPages
# sort rows
result = sorted(rows, key=itemgetter(sortBy), reverse=reverseSort)
return { "page":page, "total":totalPages, "records":len(groupData["memberuid"]), "rows":result[start:finish] }
def buildFilter(self, args):
filter = "(&(cn=*)(|(groupType=school_class)(groupType=school_department))"
try:
filter = filter + "(cn=*" + args['cn'] + "*)"
except LookupError:
pass
try:
filter = filter + "(gidNumber=" + args['gidNumber'] + ")"
except LookupError:
pass
filter = filter + ")"
return filter
def add(self):
if self.exists_group_name(): return "OK"
maxID = str(LdapUtils.getMaxID(self.ldap))
if len(self.users)>0:
members = []
for m in self.users.split(','):
members.append("uid=" + m + ",ou=People,dc=instituto,dc=extremadura,dc=es")
memberuids=self.users.split(',')
else:
members=['']
memberuids=['']
attr = [
('objectclass', ['top','posixGroup','lisGroup','lisAclGroup']),
('grouptype', [self.type] ),
('gidnumber', [maxID] ),
('cn', [self.name] ),
('description', [self.name+' department group']),
('memberuid', memberuids),
('member', members)
]
self.ldap.add("cn="+self.name+",ou=Group", attr)
return "OK"
def modify(self):
members = []
for m in self.users.split(','):
members.append("uid=" + m + ",ou=People,dc=instituto,dc=extremadura,dc=es")
mod_attrs = [
(ldap.MOD_REPLACE, 'memberuid', self.users.split(',')),
(ldap.MOD_REPLACE, 'member', members)
]
self.ldap.modify('cn='+ self.name +',ou=Group', mod_attrs)
return "OK"
def delete(self):
self.ldap.delete('cn='+ self.name +',ou=Group')
return "OK"
def getGroupData(self):
result = self.ldap.search("ou=Group","cn="+self.name,["cn","grouptype","memberuid"])
members = result[0][0][1]["memberUid"]
members.sort()
dataGroup = {
"name":result[0][0][1]["cn"][0],
"type":result[0][0][1]["groupType"][0],
"memberuid":members
}
return dataGroup
def getGroupUsers(self):
result = self.ldap.search("ou=Group","cn="+self.name,["cn","memberUid"])
members = []
for m in result:
members.append(m[0][1]["memberUid"][0])
members.sort()
return members
controlies/tags/0.6/applications/controlies/modules/Users.py
##############################################################################
# -*- coding: utf-8 -*-
# Project: ControlIES
# Module: Users.py
# Purpose: Users class
# Language: Python 2.5
# Date: 7-Feb-2011.
# Ver: 7-Feb-2011.
# Author: Manuel Mora Gordillo
# Copyright: 2011 - Manuel Mora Gordillo <manuito @no-spam@ gmail.com>
#
# ControlIES is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# ControlIES is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with ControlIES. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import ldap
import logging
import hashlib
import base64
from math import floor
from operator import itemgetter
from Utils import Utils, LdapUtils
class Users(object):
def __init__(self):
pass
def __init__(self,ldap,type,name,surname,nif,user,password,password2,departments,classrooms,foto=None):
self.ldap = ldap
self.type = type
self.name = name
self.surname = surname
self.nif = nif
self.user = user
self.password = password
self.password2 = password2
self.departments = departments
self.classrooms = classrooms
self.foto=foto
if self.departments.__class__.__name__ == 'str': self.departments=[departments]
if self.classrooms.__class__.__name__ == 'str': self.classrooms=[classrooms]
def validation(self,action):
if action == "add":
if self.type == "none":
return "type"
if self.name == "":
return "name"
if self.surname == "":
return "surname"
if self.nif == "":
return "nif"
if self.user == "":
return "user"
if action == "add":
if self.existsUsername():
return "userAlreadyExists"
if self.password == "":
return "password"
if self.password2 == "":
return "password2"
if self.password != self.password2:
return "distinctPassword"
elif action == "modify":
if self.password == "" and self.password2 != "":
return "password"
if self.password != "" and self.password2 == "":
return "password2"
if self.password != "" and self.password2 != "" and self.password != self.password2:
return "distinctPassword"
return "OK"
def process(self,action):
if action == "add":
val = self.validation(action)
if val != "OK":
return val
else:
response = self.add()
return response
if action == "modify":
val = self.validation(action)
if val != "OK":
return val
else:
response = self.modify()
return response
def list(self,args):
filter = self.buildFilter(args)
search = self.ldap.search("ou=People",filter,["employeeNumber","uid","cn","uidnumber","gidnumber","homedirectory"])
# grid parameters
limit = int(args['rows'])
page = int(args['page'])
start = limit * page - limit
finish = start + limit;
# sort by field
sortBy = args['sidx']
if sortBy == "uid":
sortBy = "id"
# reverse Sort
reverseSort = False
if args['sord'] == "asc":
reverseSort = True
# type of user (Teacher/Student)
try:
searchType = args['type']
except LookupError:
searchType = "none"
rows = []
for i in search:
typeRow="Alumno"
userdata=i[0][1]
if userdata["homeDirectory"][0][0:14]=="/home/profesor":
typeRow="Profesor"
if not "employeeNumber" in userdata: userdata["employeeNumber"]=["0"]
if searchType == typeRow or searchType=="none":
row = {
"id":userdata["uid"][0],
"cell":[typeRow, userdata["cn"][0], userdata["uid"][0], userdata["uidNumber"][0], userdata["gidNumber"][0], userdata["employeeNumber"][0]],
"type": typeRow,
"cn":userdata["cn"][0],
"uidNumber":userdata["uidNumber"][0],
"gidNumber":userdata["gidNumber"][0],
"employeeNumber":userdata["employeeNumber"][0]
}
rows.append(row)
# grid parameters
if len(rows) > 0:
totalPages = floor( len(rows) / int(limit) )
module = len(rows) % int(limit)
if module > 0:
totalPages = totalPages+1
else:
totalPages = 0
if page > totalPages:
page = totalPages
# sort rows
result = sorted(rows, key=itemgetter(sortBy), reverse=reverseSort)
return { "page":page, "total":totalPages, "records":len(rows), "rows":result[start:finish] }
def buildFilter(self, args):
filter = "(&(uid=*)"
try:
filter = filter + "(uid=*" + args['uid'] + "*)"
except LookupError:
pass
try:
filter = filter + "(cn=*" + args['cn'] + "*)"
except LookupError:
pass
try:
filter = filter + "(uidNumber=" + args['uidNumber'] + ")"
except LookupError:
pass
try:
filter = filter + "(gidNumber=" + args['gidNumber'] + ")"
except LookupError:
pass
try:
filter = filter + "(employeeNumber=*" + args['employeeNumber'] + "*)"
except LookupError:
pass
filter = filter + ")"
return filter
def add(self):
maxID = str(LdapUtils.getMaxID(self.ldap))
passwd = '{SSHA}' + Utils.encrypt(self.password)
attr = [
('objectclass', ['top','posixAccount','shadowAccount','person','inetOrgPerson']),
('uid', [self.user]),
('cn', [self.name] ),
('employeenumber', [self.nif] ),
('sn', [self.name] ),
('uidnumber', [maxID] ),
('gidnumber', [maxID] ),
('loginshell', ['/bin/bash'] ),
('homeDirectory', [LdapUtils.whatHome(self.type) + self.user] ),
#('jpegPhoto', ['jpegPhoto'] ),
('userpassword', [passwd])
]
if self.foto is not None:
attr.append(('jpegPhoto',[self.foto]))
self.ldap.add("uid="+self.user+",ou=People", attr)
# Add private group
attr = [
('objectclass', ['top','posixGroup','lisGroup']),
('grouptype', ['private']),
('gidnumber', [maxID] ),
('cn', [self.user] ),
('description', [self.name+' personal group'] )
]
self.ldap.add("cn="+self.user+",ou=Group", attr)
# Add selected groups
attr = [
(ldap.MOD_ADD, 'member', ['uid='+self.user+',ou=People,dc=instituto,dc=extremadura,dc=es'] ),
(ldap.MOD_ADD, 'memberUid', [self.user] )
]
if self.departments != ['']:
for n in self.departments:
self.ldap.modify('cn='+ n +',ou=Group', attr)
if self.classrooms != ['']:
for n in self.classrooms:
self.ldap.modify('cn='+ n +',ou=Group', attr)
if self.type=='teacher':
self.ldap.modify('cn=teachers,ou=Group', attr)
elif self.type=='student':
self.ldap.modify('cn=students,ou=Group', attr)
return "OK"
def modify(self):
attr = [
(ldap.MOD_REPLACE, 'cn', [self.name] ),
(ldap.MOD_REPLACE, 'employeenumber', [self.nif] ),
(ldap.MOD_REPLACE, 'sn', [self.surname] )
]
if self.password!="":
passwd = '{SSHA}' + Utils.encrypt(self.password)
attr.append((ldap.MOD_REPLACE, 'userpassword', [passwd]))
self.ldap.modify("uid="+self.user+",ou=People", attr)
# Get current groups
currentGroups = self.getUserGroups()
groupsDepartments = Utils.cmpLists(currentGroups["departments"], self.departments)
groupsClassrooms = Utils.cmpLists(currentGroups["classrooms"], self.classrooms)
# Delete unselected groups
deleteDepartments = groupsDepartments["onlyInList1"]
deleteClassrooms = groupsClassrooms["onlyInList1"]
attr = [
(ldap.MOD_DELETE, 'member', ['uid='+self.user+',ou=People,dc=instituto,dc=extremadura,dc=es'] ),
(ldap.MOD_DELETE, 'memberUid', [self.user] )
]
for d in deleteDepartments:
self.ldap.modify('cn='+ d +',ou=Group', attr)
for d in deleteClassrooms:
self.ldap.modify('cn='+ d +',ou=Group', attr)
# Add selected groups
newDepartments = groupsDepartments["onlyInList2"]
newClassrooms = groupsClassrooms["onlyInList2"]
attr = [
(ldap.MOD_ADD, 'member', ['uid='+self.user+',ou=People,dc=instituto,dc=extremadura,dc=es'] ),
(ldap.MOD_ADD, 'memberUid', [self.user] )
]
for n in newDepartments:
self.ldap.modify('cn='+ n +',ou=Group', attr)
for n in newClassrooms:
self.ldap.modify('cn='+ n +',ou=Group', attr)
return "OK"
def delete(self):
self.ldap.delete('uid='+ self.user +',ou=People')
self.ldap.delete("cn="+self.user+",ou=Group")
# Delete unselected groups
currentGroups = self.getUserGroups()
attr = [
(ldap.MOD_DELETE, 'member', ['uid='+self.user+',ou=People,dc=instituto,dc=extremadura,dc=es'] ),
(ldap.MOD_DELETE, 'memberUid', [self.user] )
]
for d in currentGroups["departments"]:
self.ldap.modify('cn='+ d +',ou=Group', attr)
for d in currentGroups["classrooms"]:
self.ldap.modify('cn='+ d +',ou=Group', attr)
return "OK"
def existsUsername(self):
result = self.ldap.search("ou=People","uid="+self.user,["uid"])
if len(result) > 0:
return True
return False
def searchNewUsername(self):
result = self.ldap.search("ou=People","uid=*",["uid"])
users = []
for i in result:
users.append(i[0][1]['uid'][0])
n = self.name.lower().split(" ")
username = ""
if len(n) > 0:
username = n[0][0:1]
if len(n) > 1:
username = username + n[1]
if len(n) > 2:
username = username + n[2][0:1]
num = 1
searching = username + "0" + str(num)
found = True
while found:
try:
users.index(searching)
num = num + 1
if len(str(num)) == 1:
searching = username + "0" + str(num)
else:
searching = username + str(num)
except:
found = False
return searching
def getUserGroups(self):
result = self.ldap.search("ou=Group","(&(memberUid="+self.user+")(|(groupType=school_department)(groupType=school_class)))",["cn","groupType"])
departments = []
classrooms = []
for g in result:
if g[0][1]["groupType"][0] == "school_department":
departments.append(g[0][1]["cn"][0])
elif g[0][1]["groupType"][0] == "school_class":
classrooms.append(g[0][1]["cn"][0])
departments.sort()
classrooms.sort()
return { "departments":departments, "classrooms":classrooms }
def getUserData(self):
self.getUserGroups()
result = self.ldap.search("ou=People","uid="+self.user,["uid","cn","sn","employeenumber","homedirectory","uidnumber","gidnumber","jpegPhoto"])
if len(result) == 0:
return { "user":"", "name":"", "surname":"", "nif":"", "photo":"", "type":"","uidnumber":"","gidnumber":"", "groups":[] }
type = "student"
if result[0][0][1]["homeDirectory"][0][0:14]=="/home/profesor":
type = "teacher"
try:
photo = base64.b64encode(result[0][0][1]["jpegPhoto"][0])
except:
photo = ""
userdata=result[0][0][1]
if "employeeNumber" not in userdata: userdata["employeeNumber"]=["0"]
dataUser = {
"user":userdata["uid"][0],
"name":userdata["cn"][0],
"surname":userdata["sn"][0],
"nif":userdata["employeeNumber"][0],
"uidnumber":userdata["uidNumber"][0],
"gidnumber":userdata["gidNumber"][0],
"photo":photo,
"type":type,
"groups":self.getUserGroups()
}
return dataUser
def getUserPhoto(self):
self.getUserGroups()
result = self.ldap.search("ou=People","uid="+self.user,["jpegPhoto"])
try:
photo = base64.b64encode(result[0][0][1]["jpegPhoto"][0])
except:
photo = ""
dataUser = {
"photo":photo
... Diferencia truncada por exceder el máximo tamaño visualizable.

Exportar a: Unified diff