class WebLogout(Resource): def __init__(self): self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound def render_GET(self, request): session = request.getSession() _ = getTranslatorFromSession(request) if hasattr(session, 'username'): del(session.username) del(session.userId) del(session.kind) del(session.name) del(session.lastname) del(session.locale) request.write(self.template.startPage(session, _('Cerrar Sesion'))) request.write('<div class="message"><h2>' + _('La sesion ha sido cerrada') + '</h2>' + _('Que tenga un buen dia.') + '</div>') else: request.write(self.template.startPage(session)) request.write('<div class="warning"><h2>' + _('Sesion inexistente') + '</h2>' + _('Debe iniciar una sesion antes de cerrarla!') + '</div>') request.write(self.template.finishPage(session)) del(session._) request.finish() return server.NOT_DONE_YET
class WebContent(Resource): def __init__(self): Resource.__init__(self) self.template = WebTemplates() self.pages = static.File('./htdocs/content/') def getChild(self, path, request): return self def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.writeContent, request) return server.NOT_DONE_YET def writeContent(self, trans, request): session = request.getSession() _ = trans request.write(self.template.startPage(session, \ _('Beppo - Sistema de educacion a distancia'))) page = self.pages.getChild(request.prepath[-1], request) if hasattr(page, 'getContent'): request.write(page.getContent()) else: request.write(self.template.notFound(session)) request.write(self.template.finishPage(session)) request.finish() return
class WebUserInfo(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans info = WebGetUserInfo(self.db, session) # 0) Se empieza la página request.write(self.template.startPage(session, _('Informacion de usuario'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, puede ver todos los usuarios elif "user_id" in request.args.keys() and "kind" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) kind = int(request.args['kind'][0]) msg = '<h2>' + _('Informacion de usuario') + '</h2>' d.addCallback(lambda a: info.getUserInfo(user_id, kind)) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('Argumento no valido'))) user_id = kind = msg = None d.addCallback(lambda a: None) d.addCallback(self.printContent, request, d, user_id, kind, session, msg) else: request.write(self.template.unexpectedArguments(session, \ _('Falta algun argumento'))) d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, data, request, d, userId, kind, session, msg): d.addCallback(lambda a: request.write(msg)) d.addCallback(lambda a: request.write(data)) return
class WebSubjectAdmin(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # Si estamos autenticados como admin, sirve para ver, agregar y borrar materias def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, _('Administracion de materias'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: msg = '<h2>' + _('Administracion de Materias') + '</h2>' + _('Estas son las materias disponibles en el sistema. Desde aqui se pueden agregar y borrar materias') + '<br/>' # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, msg) else: # 4) Si no es Admin, es alguien que no está autorizado a # administrar materias request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d, msg): # 1) Si se envían datos, se agrega try: pag = int(request.args['pag'][0]) except: pag = 0 _ = request.getSession()._ if "submit" in request.args.keys(): op = "insert into subject (name) values (%s)" name = QuotedString(request.args['name'][0]) d.addCallback(lambda a: self.db.db.runOperation(op, (name,))) d.addCallback(lambda a: request.write("""<div class="message"><h2>""" + \ _('Materia agregada') + '</h2>' + \ _('La materia ha sido guardada correctamente') + """</div>""")) elif "del" in request.args.keys(): # si nos piden borrar, llamamos al metodo de borrar materias de # DBDelete, el cual borra la materia si no tiene referencias # y si no devuelve False erase = DBDelete(self.db) delete = int(request.args['del'][0]) d.addCallback(lambda a: erase.deleteSubject(delete)) d.addCallback(self.printSubjectDelete, request) # 2) Se imprime un mensaje de bienvenida configurable d.addCallback(lambda a: request.write(msg)) # 3) Se buscan los datos nuevos en la base op = "select s.id, s.name, count(fk_subject), (select count(*) from subject) from subject s \ left join tutor_subject t on (s.id = t.fk_subject) \ group by s.id, s.name order by name asc" op += " LIMIT %d OFFSET %d" % (ITEMS_PAG, ITEMS_PAG*pag) d.addCallback(lambda a: self.db.db.runQuery(op)) d.addCallback(self.printForm, request, pag) return d #return confirm("¿Está seguro de borrar la materia" + subject + "?\n (" + tutors + " " + "tutores la tienen como seleccionada)"); def printForm(self, rows, request, pag): """recibe el resultado de una consulta de materias e imprime la tabla que las muestra y permite borrarlas. ademas imprime un formulario para agregar materias (y el codigo JavaScript de chequeo correspondiente) """ _ = request.getSession()._ string = """ <script type="text/javascript"> function del_confirm(subject, tutors){ string = \" """ + _('Esta seguro de borrar la materia') + """ \"+subject+\"?\\n\"; if(tutors == 1){ string += \"(""" + _('1 tutor la tiene como seleccionada') + """)\"; }else if(tutors > 0){ string += \"(\" + tutors + \" \" + \"""" + \ _('tutores la tienen como seleccionada') + """)\"; } return confirm(string); } </script> <br/> <table class="table_list" id="subjects"> <tr> <th class="icon_list"></th> <th class="header_list">""" + _('Materia') + """</th> <th class="header_list">""" + _('# Tutores') + """</th> </tr> """ for i in range(len(rows)): string += """ <tr> <td class="row_list"><a href="?del=%d" onclick="return del_confirm('%s', %d)" class="link_image"><img src="/static/graphics/delete.gif" width="16" height="16" alt=\"""" % (rows[i][0], rows[i][1], rows[i][2])+ _('Borrar') + """\" title=\"""" + _('Borrar') + """\"/></a></td> <td class="row_list">%s</td> <td class="row_list">%d</td> </tr>""" % (rows[i][1], rows[i][2]) string += """ </table> <br/> <script type="text/javascript"> function check_args(form){ if(form.name.value == ""){ alert(\"""" + _('El nombre de la materia no puede ser vacio') + """\"); return false; }else{ return true; } } </script> <form action="" method="get" onsubmit="return check_args(this)" ><div> <input type="text" name="name" id="name" size="20"/> <input type="submit" name="submit" id="submit" value=\"""" + _('Insertar') + """\" size="15"/></div> </form> """ request.write(string) #PAGINACION try: total = rows[0][-1:][0] #la ultima columna es el total de datos para la consulta print "total ", total if total > ITEMS_PAG: request.write('<div> <strong>' + _('Página:') + '</strong>') if total % ITEMS_PAG == 0: una_mas = 0 else: una_mas = 1 for pagina in range((total/ITEMS_PAG) + una_mas): tip = "href" if pagina == pag: tip = "id" link = "<a %s='/subject_admin?pag=%d'>%d</a> " % (tip,pagina,pagina+1) request.write(link) request.write('</div><br />') #FIN PAGINACION except IndexError: pass return def printSubjectDelete(self, result, request): """Chequea el resultado de la llamada al metodo de DBDelete para el borrado de una materia. Imprime el mensaje correspondiete, de acuerdo si la materia ha sido o no borrada """ _ = request.getSession()._ if result == False: msg = """<div class="error"><h2>""" + _('Materia no borrada') + """</h2>""" + \ _('Existen clases por darse o preguntas por contestarse para esta materia')\ + """</div>""" else: msg = """<div class="message"><h2>""" + _('Materia borrada') + """</h2>""" + \ _('La materia ha sido borrada correctamente') + """</div>""" request.write(msg)
class WebRoot(Resource): #def __init__(self, users, openRooms, shouldBeOpenRooms): def __init__(self, server): Resource.__init__(self) self.db = DBConnect() self.template = WebTemplates() self.putChild("roominfo", WebRoomInfo(server)) self.putChild("userinfo", WebUserInfo()) self.putChild("login", WebLogin()) self.putChild("logout", WebLogout()) self.putChild("static", static.File("./htdocs/")) self.putChild("board_archive", static.File("./archive/")) self.putChild("content", WebContent()) self.putChild("calendar", static.File("./calendar/")) self.putChild("subjects", WebSubjects()) self.putChild("settings", WebSettings()) self.putChild("subject_admin", WebSubjectAdmin()) self.putChild("schedules", WebSchedules()) self.putChild("admin", WebAdmin()) self.putChild("archive", WebArchive()) self.putChild("list", WebListUsers()) self.putChild("tutor", WebTutor()) self.putChild("tutor_info", WebTutorInfo()) self.putChild("tutor_data", WebTutorData()) self.putChild("tutor_sessions", WebTutorSessions()) self.putChild("client", WebClient()) self.putChild("report", WebClientReport()) self.putChild("mail", WebSendMail()) self.putChild("my_pupils", WebMyPupils()) self.putChild("my_pupils_info", WebMyPupilsInfo()) self.putChild("pupil_edit", WebPupilEdit()) self.putChild("new_pupil", WebPupilInsert()) self.putChild("pc_arrange", WebPCArrangeRoot()) self.putChild("editadmin", WebEditAdmin()) def getChild(self, path, request): if path in ('', 'index.html', 'index'): return self else: return static.File.childNotFound def render_GET(self, request): #verifico el parametro get por si hay que borrar una clase. keys = request.args.keys() if "del" in keys: d = defer.maybeDeferred(lambda: None) alumno = request.getSession().userId erase = DBDelete(self.db) clase = int(request.args['del'][0]) d.addCallback(lambda a: erase.deletePA(clase, alumno)) #borramos la cosa. #falta imprimir mensaje de operacion correcta #como llego a la funcion de internacionalizacion? #d.addCallback(lambda a: request.write('<div class="message">' + \ # _('La clase se ha cancelado correctamente') \ # + '</div>')) d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.writeWelcomeMessage, request) return server.NOT_DONE_YET def writeWelcomeMessage(self, trans, request): _ = trans session = request.getSession() request.write(self.template.startPage(session, \ _('Beppo - Sistema de educacion a distancia'))) d = defer.maybeDeferred(lambda: None) if hasattr(session, 'username'): d.addCallback(lambda a: self.template.homePageContent(session)) d.addCallback(request.write) d.addCallback(lambda a: self.template.commonInfo(trans)) d.addCallback(request.write) else: d.addCallback(lambda a: request.write('<h1>' + _('Bienvenido!') \ + '</h1> <p>' + \ _('Aqui podra conocer todas las ventajas de utilizar el sistema Beppo, y lo intentaremos convencer de que lo compre.') + '</p>')) d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d
class WebSendMail(Resource): fields = [{'name': 'subject', 'maxlength': 255}, {'name': 'body', 'maxlength': 64000}, {'name': 'username', 'maxlength': 255}, {'name': 'user_id', 'maxlength': 255}] def __init__(self): self.db = DBConnect() self.template = WebTemplates() self.render_POST = self.render_GET Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound #Formulario para mandar mail con sugerencias, bugs, etc def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, _('Criticas y sugerencias'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema msg = """<h2>""" + _('Criticas y sugerencias') + """</h2>""" \ + _('Desde aqui puede mandar sus criticas, sugerencias y comentarios.') + " " \ + _('La comunicacion se realizara mediante la casilla de mail con la cual se ha registrado.') if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) else: # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, msg) # 2) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def checkRequest(self, d, request): session = request.getSession() _ = session._ args = dict([(i, request.args[i][0]) for i in request.args.keys()]) if "submit" in request.args.keys(): for value in self.fields: if value['name'] not in args.keys(): args[value['name']] = '' d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Falta el argumento \'%s\'') % value['name']))) elif len(args[value['name']]) > value['maxlength']: args[value['name']] = args[value['name']][:value['maxlength']] d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Longitud excesiva del argumento \'%s\'') % value['name']))) return args def printContent(self, request, d, page): session = request.getSession() args = self.checkRequest(d, request) user_id = session.userId query = "select username, id, email from person where id = %d" d.addCallback(lambda a: self.db.db.runQuery(query, (user_id,))) d.addCallback(self.mail, args, request, page) return d def mail(self, rows, args, request, page): session = request.getSession() _ = session._ if len(rows) == 1: if "submit" in args.keys(): if args['body'] != "": subject = "[%s][%s] %s" % (rows[0][1], rows[0][0], args['subject']) msg = MIMEText(args['body'], _charset='utf-8') msg['Subject'] = Header(subject, 'utf-8') msg['From'] = rows[0][2] msg['To'] = MAIL_TO try: s = smtplib.SMTP(host = MAIL_HOST, port = MAIL_PORT) s.sendmail(MAIL_FROM, [msg['To']], msg.as_string()) except: request.write(self.template.serverError(session, \ _('Error al intentar establecer la comunicacion'))) else: s.close() request.write("""<div class="message"><h2>""" + \ _('Mail enviado correctamente') + """</h2>""" + \ _('Agradecemos su colaboracion') + """</div>""") else: request.write(self.template.unexpectedArguments(session, \ _('El texto del mail no debe ser vacio'))) else: request.write(self.template.unexpectedArguments(session, \ _('El usuario no existe en el sistema'))) request.write(page) self.printForm(rows[0], request) def printForm(self, row, request): _ = request.getSession()._ self.printCheckArgs(request) username = row[0] user_id = str(row[1]) email = row[2] string = """ <form action='' method='post' onsubmit='return check_args(this)'><p> """ + \ _('eMail') + """: %s""" % (email,) + """ </p><div><label for='subject'> """ + _('Asunto') + """: <input type='text' id='subject' name='subject' size='20' maxlength='255'/></label><br/> <label for='body'>""" + _('Texto') + """: <br/> <textarea name='body' rows='15' cols='40' id='body'></textarea></label><br/> <input type='hidden' name='user_id' value='%s'/>""" % (user_id,) + """ <input type='hidden' name='username' value='%s'/>""" % (username,) + """ <input type='submit' id='submit' name='submit' value=\'""" + _('Enviar') + """ \'/> </div></form>""" request.write(string) return def printCheckArgs(self, request): _ = request.getSession()._ page = """ <script type=\"text/javascript\">\n function check_args(form){ message=''; cont = true; if(form.body.value == ""){ message += \"- """ + _('El texto es obligatorio') + """\\n\";\n } if(message){ alert(\"""" + _('Error en el ingreso de datos:') + """\\n\" + message); return false; }else{ if(form.subject.value == ""){ cont = confirm(\"""" + _('Enviar el mensaje sin asunto?') + """\"); } if(!cont){ return false; }else{ return true; } } } </script> """ request.write(page) return
class WebSchedules(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # Si estamos autenticados como admin, sirve para modificar los horarios de cualquier tutor. # Si somos tutor, sirve para modificar solo los propios. def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, _('Modificacion de horarios'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: # 2.1) Admin debe proveer el argumento user_id if "user_id" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) msg = """<h2>""" + _('Administracion de horarios') + """</h2>""" + _('Selecciona las horas en las que el tutor se encuentra disponible.') # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, _('falta el parametro user_id'))) # 3) Si es Tutor, administra sus propios horarios elif session.kind == TUTOR: user_id = session.userId msg = """<h2>""" + _('Seleccion de horarios') + """</h2>""" + _('Indica los horarios (en tu hora local) en los que te encuentras disponible.') # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id, msg) else: # 4) Si no es ni ni Admin, ni Tutor, ni nadie, es alguien que no está # autorizado a administrar horarios request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d, userId, msg): # 1) Si se envían datos, se actualiza la base primero. # La actualizacion consiste en eliminar todos los horarios previos, # hace el packSchedule, e insertar los nuevos horarios. _ = request.getSession()._ if "submit" in request.args.keys(): op = "delete from tutor_schedule where fk_tutor = %d" d.addCallback(lambda a: self.db.db.runOperation(op, (userId, ))) d.addCallback(lambda a: self.packSchedule(request.args.get('sch', []), str(INSTANT), userId)) #instants = self.packSchedule(request.args.get('sch', []), str(INSTANT), userId) d.addCallback(self.addSched, userId,INSTANT) d.addCallback(lambda a: self.packSchedule(request.args.get('sch', []), str(PRECOORD), userId)) d.addCallback(self.addSched, userId,PRECOORD) d.addCallback(lambda a: request.write("""<div class="message"><h2>""" + _('Cambios guardados.') + """</h2>""" + _('Se guardaron los cambios correctamente') + """</div>""")) # 2) Se imprime un mensaje de bienvenida configurable d.addCallback(lambda a: request.write(msg)) # 3) Se buscan los datos nuevos en la base d.addCallback(self.requestScheduleData, userId) # 4) Se imprime un formulario con los datos actualizados d.addCallback(self.printForm, request, userId) return d def addSched(self, tipoH, userId,TIPO): for sched in tipoH: self.addSchedule(userId, sched, TIPO) return None def packSchedule(self, checks, kind, userId): try: # Mapeamos a integer y filtramos valores inadecuados checks = [int(chk[:-2]) for chk in checks if chk[-1] == kind] except ValueError: return [] checks.sort() scheds = [] last_hour = None start_time = None end_time = None for hour in checks: if last_hour is None: start_time = hour elif last_hour < hour - 1: scheds.append((start_time, end_time)) start_time = hour last_hour = hour end_time = hour + 1 # Falta el último span, que lo agregamos ahora: if end_time is not None: if end_time == LASTDAY_MIDNIGHT: if start_time == 0: # Este tipo labura 24/7! scheds.append((0, end_time)) elif len(scheds) > 0 and scheds[0][0] == 0: # El horario abarca las 0 del domingo scheds.append((start_time, end_time + scheds[0][1])) del(scheds[0]) else: scheds.append((start_time, end_time)) else: scheds.append((start_time, end_time)) # Convertimos a DateTime d = self.queryOffset(userId) d.addCallback(self.getSpans, scheds) return d def getSpans(self, rows, scheds): spans = [] # Elegimos mayo del 2005 porque el 1ero cae domingo. #creamos la fecha considerando el timezone mktimestamp = lambda x: DateTime(2005, 5, 1 + x / 48, (x % 48) / 2, (x % 2) * 30) - DateTimeDelta(0,rows[0][0]) for sched in scheds: spans.append((mktimestamp(sched[0]), mktimestamp(sched[1]))) return spans def unpackSchedule(self, rows): checks = [''] * LASTDAY_MIDNIGHT for row in rows: start_check = row[0] * 48 + row[1] * 2 + row[2] / 30 end_check = row[3] * 48 + row[4] * 2 + row[5] / 30 if end_check <= start_check: end_check += LASTDAY_MIDNIGHT for hour in range(start_check, end_check): checks[hour % LASTDAY_MIDNIGHT] = str(row[6]) return checks def requestScheduleData(self, data, userId): d = self.queryOffset(userId) d.addCallback(self.addOffset, data, userId) return d #VER refactoring de estos metodos! #resolver el gmtoffset directamente en una consulta # ver WebGetUserInfo para ejemplo def queryOffset(self, userId): query1 = 'select timezone.gmtoffset from timezone, person where \ timezone.id = person.fk_timezone and person.id = %d' return self.db.db.runQuery(query1, (userId, )) def addOffset(self, rows, request, userId): if rows[0][0] >= 0: query = "select extract(dow from time_start + interval '%i hour' ), \ extract(hour from time_start + interval '%i hour'), \ extract(minute from time_start + interval '%i hour'), \ extract(dow from time_end + interval '%i hour'), \ extract(hour from time_end + interval '%i hour'), \ extract(minute from time_end + interval '%i hour'), schedule_type \ from tutor_schedule where fk_tutor = %d" else: query = "select extract(dow from time_start - interval '%i hour' ), \ extract(hour from time_start - interval '%i hour'), \ extract(minute from time_start - interval '%i hour'), \ extract(dow from time_end - interval '%i hour'), \ extract(hour from time_end - interval '%i hour'), \ extract(minute from time_end - interval '%i hour'), schedule_type \ from tutor_schedule where fk_tutor = %d" of = abs(rows[0][0]) print "offset = %i" % of return self.db.db.runQuery(query, (of,of,of,of,of,of,userId,)) def printForm(self, rows, request, userId): _ = request.getSession()._ checks = self.unpackSchedule(rows) days = [_('Domingo'), _('Lunes'), _('Martes'), _('Miercoles'), _('Jueves'), _('Viernes'), _('Sabado')] classes={'': 'sch_unchecked', '1': 'sch_instant', '2': 'sch_precoord'} titles={'': _('No disponible'), '1': _('Disponible para acceso instantaneo'), '2': _('Disponible para clases precoordinadas')} string = """ <script type="text/javascript"> <!-- function change_cell (tag) { var classes=new Array(); classes[''] = 'sch_unchecked'; classes['1'] = 'sch_instant'; classes['2'] = 'sch_precoord'; var titles = new Array(); titles[''] = '""" + _('No disponible') + """'; titles['1'] = '""" + _('Disponible para acceso instantaneo') + """'; titles['2'] = '""" + _('Disponible para clases precoordinadas') + """'; var input = tag.getElementsByTagName('input')[0]; if (!input) return; parts = input.value.split('a'); var sel = document.getElementById('sch_kind'); if (!sel) return; opts = sel.getElementsByTagName('input'); if (opts[0].checked) { var opt = '1' } else if (opts[1].checked) { var opt = '2' } else { alert('""" + _('No ha seleccionado un tipo de horario!') + """'); var opt = ''; } if (parts[1] == opt) { opt = '' } input.value = parts[0] + 'a' + opt; tag.className = classes[opt]; tag.title = titles[opt]; } --> </script> <form action="" method="get"> <fieldset class="sched" id="sch_kind"> <legend>""" + _('Tipo de horarios') + """</legend> <p class="sch_instant"><label for="instant"><input id="instant" type="radio" name="kind" value="1" checked="checked" /> """ + _('Acceso instantaneo') + """</label></p> <p class="sch_precoord"><label for="precoord"><input id="precoord" type="radio" name="kind" value="2" /> """ + _('Clases precoordinadas') + """</label></p> </fieldset> </form> <form action="" method="get"> <div> <table id="schedule"> <tr> <th></th> """ for day in days: string += '<th class="sch_header">%s</th>\n' % day for hour in range(48): string += '</tr><tr>\n<td class="sch_row">%d:%02dhs</td>\n' % (hour / 2, (hour % 2) * 30) for day in enumerate(days): pos = 48 * day[0] + hour val = checks[pos] string += '<td class="%s" title="%s" onclick="change_cell(this)"><input type="text" name="sch" value="%da%s" /></td>\n' % (classes[val], titles[val], pos, val) string += """ </tr><tr><td class="sch_row">24:00hs</td>\n</tr></table> <input type="hidden" name="user_id" value="%d"/> <input type="submit" name="submit" value=\"""" % userId + _('Enviar') + """\" /> </div> </form> """ request.write(string) return def addSchedule(self,userId, sched, kind): operation = "insert into tutor_schedule \ (fk_tutor, time_start, time_end, schedule_type) \ values (%d, %s, %s, %d)" return self.db.db.runOperation(operation, (userId, str(sched[0]), str(sched[1]), kind))
class WebPCArrangeCommon(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) # Si estamos autenticados como admin, sirve para coordinar clases para cualquier alumno. # Si somos alumno, sirve para coordinar clases propias. def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans msg = '<div id="pchelp"><h3>' + _('Pasos para precoordinar una clase') + \ '</h3><ol class="steps"><li class="one">' + _('Elige la materia') + \ '</li><li class="two">' + _('Elige el tutor') + '</li><li class="three">' + \ _('Elige el horario') + '</li></ol></div>\n' msg = msg + self.stepMessage(session) # 0) Se empieza la página request.write(self.template.startPage(session, _('Modificacion de horarios'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: # 2.1) Admin debe proveer el argumento user_id if "user_id" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, _('falta el parametro user_id'))) # 3) Si es Pupil, coordina sus propias clases elif session.kind == PUPIL: user_id = session.userId # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id, msg) else: # 4) Si no es ni ni Admin, ni Pupil, ni nadie, es alguien que no está # autorizado a administrar horarios request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def packSchedule(self, checks): try: # Mapeamos a integer y filtramos valores inadecuados checks = [int(chk) for chk in checks] except ValueError: return [] checks.sort() scheds = [] last_hour = None start_time = None end_time = None for hour in checks: if last_hour is None: start_time = hour elif last_hour < hour - 1: scheds.append((start_time, end_time)) start_time = hour last_hour = hour end_time = hour + 1 # Falta el último span, que lo agregamos ahora: if end_time is not None: if end_time == LASTDAY_MIDNIGHT: if start_time == 0: # Este tipo labura 24/7! scheds.append((0, end_time)) elif len(scheds) > 0 and scheds[0][0] == 0: # El horario abarca las 0 del domingo scheds.append((start_time, end_time + scheds[0][1])) del(scheds[0]) else: scheds.append((start_time, end_time)) else: scheds.append((start_time, end_time)) # Convertimos a DateTime spans = [] base = today() + 3 def mktimestamp(x): day = base + x / 48 #VER #incluir DateTimeDelta del userId return DateTime(day.year, day.month, day.day, (x % 48) / 2, (x % 2) * 30) for sched in scheds: spans.append((mktimestamp(sched[0]), mktimestamp(sched[1]))) return spans def scheduleDescription(self, scheds, request, withDay): session = request.getSession() _ = session._ days = [_('lunes'), _('martes'), _('miercoles'), _('jueves'), _('viernes'), _('sabado'), _('domingo')] desc = '' for sch in scheds: if sch[0].day == sch[1].day: if withDay: desc += days[sch[0].day_of_week] + ' ' + sch[0].strftime("%d-%m-%Y") + \ ', ' + _('de') + ' ' + sch[0].strftime('%H:%M') + \ ' ' + _('a') + ' ' + sch[1].strftime('%H:%M') else: desc += days[sch[0].day_of_week] + ' ' + _('de') + ' ' + \ sch[0].strftime('%H:%M') + ' ' + _('a') + ' ' + \ sch[1].strftime('%H:%M') else: if withDay: desc += _('de') + ' ' + days[sch[0].day_of_week] + ' ' + \ sch[0].strftime('%d-%m-%Y, %H:%M') + ' ' + _('a') + \ ' ' + days[sch[1].day_of_week] + ' ' + \ sch[1].strftime('%d-%m-%Y, %H:%M') else: desc += _('de') + ' ' + days[sch[0].day_of_week] + ' ' + \ sch[0].strftime('%H:%M') + ' ' + _('a') + ' ' + \ days[sch[1].day_of_week] + ' ' + sch[1].strftime('%H:%M') desc += '<br />' return desc
class WebTutorSessions(Resource): _ = dummyTranslator typeToString = {IACLASS: _('Acceso Instantaneo'), PACLASS: _('Clase Precoordinada'), WAITING: _('En espera'), OFFLINE_QUESTION: _('Pregunta offline'), EXTRA_IACLASS: _('AI (Fuera de turno)'), EXTRA_WAITING: _('Espera (Fuera de turno)'), DECIDING: _('Analizando pregunta'), ABSENT: _('Ausente'), POST_PROCESS: _('Postprocesado')}.get typeToStyle = {IACLASS: "ia_row", PACLASS: "pc_row", WAITING: "waiting_row", OFFLINE_QUESTION: "offline_row", EXTRA_IACLASS: "extra_ia_row", EXTRA_WAITING: "extra_waiting_row", DECIDING: "deciding_row", ABSENT: "absent_row", POST_PROCESS: "postprocess_row"}.get eCodeToString = {NORMAL: _('Fin horario'), TUTOR_ENTER: _('Arribo'), PUPIL_ENTER: _('Entrada de alumno'), TUTOR_END: _('Terminada por Tutor'), PUPIL_END: _('Terminada por alumno'), TUTOR_QUIT: _('Desconexion Tutor'), SERVER_RESTART: _('Reconexion servidor'), QUESTION_ANSWERED: _('Pregunta contestada'), QUESTION_NOT_ANSWERED: _('Pregunta no contestada'), ACCEPTED: _('Pregunta aceptada'), REJECTED: _('Pregunta no aceptada'), CORRECTED: _('Postprocesado'), NOT_CORRECTED: _('No postprocesado'), None: '-'}.get def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # Si estamos autenticados como admin, sirve para modificar las # materias de cualquier tutor. # Si somos tutor, sirve para modificar solo los propios. def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, \ _('Historial de sesiones del tutor'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: if "user_id" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) msg = '<h2>' + _('Sesiones del tutor') + '</h2>' # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, \ _('falta el parametro user_id'))) # 3) Si es Tutor, ve sus propias sesiones elif session.kind == TUTOR: user_id = session.userId msg = '<h2>' + _('Tus sesiones') + '</h2>' + \ _('Este es el detalle de tus sesiones en el sistema:') + '<br/>' # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id, msg) else: # 4) Si no es ni ni Admin, ni Tutor, ni nadie, es alguien que no está # autorizado a administrar horarios request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d, user_id, msg): """Consulta las sesiones del tutor user_id en la base de datos y las manda a imprimir """ try: pag = int(request.args['pag'][0]) except: pag = 0 d.addCallback(lambda a: request.write(msg)) now = DateTime.now() query = """select s.session_type, s.time_start, s.time_end, s.error_code, \ p.username, p.id, (select count(*) from session s left join person p on (p.id = s.fk_pupil) \ where fk_tutor = %d and s.time_end < '%s') from session s left join person p on (p.id = s.fk_pupil) \ where fk_tutor = %d and s.time_end < '%s' order by time_start desc LIMIT %d OFFSET %d""" d.addCallback(lambda a: self.db.db.runQuery(query, (user_id, now,user_id, now,ITEMS_PAG, ITEMS_PAG*pag))) d.addCallback(self.printData, request, pag) return d def printData(self, rows, request,pag): _ = request.getSession()._ if len(rows) == 0: string = _('No se registran sesiones') + '<br/>' def paginacion(): pass else: total = rows[0][-1:][0] #la ultima columna es el total de datos para la consulta try: user_id = int(request.args['user_id'][0]) except: pass def paginacion(): actual = pag if total > ITEMS_PAG: request.write('<div style="text-align: left;"> <strong>' + _('Página:') + '</strong>') for pagina in range(int(total/ITEMS_PAG)+1): tip = "href" if pagina == actual: tip = "id" link = "<a %s='/tutor_sessions?user_id=%d&pag=%d'>%d</a> " % (tip,user_id,pagina,pagina+1) request.write(link) request.write('</div><br />') if total < ITEMS_PAG: lim = total else: lim = ITEMS_PAG string = _('Mostrando %d a %d de %d sesiones:') % (ITEMS_PAG*pag+1, lim*(pag+1), total) string += """ <table class="table_list" id="sessions"> <tr> <th class="header_list">""" + _('Tipo de sesion') + """</th> <th class="header_list">""" + _('Comienzo') + """</th> <th class="header_list">""" + _('Fin') + """</th> <th class="header_list">""" + _('Duracion') + """</th> <th class="header_list">""" + _('Razon cierre') + """</th> <th class="header_list">""" + _('Alumno') + """</th> </tr> """ for row in rows: session_type = _(self.typeToString(row[0], '')) style = _(self.typeToStyle(row[0])) start = row[1].Format(DATETIME_FORMAT) end = row[2].Format(DATETIME_FORMAT) diff = self.dateDiffFormat(row[2] - row[1]) pupil = (row[4] is not None) and row[4] or "" pupil_id = (row[5] is not None) and row[5] or "" reason = _(self.eCodeToString(row[3], '-')) string += """ <tr class="%s"> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td> <a href="/userinfo?user_id=%s&kind=%d"> %s </a> </td> </tr>""" % (style, session_type, start, end, diff, reason, pupil_id, PUPIL, pupil) string += """</table>""" request.write(string) paginacion() return def dateDiffFormat(self, date): hours = int(date.hours) minutes = int(date.minutes) seconds = int(date.seconds) return "%02d:%02d:%02d" % (hours, minutes % 60, seconds % 60)
class WebMyPupils(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # Si estamos autenticados como admin, sirve para ver los alumnos de cualquier cliente # Si somos cliente, sólo podremos ver los propios def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, \ _('Informacion de cuentas de usuarios'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema msg = """<h2>""" + _('Cuentas de alumnos') + """</h2>""" if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: # 2.1) Admin debe proveer el argumento user_id if "user_id" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, \ _('falta el parametro user_id'))) # 3) Si es cliente, muestra la información de alumnos propios elif session.kind == CLIENT: user_id = session.userId # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id) else: # 4) Si no, es alguien que no está autorizado request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d, userId): _ = request.getSession()._ # 2) Si se envían datos, se actualiza la base primero d.addCallback(lambda a: self.requestData(userId)) d.addCallback(self.printTitle, request) if "del" in request.args.keys(): try: to_delete = int(request.args["del"][0]) query3 = "select id from pupil where id = %d and fk_client = %d" d.addCallback(lambda a: self.db.db.runQuery(query3, (to_delete, userId))) d.addCallback(self.checkUser, userId, request) except ValueError: d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('user_id deberia ser entero')))) # 3) Se buscan los datos en la base query = "select c.ai_available, c.pc_available, count(p.id) \ from client c left join pupil p on (p.fk_client = c.id) \ where c.id = %d group by c.ai_available, c.pc_available" d.addCallback(lambda a: self.db.db.runQuery(query, (userId, ))) d.addCallback(self.printClientInfo, request) query2 = "select a.id, last_name, first_name, ai_available, ai_total, \ pc_available, pc_total, expires from person p, pupil a \ where p.id = a.id and fk_client = %d" d.addCallback(lambda a: self.db.db.runQuery(query2, (userId, ))) # 4) Se imprime los datos d.addCallback(self.printForm, request, userId) return d def checkUser(self, rows, userId, request): session = request.getSession() _ = session._ d = defer.maybeDeferred(lambda: None) if len(rows) != 1: d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('No es alumno del cliente')))) else: erase = DBDelete(self.db) to_delete = str(rows[0][0]) d.addCallback(lambda a: erase.deletePupil(to_delete)) d.addCallback(lambda a: request.write('<div class="message">' + \ _('El usuario ha sido borrado correctamente') + '</div>')) return d def requestData(self, userId): query = "select p.first_name, p.last_name, c.organization \ from person p, client c where c.id = p.id and p.id = %s" d = self.db.db.runQuery(query, (str(userId),)) return d def printTitle(self, data, request): _ = request.getSession()._ if len(data) == 1: client = "%s %s (%s)" % (data[0][0], data[0][1], data[0][2]) msg = """<h2>""" + _('Cuentas de alumnos de %s') % client + """</h2>""" else: msg = """<h2>""" + _('Cuentas de alumnos') + """</h2>""" request.write(msg) return def printForm(self, rows, request, userId): """ recibimos [(first_name, last_name, ai_total, pc_total, ai_available, pc_available, expires)] """ session = request.getSession() _ = session._ string = "" if len(rows) != 0: taia = tait = tpca = tpct = 0 string += """ <script type="text/javascript"> function del_confirm(pupil){ return confirm(\"""" + _('Esta seguro de borrar el alumno') + """ \"+pupil+"?"); } </script> """ string += """<br/> <table class="table_list" id="pupil_info"> <tr> <th class="icon_list"></th> <th class="icon_list"></th> <th class="header_list">""" + _('Alumno') + """</th> <th class="header_list">""" + _('Horas AI (restan/total)') + """</th> <th class="header_list">""" + _('Horas PC (restan/total)') + """</th> <th class="header_list">""" + _('Vencimiento') + """</th> </tr> """ for r in rows: aia = self.getFloatFormat(r[3]) ait = self.getFloatFormat(r[4]) pca = self.getFloatFormat(r[5]) pct = self.getFloatFormat(r[6]) taia += aia tait += ait tpca += pca tpct += pct link = (session.kind == ADMIN) and "&user_id=%s" % (str(userId),) or "" string += """ <tr class="row_list"> <td><a href="pupil_edit?pupil_id=%s%s" class="link_image"><img src="/static/graphics/modify.gif" width="16" height="16" alt=\"""" % (r[0], link) + \ _('Modificar') + """\" title=\"""" + _('Modificar') + """\"/></a></td> <td><a href="?del=%s%s" class="link_image" onclick="return del_confirm('%s')"><img src="/static/graphics/delete.gif" width="16" height="16" alt=\"""" % (r[0], link, r[2] + " " + r[1]) + _('Borrar alumno') + """\" title=\"""" + _('Borrar alumno') + """\"/></a></td> <td><a href="/userinfo?user_id=%s&kind=%d">%s, %s</a></td> <td>%.1f/%.1f</td> <td>%.1f/%.1f</td> <td>%s</td> </tr> """ % (r[0], PUPIL, r[1], r[2], aia, ait, pca, pct, self.getDateFormat(r[7])) string += """ <tr> <td class="last_row"></td> <td class="last_row"></td> <td class="last_row">Total</td> <td class="last_row">%.1f/%.1f</td> <td class="last_row">%.1f/%.1f</td> <td class="last_row"></td> </tr> </table>""" % (taia, tait, tpca, tpct) user = (session.kind == ADMIN) and "?user_id=" + str(userId) or "" string += "<a href='/new_pupil%s'>" % user + _('Agregar alumnos') + "</a>" string += "<a href='javascript:history.back()' id='back'>" + _('Volver') + "</a>" request.write(string) return def printClientInfo(self, rows, request): _ = request.getSession()._ fields = [{'pos': 0, 'desc': _('Horas AI disponibles')}, {'pos': 1, 'desc': _('Horas CP disponibles')}, {'pos': 2, 'desc': _('Cantidad de alumnos')}] if len(rows) != 1: string = '<div class="message">' + _('No se registran datos para el usuario') \ + '</div>' else: string = '<div class="client_info">' + \ _('Informacion de alumnos y horas:') + '<ul>' for row in rows: for i in fields: string += '<li><b>' + i['desc'] + ': </b>' + str(row[i['pos']]) \ + '</li>' string += '</ul></div>' request.write(string) return def getFloatFormat(self, value): """esta puede eliminarse cuando la base de datos ponga valores por defecto a ai_available y pc_available""" return (value != None) and value or 0.0 def getDateFormat(self, value): """esta puede eliminarse cuando la base de datos ponga valores por defecto a expires""" return (value != None) and value.Format(DATETIME_FORMAT) or "-"
class WebSubjects(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # Si estamos autenticados como admin, sirve para modificar las materias de cualquier tutor. # Si somos tutor, sirve para modificar solo los propios. def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, _('Modificacion de materias'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: # 2.1) Admin debe proveer el argumento user_id if "user_id" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) msg = '<h2>' + _('Administracion de materias') + '</h2>' + \ _('Selecciona las materias que el tutor sepa ensenar, para actualizar los datos en el sistema.') # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, \ _('falta el parametro user_id'))) # 3) Si es Tutor, administra sus propias materias elif session.kind == TUTOR: user_id = session.userId msg = '<h2>' + _('Seleccion de materias') + '</h2>' + \ _('Selecciona las materias que sepas ensenar, para actualizar tus datos en el sistema.') # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id, msg) else: # 4) Si no es ni ni Admin, ni Tutor, ni nadie, es alguien que no está # autorizado a administrar materias request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d, userId, msg): _ = request.getSession()._ # 1) Si se envían datos, se actualiza la base primero if "submit" in request.args.keys(): op = "delete from tutor_subject where fk_tutor = %d" d.addCallback(lambda a: self.db.db.runOperation(op, (userId, ))) for sbj in request.args.get('sbj', []): try: sbj = int(sbj) d.addCallback(self.addSubject, userId, sbj) except ValueError: # Alguien editó la url a mano? d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, + \ _('sbj deberia tomar valores enteros.')))) d.addCallback(lambda a: request.write('<div class="message"><h2>' + \ _('Cambios guardados.') + '</h2>' + \ _('Se guardaron los cambios correctamente') + '</div>')) # 2) Se imprime un mensaje de bienvenida configurable d.addCallback(lambda a: request.write(msg)) # 3) Se buscan los datos nuevos en la base d.addCallback(self.requestSubjectData, userId) # 4) Se imprime un formulario con los datos actualizados d.addCallback(self.printForm, request, userId) return d def requestSubjectData(self, data, userId): query = 'select s.id, s.name, t.fk_tutor from subject as s \ left join tutor_subject as t on (t.fk_subject = s.id \ and t.fk_tutor = %d)' return self.db.db.runQuery(query, (userId,)) def printForm(self, rows, request, userId): _ = request.getSession()._ string = """<form action="" method="GET"> <select id="sbj" name="sbj" size="%d" multiple="multiple">""" % len(rows) for sbj in rows: selected = '' if sbj[2] is not None: selected = ' selected="selected"' string += '<option value="%s" %s>%s</option>\n' % (sbj[0], selected, sbj[1]) string += """ </select> <input type="hidden" name="user_id" value="%d"/> <input type="submit" name="submit" value=\"""" % userId + _('Enviar') + """\"/> </form> """ request.write(string) return def addSubject(self, data, userId, sbj): operation = "insert into tutor_subject (id, fk_tutor, fk_subject) \ values (nextval('pk_seq_tutor_subject'), %d, %d)" return self.db.db.runOperation(operation, (userId, sbj))
class WebSchedules(Resource): def __init__(self, db): self.db = db self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # Si estamos autenticados como admin, sirve para modificar los horarios de cualquier tutor. # Si somos tutor, sirve para modificar solo los propios. def render_GET(self, request): session = request.getSession() _ = getTranslatorFromSession(session) # 0) Se empieza la página request.write(self.template.startPage(session, _('Modificacion de horarios'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: # 2.1) Admin debe proveer el argumento user_id if "user_id" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) msg = '<h2>' + _('Administracion de horarios') + '</h2>' + _('Selecciona las horarios de acceso instantaneo para el tutor.') # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, _('falta el parametro user_id'))) # 3) Si es Tutor, administra sus propios horarios elif session.kind == TUTOR: user_id = session.userId msg = '<h2>' + _('Seleccion de horarios') + '</h2>' + _('Selecciona los horarios en los que estas disponible para horas de acceso instantaneo.') # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id, msg) else: # 4) Si no es ni ni Admin, ni Tutor, ni nadie, es alguien que no está # autorizado a administrar horarios request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return server.NOT_DONE_YET def printContent(self, request, d, userId, msg): # 1) Si se envían datos, se actualiza la base primero _ = request.getSession()._ if "submit" in request.args.keys(): op = "delete from tutor_schedule where fk_tutor = %d" d.addCallback(lambda a: self.db.db.runOperation(op, (userId, ))) instant = self.packSchedule(request.args.get('sched_ai', [])) for sched in instant: d.addCallback(self.addSchedule, userId, sched, INSTANT) precoord = self.packSchedule(request.args.get('sched_pc', [])) for sched in precoord: d.addCallback(self.addSchedule, userId, sched, PRECOORD) d.addCallback(lambda a: request.write('<div class="message"><h2>' + _('Cambios guardados.') + '</h2>' + _('Se guardaron los cambios correctamente') + '</div>')) # 2) Se imprime un mensaje de bienvenida configurable d.addCallback(lambda a: request.write(msg)) # 3) Se buscan los datos nuevos en la base d.addCallback(self.requestScheduleData, userId) # 4) Se imprime un formulario con los datos actualizados d.addCallback(self.printForm, request, userId) return d def packSchedule(self, checks): try: # Mapeamos a integer y filtramos valores inadecuados checks = filter(lambda x: 0 <= x and x < LASTDAY_MIDNIGHT, map(int, checks)) except ValueError: return [] checks.sort() scheds = [] last_hour = None start_time = None end_time = None for hour in checks: if last_hour is None: start_time = hour elif last_hour < hour - 1: scheds.append((start_time, end_time)) start_time = hour last_hour = hour end_time = hour + 1 # Falta el último span, que lo agregamos ahora: if end_time is not None: if end_time == LASTDAY_MIDNIGHT: if start_time == 0: # Este tipo labura 24/7! scheds.append((0, end_time)) elif len(scheds) > 0 and scheds[0][0] == 0: # El horario abarca las 0 del domingo scheds.append((start_time, end_time + scheds[0][1])) del(scheds[0]) else: scheds.append((start_time, end_time)) else: scheds.append((start_time, end_time)) # Convertimos a DateTime spans = [] # Elejimos mayo del 2005 porque el 1ero cae domingo. mktimestamp = lambda x: DateTime(2005, 5, 1 + x / 24, x % 24) for sched in scheds: spans.append((mktimestamp(sched[0]), mktimestamp(sched[1]))) return spans def unpackSchedule(self, rows): checks = {} checks['ai'] = [False] * LASTDAY_MIDNIGHT checks['pc'] = [False] * LASTDAY_MIDNIGHT for row in rows: start_check = row[0] * 24 + row[1] end_check = row[2] * 24 + row[3] if end_check < start_check: end_check += LASTDAY_MIDNIGHT for hour in range(start_check, end_check): if row[4] == INSTANT: checks['ai'][hour % LASTDAY_MIDNIGHT] = True elif row[4] == PRECOORD: checks['pc'][hour % LASTDAY_MIDNIGHT] = True return checks def requestScheduleData(self, data, userId): return self.db.db.runQuery('select extract(dow from time_start), extract(hour from time_start), extract(dow from time_end), extract(hour from time_end), schedule_type from tutor_schedule where fk_tutor = %d', (userId,)) def printForm(self, rows, request, userId): _ = request.getSession()._ checks = self.unpackSchedule(rows) days = [_('Domingo'), _('Lunes'), _('Martes'), _('Miercoles'), _('Jueves'), _('Viernes'), _('Sabado')] string = """ <script> <!-- function change_cell (tag) { input = tag.getElementsByTagName('input')[0] if (!input) return; input.checked = ! input.checked; if (input.checked) { var other = tag.id.substring(0, 6) + (((tag.id[6] * 1) + 1) % 2); other = document.getElementById(other); input = other.getElementsByTagName('input')[0] input.checked = false; other.className = other.className.substring(0, 7) + 'unchecked'; other.title = '""" + _('No disponible') + """'; var style = tag.className.substring(0, 7) + "checked"; var tit = '""" + _('Disponible') + """'; } else { var style = tag.className.substring(0, 7) + "unchecked"; var tit = '""" + _('No disponible') + """'; } tag.className = style; tag.title = tit; } --> </script> <form action="" method="GET"> <fieldset class="sched"> <legend>""" + _('Tipo de horarios') + """</legend> <p class="sch_instant">""" + _('Acceso instantaneo') + """</p> <p class="sch_precoord">""" + _('Clases Precoordinadas') + """</p> </fieldset> </form> <form action="" method="GET"> <table id="schedule"> <tr> <th></th> """ for day in days: string += '<th colspan="2">%s</th>\n' % day string += '\n</tr><tr><th></th>\n' for day in days: string += '<th>AI</th><th>PC</th>\n' for hour in range(24): string += '</tr><tr>\n<td class="sch_row">%dhs</td>\n' % hour for day in enumerate(days): check = 24 * day[0] + hour for sufix, kind in enumerate(('ai', 'pc')): if checks[kind][check]: string += """<td id="sch%03d%d" class="sch_%s_checked" title=" """ %(check, sufix, kind) + _('Disponible') + """ " onmousedown="change_cell(this)"><input type="checkbox" name="sched_%s" value="%d" checked="checked"/></td>\n""" % (kind, check) else: string += """<td id="sch%03d%d" class="sch_%s_unchecked" title=" """ % (check, sufix, kind) + _('No disponible') + """ " onmousedown="change_cell(this)"><input type="checkbox" name="sched_%s" value="%d" /></td>\n""" % (kind, check) string += """ </tr><tr><td class="sch_row">24hs</td>\n</tr></table> <input type="hidden" name="user_id" value="%d"/> <input type="submit" name="submit" value=""" % userId + _('Enviar') + """/> </form> """ request.write(string) return def addSchedule(self, data, userId, sched, kind): return self.db.db.runOperation("insert into tutor_schedule (fk_tutor, time_start, time_end, schedule_type) values (%d, %s, %s, %d)", (userId, str(sched[0]), str(sched[1]), kind))
class WebPupilInsert(Resource): def __init__(self): _ = dummyTranslator self.fields = [{'name': 'username', 'pos': 1, 'desc': _('Nombre de usuario'), \ 'required': True, 'type': 'text', 'maxlength': 80, 'query': "person"}, {'name': 'password', 'pos': 2, 'desc': _('Contrasena'), 'required': True, \ 'type': 'password', 'maxlength': 80, 'query': "person"}, {'name': 'password2', 'pos': 2, 'desc': _('Repita contrasena'), 'required': True, \ 'type': 'password', 'maxlength': 80, 'query': ""}, {'name': 'first_name', 'pos': 3, 'desc': _('Nombre'), 'required': True, \ 'type': 'text', 'maxlength': 255, 'query': "person"}, {'name': 'last_name', 'pos': 4, 'desc': _('Apellido'), 'required': True, \ 'type': 'text', 'maxlength': 255, 'query': "person"}, {'name': 'email', 'pos': 5, 'desc': _('eMail'), 'required': True, \ 'type': 'text', 'maxlength': 255, 'query': "person"}, {'name': 'ai_total', 'pos': 6, 'desc': _('Horas de AI'), 'required': True, \ 'type': 'text', 'maxlength': 255, 'query': "pupil"}, {'name': 'pc_total', 'pos': 7, 'desc': _('Horas de CP'), 'required': True, \ 'type': 'text', 'maxlength': 255, 'query': "pupil"}] self.db = DBConnect() self.render_POST = self.render_GET self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans request.write(self.template.startPage(session, _('Pagina del Alumno'))) d = defer.maybeDeferred(lambda :None) msg = '<h2>' + _('Nuevo alumno') + '</h2> ' + \ _('Recuerde que los campos indicados con <sup>*</sup> son obligatorios') if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) elif session.kind == ADMIN: if "user_id" in request.args.keys(): try: user_id = int(request.args.get('user_id', [-1])[0]) # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, \ _('Falta el argumento user_id'))) elif session.kind == CLIENT: user_id = session.userId # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id, msg) else: # 4) Si no es ni ni Admin, ni Cliente es alguien no autorizado a ver alumnos request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def checkRequest(self, d, request): session = request.getSession() _ = session._ args = dict([(i, request.args[i][0]) for i in request.args.keys()]) if "submit" in request.args.keys(): for value in self.fields: if value['name'] not in args.keys(): args[value['name']] = '' d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Falta el argumento \'%s\'') % value['name']))) elif len(args[value['name']]) > value['maxlength']: args[value['name']] = (args[value['name']][:value['maxlength']]) d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Longitud excesiva del argumento \'%s\'') % value['name']))) if args['password'] != args['password2']: request.write(self.template.unexpectedArguments(session, \ _('Las contrasenas no coinciden'))) if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", args['email']) == None: request.write(self.template.unexpectedArguments(session, \ _('El email ingresado es incorrecto'))) try: args['ai_total'] = float(args['ai_total']) args['pc_total'] = float(args['pc_total']) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('El argumento de Hora debe ser numerico'))) return args def printContent(self, request, d, userId, msg): _ = request.getSession()._ args = self.checkRequest(d, request) d.addCallback(lambda a: request.write(msg)) #chequeamos que el cliente exista query = "select ai_available, pc_available from client where id = %d" d.addCallback(lambda a: self.db.db.runQuery(query, (userId,))) d.addCallback(self._checkAndInsert, request, userId, args) d.addErrback(self.printError, request) d.addCallback(self.printForm, request, args, userId) def _printAvailable(self, row, request): _ = request.getSession()._ string = _('Detalle de horas disponibles:') + "<br/>" + \ "<ul id='client_info'><li>" + _('Horas AI disponibles:') + \ ' %.1f' % row[0][0] + "</li><li>" + _('Horas CP disponibles:') + \ ' %.1f' % row[0][1] + "</li></ul>" d = defer.maybeDeferred(lambda: request.write('<div class="client_info">' + \ string + '</div>') or row) d.addCallback(lambda a: row) return d def printError(self, failure, request): """Imprime el error de failure y genera una fila vacia para la consulta de la base de datos """ session = request.getSession() d = defer.maybeDeferred(lambda :None) d.addCallback(lambda a: request.write("""<div class="error"> %s </div>""" % \ failure.getErrorMessage())) d.addCallback(self.getEmptyRow, 8) return d def _checkAndInsert(self, rows, request, userId, args): _ = request.getSession()._ if len(rows) == 1: ai_available = rows[0][0] pc_available = rows[0][1] if 'submit' in request.args.keys(): username = QuotedString(args['username']) ai_asked = args['ai_total'] pc_asked = args['pc_total'] if (ai_asked <= ai_available and pc_asked <= pc_available): query = "select username from person where username = %s" d = self.db.db.runQuery(query, (username,)) d.addCallback(self._insertDB, request, userId, args) else: return failure.Failure(_('Ha solicitado mas horas de las que dispone')) else: d = defer.maybeDeferred(lambda: self.getEmptyRow(None, 8)) else: return failure.Failure(_('El cliente solicitado no existe')) return d def _insertDB(self, rows, request, userId, args): """inserta una persona en la base de datos y llama a la función que inserta a la misma persona como alumno """ _ = request.getSession()._ if len(rows) != 0: return failure.Failure(_('El usuario ya existe en el sistema')) else: person_name = [] person_value = [] #encripto el password if args['password']!="": args['password'] = sha.new(args['password']).hexdigest() for field in self.fields: if field['query'] == "person": person_name.append(field['name']) person_value.append("'" + args[field['name']] + "'") person_name = ", ".join(person_name) + ", language, fk_timezone" person_value = ", ".join(person_value) + ", " + str(PUPIL) + ", 2" person_op = "insert into person (kind, " + person_name + ") values \ (%d"+ ", " + person_value + ")" d = self.db.db.runOperation(person_op, (PUPIL,)) query = "select id from person where username = %s" username = QuotedString(args['username']) d.addCallback(lambda a: self.db.db.runQuery(query, (username,))) d.addCallback(self.insertPupil, request, userId, args) return d def insertPupil(self, rows, request, userId, args): """Inserta un alumno en la base de datos de acuerdo a los datos de rows """ _ = request.getSession()._ assert(len(rows) == 1) pupil_name = [] pupil_value = [] expire_time = DateTime.now() + DateTime.RelativeDate(**EXPIRE_TIME) for field in self.fields: if field['query'] == "pupil": pupil_name.append(field['name']) pupil_value.append("'" + str(args[field['name']]) + "'") pupil_name = ", ".join(pupil_name) + ", fk_client, ai_available, pc_available, expires" pupil_value = ", ".join(pupil_value) + ", %d, %f, %f, '%s'" % (userId, args['ai_total'], args['pc_total'], expire_time) pupil_op = "insert into pupil (id, " + pupil_name + ") values \ (%d" + ", " + pupil_value + ")" client_op = "update client set ai_available = ai_available - %f, pc_available = pc_available - %f where id = %s" d = self.db.db.runOperation(pupil_op, (rows[0][0],)) d.addCallback(lambda a: self.db.db.runOperation(client_op, (args['ai_total'], args['pc_total'], args['user_id']))) d.addCallback(lambda a: request.write('<div class="message">' + \ _('Usuario ingresado con exito') + '</div>') or self.getEmptyRow(None, 8)) return d def getEmptyRow(self, data, size): """Devuelve una consulta vacia de tamaño size""" return [[""] * size] def printCheckArgs(self, hours, request): """Para cada diccionario de la lista fields chequea si el campo es obligatorio y arma la funcion de JavaScript para el chequeo de datos. Agrega a continuacion el chequeo de que las contraseñas coincidan """ _ = request.getSession()._ ai = hours[0][0] pc = hours[0][1] page = """ <script type="text/javascript" src="/static/js/valid.js"></script> <script type="text/javascript">\n function check_args(form){ message='';""" for i in self.fields: if i['required']: page += """if(form.%s.value == "") message += "- """ % i['name'] + \ _('El campo %s es obligatorio') % _(i['desc']) + """\\n";\n""" page += """if(form.password.value != form.password2.value) message += \"- """ + _('Las contrasenas no coinciden') + """\\n"; if(!isNaN(parseFloat(form.ai_total.value))){ form.ai_total.value = parseFloat(form.ai_total.value); }else{ message += \"- """ + _('El campo Horas AI disponibles debe ser numerico') + """\\n"; } if(form.ai_total.value > """ + str(ai) + """){ message += \"- """ + _('Se ha excedido en las Horas AI asignadas') + """\\n"; } if(form.ai_total.value < 0){ message += \"- """ + _('El campo Horas de AI debe ser positivo') + """\\n"; } if(!isNaN(parseFloat(form.pc_total.value))){ form.pc_total.value = parseFloat(form.pc_total.value); }else{ message += \"- """ + _('El campo Horas PC disponibles debe ser numerico') + """\\n"; } if(form.pc_total.value > """ + str(pc) + """){ message += \"- """ + _('Se ha excedido en las Horas PC asignadas') + """\\n"; } if(form.pc_total.value < 0){ message += \"- """ + _('El campo Horas de PC debe ser positivo') + """\\n"; } if(form.pc_total.value == 0 && form.ai_total.value == 0){ message += \"- """ + _('Debe asignarle horas al alumno') + """\\n"; } if(!isEmailAddress(form.email)){ message += \"- """ + _('El email ingresado es incorrecto') + """\\n"; } if(message){ alert(" """ + _('Error en el ingreso de datos:') + """\\n"+message+"\\n"); return false; }else{ return true; } } </script> """ request.write(page) return def printForm(self, row, request, args, userId): """Para cada diccionario de la lista fields arma el campo del formulario correspondiente. """ session = request.getSession() _ = session._ d = self.db.db.runQuery("select ai_available, pc_available from client where id = %d", (userId,)) d.addCallback(self._printAvailable, request) d.addCallback(self.printCheckArgs, request) page = """<form action="" method="post" \ onsubmit="return check_args(this)"><div> """ for i in self.fields: value = row[0][i['pos']] required = i['required'] and "<sup>*</sup>" or "" text = i['type'] page += """<label for="%s">%s%s: <input type="%s" name="%s" size="20" value="%s" maxlength="%d" id="%s" /></label><br/>\n""" % \ (i['name'], _(i['desc']), required, text, i['name'], value, i['maxlength'], i['name']) d.addCallback(lambda a: request.write(page)) d.addCallback(lambda a: request.write("""<input type="submit" \ name="submit" id="submit" value=\"""" + _('Guardar') + """\"/>""")) if userId > 0: d.addCallback(lambda a: request.write("""<input type="hidden" name="user_id" value="%s"/>""" % userId)) d.addCallback(lambda a: request.write("""</div></form>""")) return d
class WebTutorData(Resource): _ = dummyTranslator dateToString = { 1: _("Domingo"), 2: _("Lunes"), 3: _("Martes"), 4: _("Miercoles"), 5: _("Jueves"), 6: _("Viernes"), 7: _("Sabado"), 8: _("Domingo"), 9: _("Lunes"), 10: _("Martes"), 11: _("Miercoles"), 12: _("Jueves"), 13: _("Viernes"), 14: _("Sabado"), }.get def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # muestra datos de un tutor (horarios disponibles, nombre, etc.) def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, _("Datos del tutor"))) d = defer.maybeDeferred(lambda: None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, "username"): request.write(self.template.notAuthenticated(session)) # 2) debe proveerse el argumento user_id elif "user_id" in request.args.keys(): page = """<h2>""" + _("Informacion del tutor") + """</h2>""" d.addCallback(lambda a: request.write(page)) try: user_id = int(request.args["user_id"][0]) # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id) except ValueError: request.write(self.template.unexpectedArguments(session, _("user_id deberia ser entero"))) else: request.write(self.template.unexpectedArguments(session, _("falta el parametro user_id"))) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d, userId): _ = request.getSession()._ query = "select p.id, p.first_name, p.last_name from person p, \ tutor t where t.id = p.id and p.id = %d" d.addCallback(lambda a: self.db.db.runQuery(query, (userId,))) d.addCallback(self.printData, request) query2 = "select name from tutor_subject, subject where \ fk_subject = subject.id and fk_tutor = %d order by subject.id" d.addCallback(lambda a: self.db.db.runQuery(query2, (userId,))) d.addCallback(self.printSubject, request) query3 = "select t.time_start, t.time_end, t.schedule_type from \ tutor_schedule t where fk_tutor = %d \ order by schedule_type, time_start asc" d.addCallback(lambda a: self.db.db.runQuery(query3, (userId,))) d.addCallback(self.printSchedule, request) return d def printData(self, rows, request): # rows[0]: id # rows[1]: first_name # rows[2]: last_name _ = request.getSession()._ if len(rows) != 1: string = '<div class="error">' + _("El usuario solicitado no existe") + "</div>" else: last_name = rows[0][2] first_name = rows[0][1] string = ( '<table class="table_info" id="tutordata">' + '<tr><th class="header_userinfo">' + _("Nombre:") + "</th><td>%s</td></tr>" % first_name ) string += '<tr><th class="header_userinfo">' + _("Apellido:") + "</th><td>%s</td></tr>" % last_name request.write(string) return def printSubject(self, rows, request): # rows contiene una fila por cada materia que ensenha el tutor # rows[i][0]: nombre _ = request.getSession()._ string = "" if len(rows) != 0: string += '<tr><th class="header_userinfo">' + _("Materias que sabe ensenar:") + "</th><td><ul>" for row in rows: string += "<li>%s</li>" % row[0] string += "</ul>" string += "</td></tr>" request.write(string) return def printSchedule(self, rows, request): # rows contiene una fila por cada segmento de horairo guardado en # tutor_schedule. # rows[i][0]: time_start # rows[i][1]: time_end # rows[i][2]: schedule_type _ = request.getSession()._ ai = "" pc = "" for row in rows: if row[2] == SCH_AI: if ai == "": ai += ( '<tr><th class="header_userinfo">' + _("Horarios en los que da clases de Acceso Instantaneo:") + "</th><td><ul>" ) ai += "<li> %s </li>" % self.dateRangeToString(request, row[0], row[1]) elif row[2] == SCH_PC: if pc == "": pc += ( '<tr><th class="header_userinfo">' + _("Horarios en los que da clases de Clase Precoordinada:") + "</th><td><ul>" ) pc += "<li> %s </li>" % self.dateRangeToString(request, row[0], row[1]) if ai != "": ai += "</ul></td></tr>" if pc != "": pc += "</ul></td></tr>" request.write(ai) request.write(pc) request.write("</table>") return def dateRangeToString(self, request, date_start, date_end): _ = request.getSession()._ start_day = date_start.day end_day = date_end.day if self.dateToString(start_day) == self.dateToString(end_day): ret = ( _(self.dateToString(start_day)) + ": " + _("de") + " " + date_start.strftime(HOUR_FORMAT) + " " + _("a") + " " + date_end.strftime(HOUR_FORMAT) ) else: ret = ( _("Desde") + " " + _(self.dateToString(start_day)) + " " + _("a las") + " " + date_start.strftime(HOUR_FORMAT) + " " + _("hasta") + " " + _(self.dateToString(end_day)) + " " + _("a las") + " " + date_end.strftime(HOUR_FORMAT) ) return ret
class WebClientReport(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # Muestra un acceso a Listado de datos personales de alumnos (para recortar) # y Detalle de horas por alumno def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, _('Reportes de alumnos'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: # 2.1) Admin debe proveer el argumento user_id if "user_id" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, \ _('falta el parametro user_id'))) # 3) Si es Cliente, administra sus propios horarios elif session.kind == CLIENT: user_id = session.userId # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id) else: # 4) Si no es ni ni Admin, ni Cliente, ni nadie, es alguien que no está # autorizado a administrar alumnos request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d, userId): d.addCallback(lambda a: self.requestData(userId)) d.addCallback(self.printData, request, userId) return d def requestData(self, userId): query = "select p.first_name, p.last_name, c.organization \ from person p, client c where c.id = p.id and p.id = %s" d = self.db.db.runQuery(query, (str(userId),)) return d def printData(self, data, request, userId): session = request.getSession() user = (session.kind == ADMIN) and "?user_id=%s" % (str(userId),) or "" _ = session._ if len(data) != 1: string = '<div class="error">' + _('El usuario no existe en el sistema') \ + '</div>' else: client = "%s %s (%s)" %(data[0][0], data[0][1], data[0][2]) string = """<h2>""" + _('Reportes de alumnos de %s') % client \ + """</h2>""" + _('Seguimiento de alumnos') string += "<div id='client_menu'><ul>" + \ '<li> <a href="/my_pupils_info%s">' % user + \ _('Datos personales:') + ' </a> ' + \ _('Listado de datos personales los alumnos a cargo') + \ '</li><li> <a href="/my_pupils%s">' % user + _('Horas:') + ' </a> ' + \ _('Detalle de las horas usadas y disponibles por alumno') + \ '</li></ul></div>' + '<a href="javascript:history.back()" id="back">' + \ _('Volver') + '</a>' request.write(string) return
class WebArchive(Resource): _ = dummyTranslator def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound #muestra las pizarras guardadas en la base de datos def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, \ _('Archivo de pizarras'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios else: msg = _('Este es el archivo de las pizarras correspondientes a las clases dadas en el sistema. Puedes bajar cualquiera de las pizarras haciendo click en el nombre del archivo. La informacion de la fecha que aparece corresponde a la fecha de finalizacion de la clase') msg = '<h2>' + _('Archivo') + '</h2>' + msg + '<br/>' d.addCallback(lambda a: request.write(msg)) # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d): """Consulta las sesiones del tutor user_id en la base de datos y las manda a imprimir """ query = "select a.filename, s.fk_tutor, p.username, s.fk_pupil, p2.username, \ a.comment, s.time_end from archive a left join session s \ on (s.id = a.fk_session) left join person p on (p.id = s.fk_tutor) \ left join person p2 on (p2.id = s.fk_pupil)" d.addCallback(lambda a: self.db.db.runQuery(query)) d.addCallback(self.printData, request) return d def printData(self, rows, request): # cada row de rows trae: # [0]: filename # [1],[2]: tutor id, tutor username # [3],[4]: pupil id, pupil username # [5]: comentario # [6]: fecha y hora de fin de esa session _ = request.getSession()._ if len(rows) == 0: string = "<div class='client_info'>" + _('El archivo esta vacio') + '</div>' else: string = _('Se encontraron %d archivos:') % len(rows) string += """ <table class="table_list" id="archive"> <tr> <th class="header_list">""" + _('Archivo') + """</th> <th class="header_list">""" + _('Tutor') + """</th> <th class="header_list">""" + _('Alumno') + """</th> <th class="header_list">""" + _('Fecha') + """</th> <th class="header_list">""" + _('Comentario') + """</th> </tr> """ for row in rows: tutor_name = (row[2] is not None) and \ "<a href='/userinfo?user_id=%s&kind=%d'>%s</a>" % \ (row[1], TUTOR, row[2]) or _('El tutor ya no esta en el sistema') pupil_name = (row[4] is not None) and \ "<a href='/userinfo?user_id=%s&kind=%d'>%s</a>" % \ (row[3], PUPIL, row[4]) or _('El alumno ya no esta en el sistema') date = (row[6] is not None) and row[6].Format(DATETIME_FORMAT) or "" string += """ <tr class="row_list"> <td><a href="%s">%s</a></td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> </tr>""" % ("board_archive/" + row[0], row[0], tutor_name, pupil_name, date, row[5]) string += """</table>""" request.write(string) return
class WebLogin(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() self.render_POST = self.render_GET Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound def render_GET(self, request): session = request.getSession() _ = getTranslatorFromSession(request) d = defer.maybeDeferred(lambda: None) if hasattr(session, 'username'): request.write(self.template.startPage(session, _('Iniciar Sesion'))) request.write('<div class="message">' + \ _('La sesion ya estaba iniciada') + '</div>') elif "username" in request.args.keys() and "pwd" in request.args.keys(): query = "select username, id, kind, first_name, \ last_name from person where username = %s and password = %s" username = QuotedString(request.args['username'][0]) pwd = sha.new(request.args['pwd'][0]).hexdigest() #hashing sent plain-password in sha-1 d = self.db.db.runQuery(query, (username, pwd)) d.addCallback(self.authenticateUser, request) else: request.write(self.template.startPage(session)) request.write("""<h2>""" + _('Inicio de Sesion') + """</h2> \ <form action="" method="post"><div>""" + _('Nombre de Usuario') \ + """: <label for="username"><input type="text" size="5" name="username" \ id="username" value="Root"/></label><br/>""" + _('Contrasena') \ + """: <label for="pwd"><input type="password" size="5" name="pwd" \ id="pwd" value="lala"/></label><br/><input id="submit" type="submit" value=\"""" + \ _('Entrar!') + """\"/></div></form>""") d.addCallback(lambda a:request.write(self.template.finishPage(session))) d.addCallback(lambda a:request.finish()) d.addErrback(log.err) return server.NOT_DONE_YET def authenticateUser(self, rows, request): session = request.getSession() _ = session._ # Ya sabemos que está if len(rows) == 1: row = rows[0] session.username = row[0] session.userId = row[1] session.kind = row[2] session.name = row[3] session.lastname = row[4] d = defer.maybeDeferred(getTranslatorFromSession, request, refresh=True) d.addCallback(self.welcomeMessage, request, row[3], row[4]) return d elif len(rows) == 0: request.write(self.template.startPage(session)) request.write('<div class="warning"><h2>' + \ _('Nombre de Usuario o Contrasena incorrecta') + '</h2>' + \ _('Por favor verifique su nombre de usuario y contrasena.') + '<br/>' + \ _('Recuerde que su nombre de usuario y contrasena son sensibles a mayusculas y minusculas!') + '</div>') else: request.write(self.template.startPage(session)) request.write('<div class="error">' + \ _('Existen varios usuarios en el sistema con las mismas credenciales. Por favor notifique al administrador del sistema') + '</div>') return def welcomeMessage(self, trans, request, first, last): session = request.getSession() _ = trans d = defer.maybeDeferred(lambda: None) d.addCallback(lambda a: request.write(self.template.startPage(session))) d.addCallback(lambda a: request.write('<div class="message">' + \ _('Bienvenido') + ', %s %s</div>' % (first, last))) d.addCallback(lambda a: self.template.homePageContent(session)) d.addCallback(request.write) d.addCallback(lambda a: self.template.commonInfo(trans)) d.addCallback(request.write) return d
class WebRoomInfo(Resource): def __init__(self, server): self.db = DBConnect self.rOpen = server.openRoomsAndLenQueues # clave room -> valor cant gente self.subjects = server.openRoomsAndSubjects # clave room -> valor lista materias self.sbOpen = server.shouldBeOpenAndClosedRooms self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans request.write(self.template.startPage(session, \ _('Informacion de Pizarras en el sistema'))) d = defer.maybeDeferred(lambda :None) if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: msg = '<h2>' + _('Estado del sistema') + '</h2>' + \ _('Aqui se muestran las aulas que se encuentran abiertas, una descripcion de ellas y la lista de aulas que deberian estar abiertas.') # La función que procesa e imprime el contenido de la pagina else: msg = '<h2>' + _('Estado del sistema') + '</h2>' + \ _('Aqui se muestran las aulas que se encuentran abiertas y una descripcion de ellas') self.printContent(request, d, session, msg) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def printContent(self, request, d, session, msg): rOpen = self.rOpen() subjects = self.subjects() d.addCallback(lambda a: request.write(msg)) d.addCallback(lambda a: self._getORoomInfo(rOpen)) d.addCallback(self._printORoomTable, request, rOpen, subjects) if session.kind == ADMIN: d.addCallback(lambda a: self._getSBORoomInfo(self.sbOpen())) d.addCallback(self._printSBORoomTable, request) # 2) Se imprime un mensaje de bienvenida configurable return d def _getORoomInfo(self, openRooms): ids = tuple([int(b) for b in openRooms.keys() if b != GENERAL] + [0]) if len(ids) > 1: query = "select username, id from person where id in %s" d = self.db.db.runQuery(query, (ids,)) else: d = defer.maybeDeferred(lambda: []) return d def _getSBORoomInfo(self, sbopenRooms): if sbopenRooms != []: query = "select username, id from person where id in %s" d = self.db.db.runQuery(query, (tuple(sbopenRooms + [0]),)) else: d = defer.maybeDeferred(lambda: []) return d def _printORoomTable(self, rows, request, openRooms, subjects): _ = request.getSession()._ page = """<br/><br/> <table class="table_list" id="opened_rooms"> <caption>""" + _('Aulas abiertas:') + """</caption> <tr class="header_list"> <th>""" + _('Aula') + """</th> <th>""" + _('Usuarios conectados') + """</th> <th>""" + _('Tutor a cargo') + """</th> <th>""" + _('Materias') + """</th> </tr>""" if len(openRooms) == 1: page += '<tr><td colspan ="4" style="text-align: center">' + \ _('Ningun aula abierta') + ' </td></tr>' else: for room in rows: rm = room[1] connected = openRooms.get(str(room[1])) in_charge = "<a href='/tutor_data?user_id=%s'> %s </a>" % (room[1], room[0]) sub = self.printSubjects(subjects.get(str(room[1]))) page += """ <tr> <td> %s </td> <td> %s </td> <td> %s </td> <td> %s </td></tr>""" % (rm, connected, in_charge, sub) + """ </td></tr>""" page += '</table><br/><br/>' page += _('Usuarios en la cola general:') + '%d' % openRooms.get(GENERAL) request.write(page) def printSubjects(self, subjects): return " - ".join(subjects) def _printSBORoomTable(self, rows, request): _ = request.getSession()._ page = """<br/><br/> <table class="table_list" id="sbopen_rooms"> <caption>""" + _('Aulas que deberian estar abiertas y no estan:') + """</caption> <tr class="header_list"> <th>""" + _('Aula') + """</th> <th>""" + _('Tutor') + """</th> </tr>""" if len(rows) == 0: page += """ <tr><td colspan ="3" style="text-align: center">""" + \ _('No hay tutores ausentes') + """</td></tr>""" else: for room in rows: page += """ <tr> <td> %s </td> <td> <a href="/tutor_data?user_id=%s"> %s </a> </td> </tr>""" % (room[1], room[1], room[0]) page += '</table>' request.write(page)
class WebAdmin(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # A esta pagina sólo se podrá acceder si tenemos permisos de administrador. # Mostrará un link para ver las listas de: clientes, tutores y alumnos def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): _ = trans session = request.getSession() d = defer.maybeDeferred(lambda: None) # Se escribe el comienzo de la página request.write(self.template.startPage(session, _('Administracion de usuarios'))) # Si no es admin o no esta loggeado, no seguimos if not hasattr(session, 'username') or session.kind != ADMIN: d.addCallback(lambda a: request.write(self.template.notAuthenticated(session))) else: d.addCallback(lambda a: self.sysStatus(request)) d.addCallback(self.printContent, request) # Se escribe el final de la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return server.NOT_DONE_YET def sysStatus(self, request): """Busca la información acerca de la cantidad de usuarios, alumnos y tutores que tiene el sistema. """ query = "select count(*), kind from person group by kind order by kind asc" d = self.db.db.runQuery(query) return d def printContent(self, rows, request): _ = request.getSession()._ subjects = _('Listado de materias disponibles y cantidad de tutores que la tienen como seleccionada para poder dar clases. Tambien se pueden realizar alta y bajas de materias') tutors = _('Tiempo que los tutores pasaron en el sistema, dividido por tipos de conexion. Detalle de las sesiones de cada tutor. Se puede elegir un rango de fechas para visualizar') rooms = _('Informacion de las aulas del sistema, cantidad de alumnos en el aula, los tutores que se encuentran a cargo y las materias que estan brindando. Listado de aulas que deberian estar abiertas y no lo estan, con la informacion del tutor correspondiente') board = _('Archivos en formato PDF (Portable Document Format) que contienen las pizarras de las clases brindadas por los tutores del sistema') admin = [{'id': 'subject_admin', 'item': _('Administrar materias'), \ 'title': _('Materias'), 'alt': _('Materias'), 'desc': subjects, \ 'link': '/subject_admin', 'image': '/static/graphics/subjects.gif', \ 'width': '16', 'height': '16'}, {'id': 'tutor_info', 'item': _('Informacion de tutores'), \ 'title': _('Tutores'), 'alt': _('Tutores'), 'desc': tutors, \ 'link': '/tutor_info', 'image': '/static/graphics/subjects.gif', \ 'width': '16', 'height': '16'}, {'id': 'roominfo', 'item': _('Informacion de aulas'), \ 'title': _('Aulas'), 'alt': _('Aulas'), 'desc': rooms, \ 'link': '/roominfo', 'image': '/static/graphics/tutor_info.gif', \ 'width': '16', 'height': '16'}, {'id': 'tutor', 'item': _('Agregar tutores'), 'title': _('Tutores'), \ 'alt': _('Tutores'), 'desc': _('Agregar nuevos tutores al sistema'), \ 'link': '/tutor', 'image': '/static/graphics/mortarboard.gif', \ 'width': '16', 'height': '16'}, {'id': 'client', 'item': _('Agregar clientes'), 'title': _('Clientes'), \ 'alt': _('Clientes'), 'desc': _('Agregar nuevos clientes al sistema'), \ 'link': '/client', 'image': '/static/graphics/buddy.gif', \ 'width': '16', 'height': '16'}, {'id': 'archive', 'item': _('Archivo de pizarras'), 'title': _('Archivo'), \ 'alt': _('Archivo'), 'desc': board, 'link': '/archive', \ 'image': '/static/graphics/ps.png', 'width': '16', 'height': '16'}] page = '' if len(rows) != 0: page += '<h2>' + _('Administracion del sistema:') \ + '</h2><div style="padding-left: 40px"><table id="admin_table" border="0">' for item in admin: page += """<tr><td><a href='%s' id='%s'><img src='%s' width='%s' height='%s' alt='%s' title='%s'/></a><a href='%s'>%s</a> </td><td>%s</td> </tr>""" \ % (item['link'], item['id'], item['image'], item['width'], \ item['height'], item['alt'], item['title'], item['link'], \ item['item'], item['desc']) page += """</table></div><h2>""" + _('Informacion de usuarios en el sistema:') \ + """</h2><div style="padding-left: 40px" id='users'>""" \ + """<ul id="systemusers">""" for i in range(len(rows)): # row[0] es la cantidad de row[1] que hay en la base if rows[i][1] == TUTOR: page += '<li>%d <a href="/list?kind=%d">' % (rows[i][0], TUTOR) \ + _('Tutores') + '</a> ' + _('en el sistema') + '</li>' elif rows[i][1] == PUPIL: page += '<li>%d <a href="/list?kind=%d">' % (rows[i][0], PUPIL) \ + _('Alumnos') + ' </a> ' + _('en el sistema') + '</li>' elif rows[i][1] == CLIENT: page += '<li>%d <a href="/list?kind=%d">' % (rows[i][0], CLIENT) \ + _('Clientes') + ' </a> ' + _('en el sistema') + '</li>' elif rows[i][1] == ADMIN: page += '<li>%d <a href="/list?kind=%d">' % (rows[i][0], ADMIN) \ + _('Administradores') + ' </a> ' + _('en el sistema') + '</li>' else: page += '<li>%d' % rows[i][0] + \ _('Usuarios no categorizados en el sistema') + '</li>' page += '</ul></div>' else: page += '<h2>' + _('No hay usuarios en el sistema') + '</h2>' request.write(page) return
class WebMyPupilsInfo(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # Si estamos autenticados como admin, sirve para ver los alumnos de cualquier cliente # Si somos cliente, sólo podremos ver los propios def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET msg = """<h2>""" + _('Cuentas de alumnos') + """</h2>""" def doAuthentication(self, trans, request): session = request.getSession() _ = trans # 0) Se empieza la página request.write(self.template.startPage(session, \ _('Informacion de cuentas de usuarios'))) d = defer.maybeDeferred(lambda:None) # 1) Verificar que esté autenticado ante el sistema if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) # 2) Si es Admin, administra todos los usuarios elif session.kind == ADMIN: # 2.1) Admin debe proveer el argumento user_id if "user_id" in request.args.keys(): try: user_id = int(request.args['user_id'][0]) d.addCallback(lambda a: self.requestData(user_id)) d.addCallback(self.printTitle, request) self.printContent(request, d, user_id) # La función que procesa e imprime el contenido de la pagina except ValueError: request.write(self.template.unexpectedArguments(session, \ _('user_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, \ _('falta el parametro user_id'))) # 3) Si es cliente, muestra la información de alumnos propios elif session.kind == CLIENT: user_id = session.userId d.addCallback(lambda a: self.requestData(user_id)) d.addCallback(self.printTitle, request) self.printContent(request, d, user_id) else: # 4) Si no, es alguien que no está autorizado request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def requestData(self, user_id): query = "select p.first_name, p.last_name, c.organization from person p, \ client c where c.id = p.id and p.id = %s" d = self.db.db.runQuery(query, (user_id,)) return d def printTitle(self, data, request): _ = request.getSession()._ if len(data) != 1: msg = """<h2>""" + _('Cuentas de alumnos') + """</h2>""" else: client = "%s %s (%s)" % (data[0][0], data[0][1], data[0][2]) msg = """<h2>""" + _('Cuentas de alumnos de %s') % client + """</h2>""" request.write(msg) def printContent(self, request, d, userId): # 1) Si se envían datos, se actualiza la base primero _ = request.getSession()._ # 3) Se buscan los datos en la base query = "select username, password, first_name, last_name, email, \ ai_available, pc_available, expires from pupil a, person p \ where p.id = a.id and fk_client= %d" d.addCallback(lambda a: self.db.db.runQuery(query, (userId, ))) # 4) Se imprime los datos d.addCallback(self.printForm, request, userId) return d def printForm(self, rows, request, userId): _ = request.getSession()._ string = "" fields = [{'pos': 0, 'desc': _('Nombre de usuario')}, {'pos': 1, 'desc': _('Constrasena')}, {'pos': 2, 'desc': _('Nombre')}, {'pos': 3, 'desc': _('Apellido')}, {'pos': 4, 'desc': _('eMail')}, {'pos': 5, 'desc': _('Hs. AI restantes')}, {'pos': 6, 'desc': _('Hs. CP restantes')}, {'pos': 7, 'desc': _('Vencimiento')}] if len(rows) == 0: string += '<div class="message"><b>' + \ _('No se registran alumnos a cargo') + '</b></div>' else: string += _('Informacion de %d alumnos') % len(rows) + ':<br/>' for pupil in rows: string += '<div class="pupil_info"><ul>' for f in fields: string += '<li><b>' + f['desc'] + ': </b> ' + self.getFormat(pupil[f['pos']], f['pos']) + '</li>' string += '</ul></div><br/>' request.write(string) return def getFormat(self, data, pos): if pos == 7: return data.Format(DATETIME_FORMAT) else: return str(data)
class WebListUsers(Resource): def __init__(self): self.db = DBConnect() self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound # A esta pagina sólo se podrá acceder si tenemos permisos de administrador. # Mostrará una lista de clientes, tutores, etc. de acuerdo a lo que se le pase por # direccion def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans # Se escribe el comienzo de la página request.write(self.template.startPage(session, \ _('Listado de usuarios del sistema'))) d = defer.maybeDeferred(lambda: None) keys = request.args.keys() # Si no es admin o no esta loggeado, no seguimos if not hasattr(session, 'username') or session.kind != ADMIN: request.write(self.template.notAuthenticated(session)) else: if "kind" in request.args.keys(): try: kind = int(request.args['kind'][0]) if "del" in keys: erase = DBDelete(self.db) client = QuotedString(request.args['del'][0]) d.addCallback(lambda a: erase.deletePerson(client, kind)) d.addCallback(lambda a: request.write('<div class="message">' + \ _('El usuario ha sido borrado correctamente') + '</div>')) elif ("ia" in keys or "pc" in keys) and "user_id" in keys and \ not ("ia" in keys and "pc" in keys): hours = ("ia" in keys) and "ia" or "pc" user = QuotedString(request.args['user_id'][0]) cant = float(request.args[hours][0].replace(",", ".")) d.addCallback(lambda a: self.setClientHours(user, cant, hours)) d.addCallback(lambda a: request.write('<div class="message">' + \ _('Se ha actualizado correctamente la cantidad de horas disponibles') + '</div>')) d.addCallback(lambda a: self.listClient(request)) except ValueError: d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Argumento no valido')))) else: d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Falta el argumento \'kind\'')))) # Se escribe el final de la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def setClientHours(self, user, cant, hours): if hours == "pc": query = "update client set pc_available = %f where id=%s """ else: query = "update client set ai_available = %f where id=%s """ d = self.db.db.runOperation(query, (cant, user)) return d def listClient(self, request): """Busca la información para todos los usuarios del tipo dado por la request y llama a printContent con el resultado de la busqueda """ kind = int(request.args['kind'][0]) try: pag = int(request.args['pag'][0]) except: pag = 0 if kind == TUTOR: cols = "tutor.id, username, first_name, last_name" fromWhere = "from tutor, person where tutor.id = person.id" order = "order by id asc" elif kind == PUPIL: cols = "p.id, p1.username, p1.first_name, p1.last_name, p2.username, p.fk_client" fromWhere = "from person p1, person p2, pupil p where p.id = p1.id and p2.id = p.fk_client" order = "order by p.id asc" elif kind == CLIENT: cols = "client.id, username, first_name, \ last_name, organization, client.ai_available, client.pc_available, \ count(pupil.id)" fromWhere = "from client left join pupil on \ (pupil.fk_client = client.id) left join person on (client.id = person.id) \ group by client.id, person.username, person.first_name, person.last_name, \ client.organization, client.ai_available, client.pc_available" order = "order by id asc" elif kind == ADMIN: cols = "person.id, username, first_name, last_name" fromWhere = "from person where kind = %s" % kind order = "order by id asc" else: # kind desconocido cols = "person.id, username, first_name, last_name" fromWhere = "from person where kind = %s" % kind order = "order by id asc" cols += ", (SELECT count(*) %s)" % fromWhere query = "SELECT %s %s %s LIMIT %d OFFSET %d" % (cols, fromWhere, order, ITEMS_PAG, ITEMS_PAG*pag) print repr(query) d = self.db.db.runQuery(query) d.addCallback(self.printContent, kind, request) return d def printContent(self, rows, kind, request): """Lista todos los usuarios del sistema del typo kind (de acuerdo al resultado de la consulta rows """ _ = request.getSession()._ if len(rows) != 0: def paginacion(): total = rows[0][-1:][0] #la ultima columna es el total de datos para la consulta try: actual = int(request.args['pag'][0]) except: actual = 0 if total > ITEMS_PAG: request.write('<div> <strong>' + _('Página:') + '</strong>') for pagina in range(int(total/ITEMS_PAG)+1): tip = "href" if pagina == actual: tip = "id" link = "<a %s='/list?kind=%d&pag=%d'>%d</a> " % (tip,kind,pagina,pagina+1) request.write(link) request.write('</div><br />') request.write('<h2>' + _('Usuarios del sistema:') + '</h2>') if kind == TUTOR: request.write(""" <script type="text/javascript"> function del_confirm(tutor){ return confirm(\"""" + _('Esta seguro de borrar el tutor') + """ \"+tutor+"?"); } </script> """) request.write(""" <table class="table_list" id="usersinsystem"> <tr> <th class="icon_list"></th> <th class="icon_list"></th> <th class="icon_list"></th> <th class="icon_list"></th> <th class="header_list">""" + _('Usuario') + """</th> <th class="header_list">""" + _('Apellido') + """</th> <th class="header_list">""" + _('Nombre') + """</th> </tr>""") for i in range(len(rows)): # row tiene todos los datos de los usuarios del tipo kind request.write("""<tr> <td class="row_list"><a href="tutor?user_id=%s" class="link_image"><img src="/static/graphics/modify.gif" width="16" height="16" alt=\"""" % rows[i][0] + _('Modificar') + """\" title=\"""" + _('Modificar') + """\"/></a></td> <td class="row_list"><a href="?kind=%s&del=%s" class="link_image" onclick="return del_confirm('%s')"><img src="/static/graphics/delete.gif" width="16" height="16" alt=\"""" % (TUTOR, rows[i][0], rows[i][1]) + _('Borrar') + """\" title=\"""" + _('Borrar') + """\"/></a></td> <td class="row_list"><a href="/schedules?user_id=%s" class="link_image"><img src="/static/graphics/schedule.gif" width="16" height="16" alt=\"""" % rows[i][0] + _('Asignar horas') + """\" title=\"""" + _('Asignar horas') + """\"/></a></td> <td class="row_list"><a href="/subjects?user_id=%s" class="link_image"><img src="/static/graphics/subjects.gif" width="16" height="16" alt=\"""" % rows[i][0] + _('Asignar materias') + """\" title=\"""" + _('Asignar materias') + """\"/></a></td> <td class="row_list"><a href="/userinfo?user_id=%s&kind=%d">%s</a></td> <td class="row_list">%s</td> <td class="row_list">%s</td> </tr>""" % (rows[i][0], TUTOR, rows[i][1], rows[i][3], rows[i][2])) request.write('</table>') paginacion() request.write('<a href="/tutor"> ' + _('Agregar tutores') +'</a>') elif kind == PUPIL: request.write(""" <script type="text/javascript"> function del_confirm(pupil){ return confirm(" """ + _('Esta seguro de borrar el alumno') + """ "+pupil+"?"); } </script>""") request.write(""" <table class="table_list" id="usersinsystem"> <tr> <th class="icon_list"></th> <th class="icon_list"></th> <th class="header_list">""" + _('Usuario') + """</th> <th class="header_list">""" + _('Apellido') + """</th> <th class="header_list">""" + _('Nombre') + """</th> <th class="header_list">""" + _('Cliente') + """</th> </tr>""") for i in range(len(rows)): request.write("""<tr> <td class="row_list"><a href="pupil_edit?pupil_id=%s&user_id=%s" class="link_image"><img src="/static/graphics/modify.gif" width="16" height="16" alt=\"""" % (rows[i][0], rows[i][5]) + \ _('Modificar') + """\" title=\"""" + _('Modificar') + """\"/></a></td> <td class="row_list"><a href="?kind=%s&del=%s" class="link_image" onclick="return del_confirm('%s')"><img src="/static/graphics/delete.gif" width="16" height="16" alt=\"""" %(PUPIL, rows[i][0], rows[i][1]) + _('Borrar') + """\" title=\"""" + _('Borrar') + """\"/></a></td> <td class="row_list"><a href="/userinfo?user_id=%s&kind=%d">%s</a></td> <td class="row_list">%s</td> <td class="row_list">%s</td> <td class="row_list">%s</td></tr>""" %(rows[i][0], PUPIL, rows[i][1], rows[i][3], rows[i][2], rows[i][4])) request.write('</table>') paginacion() elif kind == CLIENT: request.write(""" <script type="text/javascript"> function del_confirm(client, pupils){ message = \"""" + _('Esta seguro de borrar el cliente') + """\"+client+"?\\n"; if (pupils > 0){ message += \"(""" + _('Aun tiene') + """ \" + pupils + \" """+_('alumno(s) a cargo') + """)\"; } return confirm(message); } function ask_hours(client, hour_type){ var hours = NaN; while((!hours && hours != 0) && hours != null){ hours = prompt(" """ + _('Indique la cantidad de horas a asignar:') + """ ", "100"); if(hours != null) hours = parseFloat(hours); } if(parseFloat(hours) >= 0){ var url = "?kind=%s&" + hour_type + "=" + parseFloat(hours) + "&user_id=" +client; location.href = url; } } </script> """ % CLIENT) request.write(""" <table class="table_list" id="usersinsystem"> <tr> <th class="icon_list"></th> <th class="icon_list"></th> <th class="icon_list"></th> <th class="icon_list"></th> <th class="header_list">""" + _('Usuario') + """</th> <th class="header_list">""" + _('Apellido') + """</th> <th class="header_list">""" + _('Nombre') + """</th> <th class="header_list">""" + _('Organizacion') + """</th> <th class="icon_list"></th> <th class="header_list">""" + _('Horas disponibles (AI)') + """</th> <th class="header_list">""" + _('Horas disponibles (CP)') + """</th> <th class="icon_list"></th> </tr>""") for i in range(len(rows)): request.write("""<tr> <td class="row_list"><a href="client?user_id=%s" class="link_image"><img src="/static/graphics/modify.gif" width="16" height="16" alt=\"""" % (rows[i][0],) + _('Modificar') + """\" title=\"""" + _('Modificar') + """\"/></a></td> <td class="row_list"><a href="?kind=%d&del=%s" onclick="return del_confirm('%s', %d)" class="link_image"><img src="/static/graphics/delete.gif" width="16" height="16" alt=\"""" % (CLIENT, rows[i][0], rows[i][1], rows[i][7]) + _('Borrar') + """\" title=\"""" + _('Borrar') + """\"/></a></td> <td class="row_list"><a href="new_pupil?user_id=%s" class="link_image"><img src="/static/graphics/board.gif" width="16" height="16" alt=\"""" % (rows[i][0],) + _('Agregar alumno') + """\" title=\"""" + _('Agregar alumno') + """\"/></a></td> <td class="row_list"><a href="report?user_id=%s" class="link_image"><img src="/static/graphics/board.gif" width="16" height="16" alt=\"""" % (rows[i][0],) + _('Ver alumnos') + """\" title=\"""" + _('Ver alumnos') + """\"/></a></td> <td class="row_list"><a href="/userinfo?user_id=%s&kind=%d">%s</a></td> <td class="row_list">%s</td> <td class="row_list">%s</td> <td class="row_list">%s</td> <td class="row_list"><a href="" class="link_image" onclick="ask_hours(\'%s\', \'ia\'); return false;"><img src="/static/graphics/schedule.gif" width="16" height="16" alt=\"""" % (rows[i][0], CLIENT, rows[i][1], rows[i][3], rows[i][2], rows[i][4], rows[i][0]) + _('Asignar horas') + """\" title=\"""" + _('Asignar horas') + """\"/></a></td> <td class="row_list">%s</td> <td class="row_list">%s</td> <td class="row_list"><a href="" class="link_image" onclick="ask_hours(\'%s\', \'pc\'); return false;"><img src="/static/graphics/schedule.gif" width="16" height="16" alt=\"""" % (self.hoursFormat(rows[i][5]), self.hoursFormat(rows[i][6]), rows[i][0]) + _('Asignar horas') + """\" title=\"""" + _('Asignar horas') + """\"/></a></td></tr>""") request.write('</table>') paginacion() request.write('<a href="/client">' + _('Agregar clientes') + '</a>') elif kind == ADMIN: request.write(""" <table class="table_list" id="usersinsystem"> <tr> <th class="header_list"></th> <th class="header_list">""" + _('Usuario') + """</th> <th class="header_list">""" + _('Apellido') + """</th> <th class="header_list">""" + _('Nombre') + """</th> </tr>""") for i in range(len(rows)): request.write("""<tr> <td class="row_list"><a href="editadmin?user_id=%s" class="link_image"><img src="/static/graphics/modify.gif" width="16" height="16" alt=\"""" % (rows[i][0],) + _('Modificar') + """\" title=\"""" + _('Modificar') + """\"/></a></td> <td class="row_list"><a href="/userinfo?user_id=%s&kind=%d">%s</a></td> <td class="row_list">%s</td> <td class="row_list">%s</td> </tr>"""% (rows[i][0], ADMIN, rows[i][1], rows[i][3], rows[i][2])) request.write('</table>') paginacion() request.write('<a href="/editadmin"> ' + _('Agregar Administrador') +'</a>') else: for i in range(len(rows)): request.write('<li>' + _('Usuarios') + '%s %s, %s</li>' % (rows[i][0], rows[i][4], rows[i][5])) else: request.write('<h2> ' + _('No hay usuarios de este tipo en el sistema') + '</h2>') request.write('<a href="/admin" id="back"> ' + _('Volver') + '</a>') return def hoursFormat(self, hours): return (hours == None) and "0.0" or hours
class WebPerson(Resource): _ = dummyTranslator fields = [{'name': 'username', 'pos': 1, 'desc': _('Nombre de usuario'), \ 'required': True, 'isPass': False, 'maxlength': 80, 'query': "person"}, {'name': 'password', 'pos': 2, 'desc': _('Contrasena'), \ 'required': True, 'isPass': True, 'maxlength': 80, 'query': "person"}, {'name': 'password2', 'pos': 2, 'desc': _('Repita contrasena'), \ 'required': True, 'isPass': True, 'maxlength': 255, 'query': ""}, {'name': 'first_name', 'pos': 3, 'desc': _('Nombre'), 'required': True, \ 'isPass': False, 'maxlength': 255, 'query': "person"}, {'name': 'last_name', 'pos': 4, 'desc': _('Apellido'), 'required': True, \ 'isPass': False, 'maxlength': 255, 'query': "person"}, {'name': 'email', 'pos': 5, 'desc': _('eMail'), 'required': True, \ 'isPass': False, 'maxlength': 255, 'query': "person"}] def __init__(self, table, title, kind, query, empty, xtra_fields): _ = dummyTranslator self.db = DBConnect() self.render_POST = self.render_GET self.template = WebTemplates() self.table = table self.title = title self.kind = kind self.query = query self.empty = empty self.fields = WebPerson.fields + xtra_fields Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = trans request.write(self.template.startPage(session, self.title)) d = defer.maybeDeferred(lambda :None) if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) elif session.kind == ADMIN: try: user_id = int(request.args.get('user_id', [-1])[0]) msg = '<h2>' + self.title + ": " + _('Datos personales') + '</h2> ' + \ _('Recuerde que los campos indicados con <sup>*</sup> son obligatorios<br>') if user_id!=-1: msg += _('Si desea conservar la contraseña actual deje los campos en blanco') + '<br/>' # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('user_id deberia ser entero'))) # 3) Administra sus propios datos elif session.kind == self.kind: user_id = session.userId msg = '<h2>' + _('Tus Datos personales') + '</h2>' + \ _('Recuerda que los campos indicados con <sup>*</sup> son obligatorios') # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id, msg) else: # 4) Es alguien que no está autorizado a administrar materias request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return server.NOT_DONE_YET def checkRequest(self, d, request): session = request.getSession() _ = session._ args = dict([(i, request.args[i][0]) for i in request.args.keys()]) if "submit" in request.args.keys(): for value in self.fields: if value['name'] not in args.keys(): args[value['name']] = '' d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Falta el argumento \'%s\'') % value['name']))) elif len(args[value['name']]) > value['maxlength']: args[value['name']] = args[value['name']][:value['maxlength']] d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Longitud excesiva del argumento \'%s\'') % value['name']))) if(args['password'] != args['password2']): request.write(self.template.unexpectedArguments(session, \ _('Las contrasenas no coinciden'))) if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", args['email']) == None: request.write(self.template.unexpectedArguments(session, \ _('El email ingresado es incorrecto'))) return args def printContent(self, request, d, userId, msg): # si se estan enviando datos _ = request.getSession()._ #si se trata de una edicion las contraseñas no son requeridas. #Dejarlas en blanco es la forma de no modificarlas if int(request.args.get('user_id', [-1])[0])!=-1: self.fields[1]['required'] = self.fields[2]['required'] = False else: self.fields[1]['required'] = self.fields[2]['required'] = True args = self.checkRequest(d, request) if "submit" in args.keys(): # si tenemos que actualizar if userId > 0: person = [] kind = [] #si se ha modificado, encripto el nuevo password if args['password']!="": args['password'] = sha.new(args['password']).hexdigest() for field in self.fields: if field['query'] == "person": #si los password estan en blanco no se incluyen en la query de actualizacion if not(field['name']=='password' and args['password']==""): person.append(field['name'] + " = '" + args[field['name']] + "'") elif field['query'] == self.table: kind.append(field['name'] + " = '" + args[field['name']] + "'") person = ", ".join(person) kind = ", ".join(kind) update_person = "update person set " + person + " where id = %s" update_kind = "update " + str(self.table) + " set " + kind + " where id=%s" d.addCallback(lambda a: self.db.db.runOperation(update_person, (userId,))) if self.table != "admin": d.addCallback(lambda a: self.db.db.runOperation(update_kind, (userId,))) d.addCallback(lambda a: request.write("""<div class="message">""" + \ _('Datos actualizados con exito') + """</div>""") or userId) #antes de insertar debemos chequear si el usuario ya existe else: query = "select username from person where username = %s" username = args['username'] d.addCallback(lambda a: self.db.db.runQuery(query, (username,))) d.addCallback(self._insertDB, request, args) else: d.addCallback(lambda a:userId) d.addCallback(self._requestData, request, msg) d.addErrback(self.printError, request) d.addCallback(self.printForm, request, args, userId) def _requestData(self, userId, request, msg): request.write(msg) # no se estan mandando datos, se los solicita if userId > 0: d = self.db.db.runQuery(self.query, (userId,)) return d # ni se mandan ni se solicitan datos (formulario en blanco) else: return self.getEmptyRow(None, self.empty) def printError(self, failure, request): """Imprime el error de failure y genera una fila vacia para la consulta de la base de datos """ session = request.getSession() d = defer.maybeDeferred(lambda :None) d.addCallback(lambda a: request.write("""<div class="error"> %s </div>""" % \ failure.getErrorMessage())) d.addCallback(self.getEmptyRow, self.empty) return d def _insertDB(self, rows, request, args): """inserta una persona en la base de datos y llama a la función que inserta a la misma persona como self.kind """ session = request.getSession() _ = session._ if len(rows) == 0: person_name = [] person_value = [] #encripto el password if args['password']!="": args['password'] = sha.new(args['password']).hexdigest() for field in self.fields: if field['query'] == "person": person_name.append(field['name']) person_value.append("'" + args[field['name']] + "'") person_name = ", ".join(person_name) + ", language, fk_timezone, demo" person_value = ", ".join(person_value) + \ ", " + str(session.locale_id) + ", 2, False" person_op = "insert into person (kind, " + person_name + ") values \ (%d"+ ", " + person_value + ")" d = self.db.db.runOperation(person_op, (self.kind,)) if self.table != "admin": query = "select id from person where username=%s" username = QuotedString(args['username']) d.addCallback(lambda a: self.db.db.runQuery(query, (username,))) d.addCallback(self.insertKind, request, args) else: d.addCallback(lambda a: request.write("""<div class="message">""" + \ _('Administrador ingresado con exito') + """</div>""")) return d else: return failure.Failure(_('El usuario %s ya existe en el sistema') % \ args['username']) def insertKind(self, rows, request, args): """Inserta un usuario en la base de datos de acuerdo a los datos de rows """ _ = request.getSession()._ assert(len(rows) == 1) kind_name = [] kind_value = [] for field in self.fields: if field['query'] == self.table: kind_name.append(field['name']) kind_value.append("'" + args[field['name']] + "'") kind_name = ", ".join(kind_name) kind_value = ", ".join(kind_value) kind_op = "insert into " + self.table + "(id, " + kind_name + ") values \ (%d"+ ", " + kind_value + ")" d = self.db.db.runOperation(kind_op, (rows[0][0],)) d.addCallback(lambda a: request.write("""<div class="message">""" + \ _('Usuario ingresado con exito') + """</div>""") or rows[0][0]) return d def getEmptyRow(self, data, size): """Devuelve una consulta vacia de tamaño size""" return [[""] * size] def printCheckArgs(self, request): """Para cada diccionario de la lista fields chequea si el campo es obligatorio y arma la funcion de JavaScript para el chequeo de datos. Agrega a continuacion el chequeo de que las contraseñas coincidan """ _ = request.getSession()._ page = """ <script type="text/javascript" src="/static/js/valid.js"></script> \n <script type="text/javascript">\n function check_args(form){ message='';""" for i in self.fields: if i['required']: page += 'if(form.%s.value == "") message += "- ' % i['name'] + \ _('El campo %s es obligatorio') % _(i['desc']) + '\\n";\n' page += """if(form.password.value != form.password2.value) message += \"- """ + _('Las contraseñas no coinciden') + """\";\n""" page += """if(!isEmailAddress(form.email)) message += \"\\n- """ + _('El email ingresado es incorrecto') + """\"\n; if(message){ alert(" """ + _('Error en el ingreso de datos:') + """\\n"+message+"\\n"); return false; }else{ return true; } } </script> """ request.write(page) return def printForm(self, row, request, args, userId): """Para cada diccionario de la lista fields arma el campo del formulario correspondiente. """ _ = request.getSession()._ if len(row) == 0: request.write(self.template.unexpectedArguments(request.getSession(), \ _('El usuario solicitado no existe'))) row = self.getEmptyRow(None, self.empty) self.printCheckArgs(request) page = """<form action="" method="post" \ onsubmit="return check_args(this)"><div> """ for i in self.fields: value = args.get(i['name'], row[0][i['pos']]) required = i['required'] and "<sup>*</sup>" or "" text = i['isPass'] and "password" or "text" #dejo los campos password en blanco por defecto. if value is None or i['name']=='password' or i['name']=='password2': value = '' page += """<label for='%s'>%s%s: <input type='%s' name='%s' size="20" value='%s' maxlength="%d" id="%s" /></label><br/>\n""" % (i['name'], _(i['desc']), required, text, i['name'], value, i['maxlength'], i['name']) page += """<input type="submit" id="submit" name="submit" value=\"""" + _('Guardar') + """\"/>""" if userId > 0: page += """<input type="hidden" name="user_id" value='%s'/>""" % userId page += """</div></form>""" request.write(page) return
class WebPupilEdit(Resource): def __init__(self): _ = dummyTranslator self.fields = [{'name': 'username', 'pos': 1, 'desc': _('Nombre de usuario'), \ 'required': True, 'type': 'text', 'maxlength': 80, 'query': "person"}, {'name': 'password', 'pos': 2, 'desc': _('Contrasena'), 'required': False, \ 'type': 'password', 'maxlength': 80, 'query': "person"}, {'name': 'password2', 'pos': 2, 'desc': _('Repita contrasena'), 'required': False, \ 'type': 'password', 'maxlength': 80, 'query': ""}, {'name': 'first_name', 'pos': 3, 'desc': _('Nombre'), 'required': True, \ 'type': 'text', 'maxlength': 255, 'query': "person"}, {'name': 'last_name', 'pos': 4, 'desc': _('Apellido'), 'required': True, \ 'type': 'text', 'maxlength': 255, 'query': "person"}, {'name': 'email', 'pos': 5, 'desc': _('eMail'), 'required': True, \ 'type': 'text', 'maxlength': 255, 'query': "person"}] self.db = DBConnect() self.render_POST = self.render_GET self.template = WebTemplates() Resource.__init__(self) def getChild(self, path, request): if path == "": return self else: return static.File.childNotFound def render_GET(self, request): d = defer.maybeDeferred(getTranslatorFromSession, request) d.addCallback(self.doAuthentication, request) return server.NOT_DONE_YET def doAuthentication(self, trans, request): session = request.getSession() _ = session._ request.write(self.template.startPage(session, _('Pagina del Alumno'))) d = defer.maybeDeferred(lambda :None) msg = '<h2>' + _('Informacion de alumno') + '</h2>' msg += _('Recuerda que los campos indicados con <sup>*</sup> son obligatorios<br>') msg += _('Si desea conservar la contraseña actual deje los campos en blanco') if not hasattr(session, 'username'): request.write(self.template.notAuthenticated(session)) elif session.kind == ADMIN: if 'user_id' in request.args.keys() and 'pupil_id' in request.args.keys(): try: user_id = int(request.args.get('user_id', [-1])[0]) pupil_id = int(request.args.get('pupil_id')[0]) # La función que procesa e imprime el contenido de la pagina self.printContent(request, d, user_id, pupil_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('user_id y pupil_id deberian ser enteros'))) else: request.write(self.template.unexpectedArguments(session, \ _('Faltan argumentos requeridos'))) # 3) Si es Cliente, ve solo su alumno elif session.kind == CLIENT: user_id = session.userId if 'pupil_id' in request.args.keys(): try: pupil_id = int(request.args.get('pupil_id')[0]) # La función que imprime el contenido, pero con otros argumentos self.printContent(request, d, user_id, pupil_id, msg) except ValueError: request.write(self.template.unexpectedArguments(session, \ _('pupil_id deberia ser entero'))) else: request.write(self.template.unexpectedArguments(session, \ _('Faltan argumentos requeridos'))) else: # 4) Si no es ni ni Admin, ni Cliente es alguien que no está # autorizado a modificar alumnos request.write(self.template.notAuthorized(session)) # 5) Se termina la página d.addCallback(lambda a: request.write(self.template.finishPage(session))) d.addCallback(lambda a: request.finish()) return d def checkRequest(self, d, request): session = request.getSession() _ = session._ args = dict([(i, request.args[i][0]) for i in request.args.keys()]) if "submit" in request.args.keys(): for value in self.fields: if value['name'] not in args.keys(): args[value['name']] = '' d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Falta el argumento \'%s\'') % value['name']))) elif len(args[value['name']]) > value['maxlength']: args[value['name']] = (args[value['name']][:value['maxlength']]) d.addCallback(lambda a: \ request.write(self.template.unexpectedArguments(session, \ _('Longitud excesiva del argumento \'%s\'') % value['name']))) if(args['password'] != args['password2']): request.write(self.template.unexpectedArguments(session, \ _('Las contrasenas no coinciden'))) if re.match("^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$", args['email']) == None: request.write(self.template.unexpectedArguments(session, \ _('El email ingresado es incorrecto'))) return args def printContent(self, request, d, userId, pupilId, msg): # si se estan enviando datos _ = request.getSession()._ args = self.checkRequest(d, request) if "submit" in args.keys(): # si tenemos que actualizar query = "select username from person where username = %s and id <> %d" d.addCallback(lambda a: self.db.db.runQuery(query, (args['username'], pupilId))) d.addCallback(self._updateUser, request, pupilId, args, userId) else: d.addCallback(lambda a:userId) d.addCallback(self._requestData, request, pupilId, msg) d.addErrback(self.printError, request) d.addCallback(self.printForm, request, args, userId) def _updateUser(self, row, request, pupilId, args, userId): _ = request.getSession()._ if len(row) == 0: person = [] #encripto el password if args['password']!="": args['password'] = sha.new(args['password']).hexdigest() for field in self.fields: if field['query'] == "person": #si los password estan en blanco no se incluyen en la query de actualizacion if not(field['name']=='password' and args['password']==""): person.append(field['name'] + " = '" + args[field['name']] + "'") person = ", ".join(person) update_person = "update person set " + person + " where id = %s" d = self.db.db.runOperation(update_person, (pupilId,)) d.addCallback(lambda a: request.write('<div class="message">' + \ _('Datos actualizados con exito') + '</div>') or userId) else: return failure.Failure(_('El usuario %s ya existe en el sistema') % \ row[0][0]) return d def _requestData(self, userId, request, pupilId, msg): request.write(msg) # no se estan mandando datos, se los solicita query = "select person.id, username, password, first_name, last_name, \ email from person, pupil, client where person.id = pupil.id and \ client.id = pupil.fk_client and client.id = %s and person.id = %s" d = self.db.db.runQuery(query, (userId, pupilId)) return d def printError(self, failure, request): """Imprime el error de failure y genera una fila vacia para la consulta de la base de datos """ session = request.getSession() d = defer.maybeDeferred(lambda :None) d.addCallback(lambda a: request.write("""<div class="error"> %s </div>""" % \ failure.getErrorMessage())) d.addCallback(self.getEmptyRow, 6) return d def getEmptyRow(self, data, size): """Devuelve una consulta vacia de tamaño size""" return [[""] * size] def printCheckArgs(self, request): """Para cada diccionario de la lista fields chequea si el campo es obligatorio y arma la funcion de JavaScript para el chequeo de datos. Agrega a continuacion el chequeo de que las contraseñas coincidan TO-DO: si las contraseñas estan en blanco, ignorar el update. """ _ = request.getSession()._ page = """ <script type="text/javascript" src="/static/js/valid.js"></script> <script type="text/javascript">\n function check_args(form){ message='';""" for i in self.fields: if i['required']: page += """if(form.%s.value == "") message += "- """ % i['name'] + \ _('El campo %s es obligatorio') % _(i['desc']) + """\\n";\n""" page += """if(form.password.value != form.password2.value) message += \"- """ + _('Las contrasenas no coinciden') + """\";\n""" page += """if(!isEmailAddress(form.email)) message += \"- """ + _('El email ingresado es incorrecto') + """\"; if(message){ alert(" """ + _('Error en el ingreso de datos:') + """\\n"+message+"\\n"); return false; }else{ return true; } } </script> """ request.write(page) return def printForm(self, row, request, args, userId): """Para cada diccionario de la lista fields arma el campo del formulario correspondiente. """ session = request.getSession() _ = session._ if len(row) == 0: request.write(self.template.unexpectedArguments(session, \ _('El usuario solicitado no existe'))) row = self.getEmptyRow(None, 6) self.printCheckArgs(request) page = """<form action="" method="post" \ onsubmit="return check_args(this)"><div> """ for i in self.fields: value = args.get(i['name'], row[0][i['pos']]) required = i['required'] and "<sup>*</sup>" or "" text = i['type'] #dejo los campos password en blanco por defecto. if value is None or i['name']=='password' or i['name']=='password2': value = '' page += """<label for="%s">%s%s: <input type="%s" name="%s" size="20" value="%s" maxlength="%d" id="%s" /></label><br/>\n""" % \ (i['name'], _(i['desc']), required, text, i['name'], value, i['maxlength'], i['name']) request.write(page) request.write("""<input type="submit" name="submit" id="submit" value=\"""" + \ _('Guardar') + """\"/>""") if userId > 0: request.write("""<input type="hidden" name="user_id" value="%s"/>""" % userId) request.write("""</div></form>""") return