From aad437e6aba4d2310e5d6b799f8aa27f60b9f387 Mon Sep 17 00:00:00 2001
From: Marcos Viera <mviera@fing.edu.uy>
Date: Tue, 30 Mar 2021 15:48:50 -0300
Subject: [PATCH] no para autenticacion, scripts para agregar users y grupos,
 bugfix compilacion incluyendo compartidos, bugfix de seguridad

---
 .../app/layout/archivos/archivos.component.ts |  1 +
 .../app/layout/matefun/matefun.component.ts   |  9 +--
 .../app/shared/services/session.service.ts    | 38 ++++++++++-
 Servidor JEE/WebContent/index.html            |  2 +-
 .../java/edu/proygrado/ejb/CommandsBean.java  |  7 +-
 .../java/edu/proygrado/ejb/GruposEJB.java     | 33 ++++++++++
 .../java/edu/proygrado/ejb/InvitadoEJB.java   | 18 ++---
 .../main/java/edu/proygrado/ejb/LoginEJB.java | 65 +++++++++++++++----
 .../java/edu/proygrado/ejb/UsuarioEJB.java    | 31 ++++++++-
 .../matefun/AuthenticationFilter.java         |  6 +-
 .../servicios/ghci/WebSocketEndpoint.java     |  2 +-
 .../proygrado/servicios/grupos/GruposRS.java  | 24 +++++--
 .../proygrado/servicios/login/LoginRS.java    | 16 ++++-
 .../servicios/usuario/UsuarioRS.java          |  3 +-
 addToGrupo.sh                                 | 39 +++++++++++
 addUsers.sh                                   | 25 +++++--
 16 files changed, 269 insertions(+), 50 deletions(-)
 create mode 100644 addToGrupo.sh

diff --git a/Frontend Angular 4/src/app/layout/archivos/archivos.component.ts b/Frontend Angular 4/src/app/layout/archivos/archivos.component.ts
index 4a4c1e80..187ed08e 100755
--- a/Frontend Angular 4/src/app/layout/archivos/archivos.component.ts	
+++ b/Frontend Angular 4/src/app/layout/archivos/archivos.component.ts	
@@ -466,6 +466,7 @@ export class ArchivosComponent {
 			this.directorioActual=arch;
 		}else {
 			this.sessionService.setDirectorioActual(this.directorioActual);
+			this.sessionService.setArchivosCompartidos(this.archivosCompartidos);
 			this.sessionService.cargarDependencias(arch);
 		}
 		this.archivoSeleccionado = arch;	
diff --git a/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts b/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts
index cda41e0e..d5cce103 100755
--- a/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts	
+++ b/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts	
@@ -113,7 +113,7 @@ export class MateFunComponent {
     };
     configCodeMirrorDefinicion: any = {};
     themes = ['3024-day', '3024-night', 'abcdef', 'ambiance-mobile', 'ambiance', 'base16-dark', 'base16-light', 'bespin', 'blackboard', 'cobalt', 'colorforth', 'dracula', 'duotone-dark', 'duotone-light', 'eclipse', 'elegant', 'erlang-dark', 'hopscotch', 'icecoder', 'isotope', 'lesser-dark', 'liquibyte', 'material', 'mbo', 'mdn-like', 'midnight', 'monokai', 'neat', 'neo', 'night', 'panda-syntax', 'paraiso-dark', 'paraiso-light', 'pastel-on-dark', 'railscasts', 'rubyblue', 'seti', 'solarized', 'the-matrix', 'tomorrow-night-bright', 'tomorrow-night-eighties', 'ttcn', 'twilight', 'vibrant-ink', 'xq-dark', 'xq-light', 'yeti', 'zenburn']
-    version: string = npm.version;
+    version: string = "3.0";//npm.version;
 
     constructor(
         private haskellService: HaskellService,
@@ -322,7 +322,8 @@ export class MateFunComponent {
             if (evtobj.keyCode == 90 && evtobj.ctrlKey){
                 //alert("Ctrl+z")
             };
-            if(evtobj.key.toLowerCase() ==="a" && evtobj.ctrlKey){
+	    if (evtobj != null && evtobj.key != null){
+            if( evtobj.key.toLowerCase() ==="a" && evtobj.ctrlKey){
                 componentRef.seleccionarDirectorio();
                 return false;
             }else if(evtobj.key.toLowerCase() ==="e" && evtobj.ctrlKey){
@@ -358,7 +359,8 @@ export class MateFunComponent {
             }  else if(evtobj.key.toLowerCase() ==="p" && evtobj.ctrlKey && !evtobj.altKey){
                 componentRef.runCode();
                 return false;
-            } 
+            }
+	    }
         }
         document.onkeydown = KeyPress;
 
@@ -553,7 +555,6 @@ export class MateFunComponent {
         }else if (!regex.test(this.archivo.nombre)){
             this.notifService.error("Nombre de archivo debe iniciar con mayusula.")
         }else{
-
             var resultado = this.sessionService.cargarDependencias(this.archivo);
             if(resultado["status"]==="miss"){
                 this.ghciService.outputConsole("Error: No se encuentra el archivo " + resultado["nombre"] + "\n");
diff --git a/Frontend Angular 4/src/app/shared/services/session.service.ts b/Frontend Angular 4/src/app/shared/services/session.service.ts
index 84417842..99d79ef1 100755
--- a/Frontend Angular 4/src/app/shared/services/session.service.ts	
+++ b/Frontend Angular 4/src/app/shared/services/session.service.ts	
@@ -9,6 +9,7 @@ export class SessionService {
 	dependencias :any;
 	archivosList :any;
 	directorioActual : any;
+	archivosCompartidos : any;
 	grupos: Grupo[];
 
 	public setArchivo(archivo){
@@ -60,6 +61,13 @@ export class SessionService {
 	public setDirectorioActual(d){
 		this.directorioActual = d;
 	}
+	public setArchivosCompartidos(d){
+		this.archivosCompartidos = d;
+	}
+	public getArchivosCompartidos(){
+		return this.archivosCompartidos;
+	}
+	
 
 	public cargarDependencias(arch){
 			
@@ -79,9 +87,11 @@ export class SessionService {
 		var hijos:any = [];
 		var result : any = {};
 		var resultObject = {};
+		
 		result.id = pivot.id;
 		result.nombre = pivot.nombre;
 		result.contenido = pivot.contenido;
+		archivosRecorridos.push(pivot.nombre);
 		for(var i in contentIncludes){
 			if(!archivosRecorridos.includes(contentIncludes[i])){
 				try{
@@ -90,11 +100,23 @@ export class SessionService {
 						return a.nombre === contentIncludes[i];
 					}
 					)[0];
-					archivosRecorridos.push(pivot.nombre);	
+					//archivosRecorridos.push(pivot.nombre);	
+				} catch(err){
+					
+				}
+				try{
+					var archivo2 = this.archivosCompartidos.filter(
+					function(a){
+						return a.nombre === contentIncludes[i];
+					}
+					)[0];
+					//archivosRecorridos.push(pivot.nombre);	
 				} catch(err){
 					
 				}
+				
 				if(archivo){
+				
 					var resultado_ = this.buildDependenciesTree(archivo,archivosRecorridos);
 					if(resultado_["status"]==="ok"){
 						hijos.push(resultado_["dependencies"]);						
@@ -103,10 +125,22 @@ export class SessionService {
 					}
 
 
-				}else {
+				} else {
+
+ 				      if(archivo2){
+				
+						var resultado_ = this.buildDependenciesTree(archivo2,archivosRecorridos);
+						if(resultado_["status"]==="ok"){
+							hijos.push(resultado_["dependencies"]);						
+						} else{
+						  return resultado_;
+						}
+				      } else {
+
 					resultObject["status"] = "miss";
 					resultObject["nombre"] = contentIncludes[i];
 					return resultObject;
+				      }
 				}
 			}
 		}
diff --git a/Servidor JEE/WebContent/index.html b/Servidor JEE/WebContent/index.html
index 9260a74c..48de9477 100644
--- a/Servidor JEE/WebContent/index.html	
+++ b/Servidor JEE/WebContent/index.html	
@@ -1,4 +1,4 @@
 <!doctype html><html><head><meta charset="utf-8"><title>Proyecto MateFun</title><base href="/"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><!-- despues lo saco de aca --><!-- <link rel="stylesheet" type="text/css" href="node_modules/codemirror/addon/hint/show-hint.css">  --><script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script><script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" crossorigin="anonymous"></script><!--
     <script src="https://wzrd.in/standalone/function-plot@1.18.1" crossorigin="anonymous"></script>
 
-    --><link href="styles.1dc6715c59e708068692.bundle.css" rel="stylesheet"/></head><body><app-root><div class="loading"><div class="loading-bar"></div><div class="loading-bar"></div><div class="loading-bar"></div><div class="loading-bar"></div><div class="loading-bar"></div></div></app-root><script type="text/javascript" src="inline.427fe152dbac388e02e1.bundle.js"></script><script type="text/javascript" src="polyfills.d50ac7c762e2eb4097d9.bundle.js"></script><script type="text/javascript" src="scripts.d01654a9119059a68b2b.bundle.js"></script><script type="text/javascript" src="vendor.d3c1758890cc7548bc7b.bundle.js"></script><script type="text/javascript" src="main.94941e96a5bd65bdeb71.bundle.js"></script></body></html>
\ No newline at end of file
+    --><link href="styles.1dc6715c59e708068692.bundle.css" rel="stylesheet"/></head><body><app-root><div class="loading"><div class="loading-bar"></div><div class="loading-bar"></div><div class="loading-bar"></div><div class="loading-bar"></div><div class="loading-bar"></div></div></app-root><script type="text/javascript" src="inline.508b8662687ccc0832e0.bundle.js"></script><script type="text/javascript" src="polyfills.d50ac7c762e2eb4097d9.bundle.js"></script><script type="text/javascript" src="scripts.d01654a9119059a68b2b.bundle.js"></script><script type="text/javascript" src="vendor.d3c1758890cc7548bc7b.bundle.js"></script><script type="text/javascript" src="main.98a532e0b59061522b75.bundle.js"></script></body></html>
\ No newline at end of file
diff --git a/Servidor JEE/src/main/java/edu/proygrado/ejb/CommandsBean.java b/Servidor JEE/src/main/java/edu/proygrado/ejb/CommandsBean.java
index 0cde2b15..6d517021 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/ejb/CommandsBean.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/ejb/CommandsBean.java	
@@ -81,7 +81,7 @@ public class CommandsBean {
 	}
 
 	public void ejecutarComandos(String comandos, Session session) {
-		System.out.println("Ejecuto " + this.hashCode());
+	    //System.out.println("Ejecuto " + this.hashCode());
 		try {
 			JsonReader jsonReader = Json.createReader(new StringReader(comandos));
 			JsonObject comandoJson = jsonReader.readObject();
@@ -112,9 +112,11 @@ public class CommandsBean {
 				int fileId = comandoJson.getInt("load");
 
 				JsonArray dependenciasJsonArray = comandoJson.getJsonArray("dependencias");
+				
 				Iterator<JsonValue> iter = dependenciasJsonArray.iterator();
 				while (iter.hasNext()) {
 					JsonValue val = iter.next();
+					System.out.println("Dependencia: "+ val.toString());
 					int fileId_ = Integer.valueOf(val.toString());
 					try {
 						ArchivoDTO archivo;
@@ -137,10 +139,10 @@ public class CommandsBean {
 								file = new File(fullPathMatefunTmp + this.cedula + "/"
 										+ corregirNombreArchivo(archivo.getNombre()) + ".mf");
 							}
+
 							file.getParentFile().mkdirs();
 							FileWriter writer = new FileWriter(file);
 							writer.write(contenido);
-							
 							writer.flush();
 							writer.close();
 						} catch (IOException e) {
@@ -148,6 +150,7 @@ public class CommandsBean {
 							System.out.println(e.getMessage()); 
 						}
 					} catch (Exception ex) {
+					        System.out.println("Error con archivo: "+ val.toString());
 						Logger.getLogger(CommandsBean.class.getName()).log(Level.SEVERE, null, ex);
 					}
 
diff --git a/Servidor JEE/src/main/java/edu/proygrado/ejb/GruposEJB.java b/Servidor JEE/src/main/java/edu/proygrado/ejb/GruposEJB.java
index b0060953..d7b84892 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/ejb/GruposEJB.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/ejb/GruposEJB.java	
@@ -7,10 +7,18 @@ import javax.ejb.Stateless;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 
+import edu.proygrado.matefun.MatefunException;
 import edu.proygrado.dto.GrupoDTO;
 import edu.proygrado.modelo.Archivo;
 import edu.proygrado.modelo.Grupo;
 import edu.proygrado.modelo.GrupoPK;
+import edu.proygrado.modelo.Liceo;
+import edu.proygrado.modelo.LiceoPK;
+import edu.proygrado.modelo.Alumno;
+import edu.proygrado.modelo.Docente;
+import edu.proygrado.modelo.Usuario;
+
+
 
 @Stateless
 public class GruposEJB {
@@ -18,6 +26,31 @@ public class GruposEJB {
 	@PersistenceContext(unitName = "matefunDS")
 	private EntityManager em;
 
+        public String agregarUsuarioGrupo(String cedula, GrupoDTO grupoDTO) throws Exception {
+		Usuario usuario = em.find(Usuario.class, cedula);
+		if(usuario!=null){
+        		LiceoPK lpk = new LiceoPK(grupoDTO.getLiceoId());
+			GrupoPK gpk = new GrupoPK(grupoDTO.getAnio(), grupoDTO.getGrado(), grupoDTO.getGrupo(), lpk);
+			Grupo grupo = em.find(Grupo.class, gpk);
+			if (grupo==null){
+			    System.out.println("creando grupo");
+			    grupo = new Grupo(gpk);
+			    em.persist(grupo);
+			}
+			if (usuario instanceof  Alumno) {
+			    grupo.addAlumno((Alumno) usuario);
+			}
+			else {
+			    ((Docente)usuario).addGrupoAsignado(grupo);
+			}
+		}
+		else{
+
+			throw new MatefunException("No existe el usuario de cedula "+cedula);
+		}
+		return ("Usuario " + cedula + "agregado a grupo.");
+	}
+    
 	public void agregarArchivoGrupo(long archivoId, GrupoPK grupoPK) throws Exception {
 		Grupo grupo = em.find(Grupo.class, grupoPK);
 		if (grupo == null) {
diff --git a/Servidor JEE/src/main/java/edu/proygrado/ejb/InvitadoEJB.java b/Servidor JEE/src/main/java/edu/proygrado/ejb/InvitadoEJB.java
index 8b38d9d1..175397a3 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/ejb/InvitadoEJB.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/ejb/InvitadoEJB.java	
@@ -37,7 +37,7 @@ public class InvitadoEJB {
 	private Map<String, InvitadoSesion> sesiones = new HashMap<>();
 	
 	public Usuario getUsuario(String token){
-		System.out.println("getUsuario"+token);
+		System.out.println("getUsuario "+token);
 		InvitadoSesion invitadoSesion = sesiones.getOrDefault(token, null);
 		if (invitadoSesion != null) {
 			return invitadoSesion.getUsuario();
@@ -47,7 +47,7 @@ public class InvitadoEJB {
 	}
 
 	public void setUsuario(String token, Usuario usuario){
-		System.out.println("setUsuario"+token);
+		System.out.println("setUsuario "+token);
 		sesiones.put(token,new InvitadoSesion(usuario));
 	}
 	
@@ -56,7 +56,7 @@ public class InvitadoEJB {
 	}
 	
 	public List<ArchivoDTO> getArchivosUsuario(String token, String cedula) throws Exception {
-		System.out.println("getArchivosUsuario"+token);
+		System.out.println("getArchivosUsuario "+token);
 		InvitadoSesion invitadoSesion = sesiones.getOrDefault(token, null);
 		if (invitadoSesion == null) {
 			throw new NotAuthorizedException("No autorizado");
@@ -81,7 +81,7 @@ public class InvitadoEJB {
 	}
 
 	public List<ArchivoDTO> getArchivosCompartidosAlumno(String token, String cedula) throws Exception {
-		System.out.println("getArchivosCompartidosAlumno"+token);
+		System.out.println("getArchivosCompartidosAlumno "+token);
 		InvitadoSesion invitadoSesion = sesiones.getOrDefault(token, null);
 		if (invitadoSesion == null) {
 			throw new NotAuthorizedException("No autorizado");
@@ -117,7 +117,7 @@ public class InvitadoEJB {
 
 	
 	public ArchivoDTO crearArchivo(String token, ArchivoDTO archivoDTO) throws Exception {
-		System.out.println("crearArchivo"+token);
+		System.out.println("crearArchivo "+token);
 		InvitadoSesion invitadoSesion = sesiones.getOrDefault(token, null);
 		if (invitadoSesion == null) {
 			throw new NotAuthorizedException("No autorizado");
@@ -174,7 +174,7 @@ public class InvitadoEJB {
 	}
 
 	public ArchivoDTO getCopiaCompartido(String token, String cedula, Long archivoId) throws Exception {
-		System.out.println("getCopiaCompartido"+token);
+		System.out.println("getCopiaCompartido "+token);
 		InvitadoSesion invitadoSesion = sesiones.getOrDefault(token, null);
 		if (invitadoSesion == null) {
 			throw new NotAuthorizedException("No autorizado");
@@ -227,7 +227,7 @@ public class InvitadoEJB {
 	}
 
 	public ArchivoDTO editarArchivo(String token, long archivoId, ArchivoDTO archivoDTO) throws Exception {
-		System.out.println("editarArchivo"+token);
+		System.out.println("editarArchivo "+token);
 		InvitadoSesion invitadoSesion = sesiones.getOrDefault(token, null);
 		if (invitadoSesion == null) {
 			throw new NotAuthorizedException("No autorizado");
@@ -267,7 +267,7 @@ public class InvitadoEJB {
 	}
 
 	public void eliminarArchivo(String token, long archivoId) throws Exception {
-		System.out.println("eliminarArchivo"+token);
+		System.out.println("eliminarArchivo "+token);
 		InvitadoSesion invitadoSesion = sesiones.getOrDefault(token, null);
 		if (invitadoSesion == null) {
 			throw new NotAuthorizedException("No autorizado");
@@ -287,7 +287,7 @@ public class InvitadoEJB {
 	}
 	
 	public ArchivoDTO getArchivo(String token, long archivoId) throws Exception {
-		System.out.println("getArchivo"+token);
+		System.out.println("getArchivo "+token);
 		InvitadoSesion invitadoSesion = sesiones.getOrDefault(token, null);
 		if (invitadoSesion == null) {
 			throw new NotAuthorizedException("No autorizado");
diff --git a/Servidor JEE/src/main/java/edu/proygrado/ejb/LoginEJB.java b/Servidor JEE/src/main/java/edu/proygrado/ejb/LoginEJB.java
index 5d9a201c..a313d71a 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/ejb/LoginEJB.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/ejb/LoginEJB.java	
@@ -24,6 +24,7 @@ import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.TypedQuery;
+import javax.persistence.Query;
 import javax.servlet.ServletContext;
 import javax.transaction.UserTransaction;
 import javax.ws.rs.client.ClientBuilder;
@@ -50,7 +51,7 @@ import edu.proygrado.modelo.Liceo;
 import edu.proygrado.modelo.LiceoPK;
 import edu.proygrado.modelo.Sesion;
 import edu.proygrado.modelo.Usuario;
-
+    
 /**
  *
  * @author gonzalo
@@ -58,7 +59,6 @@ import edu.proygrado.modelo.Usuario;
 @Stateless
 @TransactionManagement(value=TransactionManagementType.BEAN)
 
-
 public class LoginEJB {
 	
 	@Inject
@@ -76,6 +76,12 @@ public class LoginEJB {
 	@Resource
 	private UserTransaction userTransaction;
 
+    	public boolean validarDocente(String token){
+		Sesion sesion = em.find(Sesion.class,token);
+		Date now = new Date();
+		return (sesion != null && sesion.getUsuario() instanceof Docente);
+	}
+
 	public boolean validarSesion(String token){
 		Sesion sesion = em.find(Sesion.class,token);
 		Date now = new Date();
@@ -117,21 +123,52 @@ public class LoginEJB {
 	    cal.setTime(new Date());
 	    cal.add(Calendar.HOUR_OF_DAY, -1);	    
 		Date horaExpiracion = cal.getTime();
+
+		try{
+		    userTransaction.begin();
+		    Query query = em.createQuery("delete from Sesion where timestamp < :horaExpiracion")
+			.setParameter("horaExpiracion", horaExpiracion);
+		    query.executeUpdate();
+		    userTransaction.commit();
+		}
+                catch(Exception e) {
+				System.out.println("Error borrando sesiones expiradas");
+		}
+
+		    /*
 		List<Sesion> sesiones = em.createQuery("select s from Sesion s where s.timestamp < :horaExpiracion", Sesion.class)
 				.setParameter("horaExpiracion", horaExpiracion)
 				.getResultList();
 		try{
 		userTransaction.begin();
 		for(Sesion sesion:sesiones){
+		    
+		    String tk = sesion.getToken();
+		    System.out.println("Borrando sesion: " + tk);
 			em.remove(sesion);
+		    System.out.println("Sesion borrada: " + tk);
+		    
 		}
 		userTransaction.commit();
 		}
                 catch(Exception e) {
 				System.out.println("Error borrando sesiones expiradas");
-			}
+				e.printStackTrace();
+		}*/
 	}
-	
+
+    	public String logout(String cedula, String token) throws MatefunException {
+	    Sesion sesion = em.find(Sesion.class,token);
+	    String user  = sesion.getUsuario().getCedula();
+	    if (user.equals(cedula)) {
+		invitadoEJB.eliminarRecursos(token);
+		return ("Usuario cerrado.");
+	    }   
+	    else {
+		return ("Esta intentando cerrar a otro usuario: " + cedula + " != " + user);
+	    }
+	}
+
 	public UsuarioDTO login(String cedula, String password) throws MatefunException {
 		Usuario usuario;
 
@@ -152,11 +189,11 @@ public class LoginEJB {
 			invitadoEJB.setUsuario(tokenAuth, usuario);
 			return new UsuarioDTO(tokenAuth, usuario);
 		}
-
-		//Si no se encuentra configuracion para Moodle se notifica que las credenciales son incorrectas.
-		if(getMoodleAPIEndpoint() == null || getMoodleDefaultGroup() == null){
+		else {
 			throw new MatefunException("Usuario o contraseña incorrecto");
 		}
+		
+		/*
 		String token = null;
 		token = getTokenMoodle(cedula, password);
 		System.out.println("Obtengo token desde moodle");
@@ -263,8 +300,14 @@ public class LoginEJB {
 			invitadoEJB.setUsuario(tokenAuth, nuevoDesdeMoodle);
 			return new UsuarioDTO(tokenAuth, nuevoDesdeMoodle);
 		}
+
+     */
+
+
 	}
-	
+
+    /*    
+    
 	private String getMoodleAPIEndpoint(){
 		try{
 			String pathMatefunProperties = context.getRealPath("/WEB-INF/matefun.properties");
@@ -387,7 +430,7 @@ public class LoginEJB {
 		}
 
 	}
-
+    */
 	private static String generateHash(String input) {
 		StringBuilder hash = new StringBuilder();
 
@@ -473,11 +516,11 @@ public class LoginEJB {
 	}
 
 	private String getContenidoArchivoManual() {
-		return "{- EL LENGUAJE MateFun -}\n\n{-\n# Definición de Funciones\n\nPara definir una función se debe indicar su signatura y la ecuación que la define.  La signatura se compone del nombre de la función, el conjunto dominio y el codominio.  La ecuación se define dando el nombre de la función, los parámetros y el cuerpo de la función. Por ejemplo, la siguiente función retorna el cuadrado de un número real:\n-}\ncuad :: R -> R\ncuad(x) = x * x\n\n{-\nEl nombre de la función es cuad, el dominio es R, el codominio R, la variable independiente x y el cuerpo la expresión x * x. \nEl conjunto R de los números reales es uno de los conjuntos primitivos del lenguaje. Los otros conjuntos elementales primitivos son Fig (figuras) y Color.\n-}\n\n{-\nLas expresiones, que definen el cuerpo de una función, se pueden componer de literales, variables, aplicación de operadores infijos (por ejemplo, para R están definidos +, -, *, / y ^), aplicación de operadores prefijos (-) y aplicación de funciones. Por ejemplo, la siguiente función calcula el área de un círculo en función de su radio:\n-}\narea_circ :: R -> R\narea_circ(r) = 3.14 * cuad(r)\n\n{-\nNotar que al definir area_circ se utiliza la función cuad, definida anteriormente.\n-}\n\n{-\n# Funciones con múltiples variables\n\nSe pueden definir funciones con más de una variable independiente, para esto se utiliza el conjunto producto cartesiano (y su generalización n-tupla). Por ejemplo la siguiente función calcula el área del triángulo dadas su base y altura:\n-}\n\narea_tria :: R X R -> R\narea_tria(base,altura) = (base * altura) / 2\n\n{-\n# Funciones definidas por casos\n\nLa ecuación de la función se puede definir por casos, estableciendo la condición de cada caso y por último un caso por defecto (si no se cumple ninguna condición), de manera que la función sea total sobre su dominio. Por ejemplo, la siguiente función calcula el valor absoluto de un real:\n-}\nabs :: R -> R\nabs(x) =  x si x >= 0\n       o -x\n\n{-\nLas condiciones para los casos se definen como comparaciones (==,/=,>,>=,<,<=) entre expresiones. \n-}\nmax :: R X R -> R\nmax(x,y) = x si x >= y\n         o y\n\n{-\nTambién se puede definir una condición como una conjunción de condiciones entre paréntesis y separadas con comas. Por ejemplo:\n-}\nmax3 :: R X R X R -> R\nmax3(x,y,z) = x si (x >= y, x >=z)\n            o y si y >= z\n            o z\n{-\nEsta función se puede leer de la siguiente manera: La función max3 toma tres reales (x,y,z) y retorna x si x es mayor o igual que y y x es mayor o igual que z o (si no se cumple lo anterior) retorna y si y es mayor o igual que z o (si no se cumple ninguna de las anteriores) retorna z. Notar que las condiciones se evalúan de forma secuencial y que una condición sólo se evalúa si las anteriores no se cumplieron.\n-}\n\n{-\n# Definición de Conjuntos\nAdemás de utilizar los conjuntos primitivos, en un programa MateFun se pueden definir nuevos conjuntos. Hay dos formas de definir conjuntos: por Enumeración (o Extensión) y por Comprensión.\n-}\n\n{-\n# Por Enumeración\nPara definir un conjunto por Enumeración se deben listar todos sus componentes. Por ejemplo, si queremos definir el conjunto de los meses:\n-}\nconj Mes = { Enero, Febrero, Marzo\n           , Abril, Mayo, Junio\n           , Julio, Agosto, Setiembre\n           , Octubre, Noviembre, Diciembre }\n{-\nNotar que los nombres de conjuntos y sus elementos empiezan con mayúsculas, mientras que los nombres de funciones y variables empiezan con minúsculas. Esto es una regla del lenguaje.\n-}\n\n{-\nLa siguiente función retorna la cantidad de días que (generalmente) tiene un mes:\n-}\ndias :: Mes -> R\ndias(m) = 31 si m == Enero\n        o 28 si m == Febrero\n        o 31 si m == Marzo\n        o 30 si m == Abril\n        o 31 si m == Mayo\n        o 30 si m == Junio\n        o 31 si m == Julio\n        o 31 si m == Agosto\n        o 30 si m == Setiembre\n        o 31 si m == Octubre\n        o 30 si m == Noviembre\n        o 31\n\n\n{-\n# Por Comprensión\n\nPara definir un conjunto por Comprensión se debe especificar un conjunto base y la condición que deben cumplir los elementos de ese conjunto base para pertenecer al nuevo conjunto que estamos definiendo. Por lo tanto el nuevo conjunto será un subconjunto del conjunto base. Ahora podemos definir el conjunto de los Reales no nulos:\n-}\nconj Rno0 = { x en R | x /= 0 }\n\n{-\nTeniendo este conjunto podemos definir la función inverso como una función total:\n-}\ninverso :: Rno0 -> R\ninverso(x) = 1 / x\n\n{-\nCualquier conjunto puede ser base de un conjunto por comprensión, incluso otro conjunto definido por comprensión. Por ejemplo, si definimos al conjunto de los enteros (Z) como el de los reales que son iguales a su redondeo (red):\n-}\nconj Z = { x en R | red(x) == x }\n\n{-\nLuego podemos definir a los naturales (N) como los enteros mayores o iguales que cero:\n-}\nconj N = { x en Z | x >= 0 }\n\n\npred :: N -> N\npred (x) = x - 1\n\n\n{-\n# Tuplas\nComo hemos visto anteriormente, las tuplas se utilizan para definir funciones con más de una variable independiente. Pero también se pueden manipular tuplas tanto como elementos del dominio como del codominio de una función. Por ejemplo, podemos definir una función que toma un número de mes (del 1 al 12) y retorna un par con el mes y la cantidad de días que tiene: \n-}\nconj NMes = { x en N | (x > 0, x <= 12) }\ninfo_mes :: NMes -> Mes X R\ninfo_mes(m) = (Enero,     dias(Enero))     si m == 1\n            o (Febrero,   dias(Febrero))   si m == 2\n            o (Marzo,     dias(Marzo))     si m == 3\n            o (Abril,     dias(Abril))     si m == 4\n            o (Mayo,      dias(Mayo))      si m == 5\n            o (Junio,     dias(Junio))     si m == 6\n            o (Julio,     dias(Julio))     si m == 7\n            o (Agosto,    dias(Agosto))    si m == 8\n            o (Setiembre, dias(Setiembre)) si m == 9\n            o (Octubre,   dias(Octubre))   si m == 10\n            o (Noviembre, dias(Noviembre)) si m == 11\n            o (Diciembre, dias(Diciembre)) \n            \n\n{-\nPara obtener un componente de una tupla se utiliza el operador de proyección “!”. Por ejemplo la siguiente función toma un número de mes y retorna la cantidad de días que tiene proyectando el segundo componente de la tupla que retorna la función info_mes:\n-}\ndias_mes :: NMes -> R\ndias_mes (m) = info_mes(m) ! 2\n\n\n{- Par Ordenado -}\nconj POrd = { p en R X R | p!1 <= p!2 }\n\npord :: R X R -> POrd\npord (x,y) = (x,y)\n\n\n{-\n# Secuencias\n\nEn ocasiones es útil procesar varios elementos de un mismo conjunto en una función. Para esto se utilizan las secuencias. Dado un conjunto, por ejemplo R, una secuencia, en este caso R*, es una colección ordenada de elementos de ese conjunto en la que se admiten elementos repetidos. Por ejemplo, la secuencia R* se define inductivamente como:\n- la secuencia vacía [R] pertenece a R*\n- si r pertenece a R y s pertenece a R* entonces r:s pertenece a R*\n\nPara obtener los elementos de una secuencia se utilizan las funciones primero, que retorna el primer elemento de una secuencia, y resto, que retorna la secuencia sin su primer elemento. Utilizando secuencias podemos definir la función tienen, que dado un número de días, retorna todos los meses que tienen ese número de días (y la secuencia vacía si ningún mes los tiene):\n-}\ntienen :: R -> Mes*\ntienen(d) = Abril:Junio:\n            Setiembre:Noviembre:[Mes]       si d == 30\n          o Enero:Marzo:Mayo:\n            Julio:Agosto:Octubre:\n            Diciembre:[Mes]                 si d == 31\n          o Febrero:[Mes]                   si d == 28\n          o [Mes]\n\n\n{-\n# Recursión\n\nDada la naturaleza inductiva del conjunto secuencia, es natural que muchas funciones que operan sobre secuencias se definan usando recursión.\nPor ejemplo, para obtener la suma de una secuencia de reales, sumamos el primer real de la secuencia con el resultado de la suma del resto (considerando que la secuencia vacía suma 0):\n-}\nsuma :: R* -> R\nsuma(l) = 0 si esVacia(l)\n        o primero(l) + suma(resto(l))\n\n{-\nDe forma similar, si queremos obtener el largo de una secuencia:\n-}\nlargo :: R* -> R\nlargo(l) = 0 si esVacia(l)\n        o 1 + largo(resto(l))\n\n\n{-\nO el máximo de una secuencia no vacía de reales:\n-}\nconj RSeqNV = { l en R* | largo(l) /= 0 }\n\nmaximo :: RSeqNV -> R\nmaximo (l) = primero(l) si esVacia(resto(l))\n           o max(primero(l),maximo(resto(l)))\n\n{-\nPor supuesto que la recursión no se limita sólo a las secuencias, por ejemplo la función factorial se define como una recursión sobre los naturales:\n-}\nfactorial :: N -> N\nfactorial (n) = 1 si n == 0\n              o n * factorial(n-1)\n\ncontramano :: R -> Fig\ncontramano(x) = juntar(color(circ(x),Rojo),rect(x,2))\n\n\nrodar :: Fig -> Fig*\nrodar (f) = f:rotar(f,45):rotar(f,90):rotar(f,135):\n            rotar(f,180):rotar(f,225):rotar(f,270):\n            rotar(f,315):[Fig]\n";
+		return "{- EL LENGUAJE MateFun -}\n\n{-\n# Definición de Funciones\n\nPara definir una función se debe indicar su signatura y la ecuación que la define.  La signatura se compone del nombre de la función, el conjunto dominio y el codominio.  La ecuación se define dando el nombre de la función, los parámetros y el cuerpo de la función. Por ejemplo, la siguiente función retorna el cuadrado de un número real:\n-}\ncuad :: R -> R\ncuad(x) = x * x\n\n{-\nEl nombre de la función es cuad, el dominio es R, el codominio R, la variable independiente x y el cuerpo la expresión x * x. \nEl conjunto R de los números reales es uno de los conjuntos primitivos del lenguaje. Los otros conjuntos elementales primitivos son Fig (figuras) y Color.\n-}\n\n{-\nLas expresiones, que definen el cuerpo de una función, se pueden componer de literales, variables, aplicación de operadores infijos (por ejemplo, para R están definidos +, -, *, / y ^), aplicación de operadores prefijos (-) y aplicación de funciones. Por ejemplo, la siguiente función calcula el área de un círculo en función de su radio:\n-}\narea_circ :: R -> R\narea_circ(r) = 3.14 * cuad(r)\n\n{-\nNotar que al definir area_circ se utiliza la función cuad, definida anteriormente.\n-}\n\n{-\n# Funciones con múltiples variables\n\nSe pueden definir funciones con más de una variable independiente, para esto se utiliza el conjunto producto cartesiano (y su generalización n-tupla). Por ejemplo la siguiente función calcula el área del triángulo dadas su base y altura:\n-}\n\narea_tria :: R X R -> R\narea_tria(base,altura) = (base * altura) / 2\n\n{-\n# Funciones definidas por casos\n\nLa ecuación de la función se puede definir por casos, estableciendo la condición de cada caso y por último un caso por defecto (si no se cumple ninguna condición), de manera que la función sea total sobre su dominio. Por ejemplo, la siguiente función calcula el valor absoluto de un real:\n-}\nabs :: R -> R\nabs(x) =  x si x >= 0\n       o -x\n\n{-\nLas condiciones para los casos se definen como comparaciones (==,/=,>,>=,<,<=) entre expresiones. \n-}\nmax :: R X R -> R\nmax(x,y) = x si x >= y\n         o y\n\n{-\nTambién se puede definir una condición como una conjunción de condiciones entre paréntesis y separadas con comas. Por ejemplo:\n-}\nmax3 :: R X R X R -> R\nmax3(x,y,z) = x si (x >= y, x >=z)\n            o y si y >= z\n            o z\n{-\nEsta función se puede leer de la siguiente manera: La función max3 toma tres reales (x,y,z) y retorna x si x es mayor o igual que y y x es mayor o igual que z o (si no se cumple lo anterior) retorna y si y es mayor o igual que z o (si no se cumple ninguna de las anteriores) retorna z. Notar que las condiciones se evalúan de forma secuencial y que una condición sólo se evalúa si las anteriores no se cumplieron.\n-}\n\n{-\n# Definición de Conjuntos\nAdemás de utilizar los conjuntos primitivos, en un programa MateFun se pueden definir nuevos conjuntos. Hay dos formas de definir conjuntos: por Enumeración (o Extensión) y por Comprensión.\n-}\n\n{-\n# Por Enumeración\nPara definir un conjunto por Enumeración se deben listar todos sus componentes. Por ejemplo, si queremos definir el conjunto de los meses:\n-}\nconj Mes = { Enero, Febrero, Marzo\n           , Abril, Mayo, Junio\n           , Julio, Agosto, Setiembre\n           , Octubre, Noviembre, Diciembre }\n{-\nNotar que los nombres de conjuntos y sus elementos empiezan con mayúsculas, mientras que los nombres de funciones y variables empiezan con minúsculas. Esto es una regla del lenguaje.\n-}\n\n{-\nLa siguiente función retorna la cantidad de días que (generalmente) tiene un mes:\n-}\ndias :: Mes -> R\ndias(m) = 31 si m == Enero\n        o 28 si m == Febrero\n        o 31 si m == Marzo\n        o 30 si m == Abril\n        o 31 si m == Mayo\n        o 30 si m == Junio\n        o 31 si m == Julio\n        o 31 si m == Agosto\n        o 30 si m == Setiembre\n        o 31 si m == Octubre\n        o 30 si m == Noviembre\n        o 31\n\n\n{-\n# Por Comprensión\n\nPara definir un conjunto por Comprensión se debe especificar un conjunto base y la condición que deben cumplir los elementos de ese conjunto base para pertenecer al nuevo conjunto que estamos definiendo. Por lo tanto el nuevo conjunto será un subconjunto del conjunto base. Ahora podemos definir el conjunto de los Reales no nulos:\n-}\nconj Rno0 = { x en R | x /= 0 }\n\n{-\nTeniendo este conjunto podemos definir la función inverso como una función total:\n-}\ninverso :: Rno0 -> R\ninverso(x) = 1 / x\n\n{-\nCualquier conjunto puede ser base de un conjunto por comprensión, incluso otro conjunto definido por comprensión. Por ejemplo, podemos definir a los naturales (N) como los enteros mayores o iguales que cero:\n-}\nconj N = { x en Z | x >= 0 }\n\n\npred :: N -> N\npred (x) = x - 1\n\n\n{-\n# Tuplas\nComo hemos visto anteriormente, las tuplas se utilizan para definir funciones con más de una variable independiente. Pero también se pueden manipular tuplas tanto como elementos del dominio como del codominio de una función. Por ejemplo, podemos definir una función que toma un número de mes (del 1 al 12) y retorna un par con el mes y la cantidad de días que tiene: \n-}\nconj NMes = { x en N | (x > 0, x <= 12) }\ninfo_mes :: NMes -> Mes X R\ninfo_mes(m) = (Enero,     dias(Enero))     si m == 1\n            o (Febrero,   dias(Febrero))   si m == 2\n            o (Marzo,     dias(Marzo))     si m == 3\n            o (Abril,     dias(Abril))     si m == 4\n            o (Mayo,      dias(Mayo))      si m == 5\n            o (Junio,     dias(Junio))     si m == 6\n            o (Julio,     dias(Julio))     si m == 7\n            o (Agosto,    dias(Agosto))    si m == 8\n            o (Setiembre, dias(Setiembre)) si m == 9\n            o (Octubre,   dias(Octubre))   si m == 10\n            o (Noviembre, dias(Noviembre)) si m == 11\n            o (Diciembre, dias(Diciembre)) \n            \n\n{-\nPara obtener un componente de una tupla se utiliza el operador de proyección “!”. Por ejemplo la siguiente función toma un número de mes y retorna la cantidad de días que tiene proyectando el segundo componente de la tupla que retorna la función info_mes:\n-}\ndias_mes :: NMes -> R\ndias_mes (m) = info_mes(m) ! 2\n\n\n{- Par Ordenado -}\nconj POrd = { p en R X R | p!1 <= p!2 }\n\npord :: R X R -> POrd\npord (x,y) = (x,y)\n\n\n{-\n# Secuencias\n\nEn ocasiones es útil procesar varios elementos de un mismo conjunto en una función. Para esto se utilizan las secuencias. Dado un conjunto, por ejemplo R, una secuencia, en este caso R*, es una colección ordenada de elementos de ese conjunto en la que se admiten elementos repetidos. Por ejemplo, la secuencia R* se define inductivamente como:\n- la secuencia vacía [R] pertenece a R*\n- si r pertenece a R y s pertenece a R* entonces r:s pertenece a R*\n\nPara obtener los elementos de una secuencia se utilizan las funciones primero, que retorna el primer elemento de una secuencia, y resto, que retorna la secuencia sin su primer elemento. Utilizando secuencias podemos definir la función tienen, que dado un número de días, retorna todos los meses que tienen ese número de días (y la secuencia vacía si ningún mes los tiene):\n-}\ntienen :: R -> Mes*\ntienen(d) = Abril:Junio:\n            Setiembre:Noviembre:[Mes]       si d == 30\n          o Enero:Marzo:Mayo:\n            Julio:Agosto:Octubre:\n            Diciembre:[Mes]                 si d == 31\n          o Febrero:[Mes]                   si d == 28\n          o [Mes]\n\n\n{-\n# Recursión\n\nDada la naturaleza inductiva del conjunto secuencia, es natural que muchas funciones que operan sobre secuencias se definan usando recursión.\nPor ejemplo, para obtener la suma de una secuencia de reales, sumamos el primer real de la secuencia con el resultado de la suma del resto (considerando que la secuencia vacía suma 0):\n-}\nsuma :: R* -> R\nsuma(l) = 0 si esVacia(l)\n        o primero(l) + suma(resto(l))\n\n{-\nDe forma similar, si queremos obtener el largo de una secuencia:\n-}\nlargo :: R* -> R\nlargo(l) = 0 si esVacia(l)\n        o 1 + largo(resto(l))\n\n\n{-\nO el máximo de una secuencia no vacía de reales:\n-}\nconj RSeqNV = { l en R* | largo(l) /= 0 }\n\nmaximo :: RSeqNV -> R\nmaximo (l) = primero(l) si esVacia(resto(l))\n           o max(primero(l),maximo(resto(l)))\n\n{-\nPor supuesto que la recursión no se limita sólo a las secuencias, por ejemplo la función factorial se define como una recursión sobre los naturales:\n-}\nfactorial :: N -> N\nfactorial (n) = 1 si n == 0\n              o n * factorial(n-1)\n\ncontramano :: R -> Fig\ncontramano(x) = juntar(color(circ(x),Rojo),rect(x,2))\n\n\nrodar :: Fig -> Fig*\nrodar (f) = f:rotar(f,45):rotar(f,90):rotar(f,135):\n            rotar(f,180):rotar(f,225):rotar(f,270):\n            rotar(f,315):[Fig]\n";
 	}
 
 	private String getContenidoArchivoDiscreto() {
-		return "{- conjunto de los enteros (reales que son iguales a su redondeo) -}\nconj Z = { x en R | x == red(x) }  \n\n{- conjunto de los natulares (enteros mayores o iguales que cero) -}\nconj N = { x en Z | x >= 0  }\n\n{- truncar un real a su parte entera -}\ntrunc :: R -> Z\ntrunc(x) = 0 si (x < 1, x > -1)\n         o trunc(x-1) + 1 si x >= 1\n         o trunc(x+1) - 1\n\n{- valor absoluto de un entero -}\nabs :: Z -> N\nabs(x) =  x  si x >= 0\n       o -x\n\n{- signo de un entero -}\nsigno :: Z -> Z\nsigno(x) =  1  si x >= 0\n         o -1\n\n{- predecesor de un entero -}\npred :: Z -> Z\npred (x) = x - 1\n\n{- sucesor de un entero -}\nsuc :: Z -> Z\nsuc (x) = x + 1\n\n\n{- division de dos enteros -}\ndiv :: Z X Z -> Z\ndiv (x,y) = signo(x) * signo(y) * divN(abs(x),abs(y))\n\n{- division de dos naturales -}\ndivN :: N X N -> N\ndivN (x,y) = 0 si x < y\n           o 1 + divN (x-y,y)\n\n{- resto de division de dos enteros -}\nmod :: Z X Z -> Z\nmod (x,y) = signo(x) * modN(abs(x),abs(y))\n\n{- resto de division de dos naturales -}\nmodN :: N X N -> N\nmodN (x,y) = x si x < y\n           o modN (x-y,y)\n\n\n{- factorial de un natural -}\nfact :: N -> N\nfact (x) = 1 si x == 0\n         o x * fact (x-1)\n";
+		return "{- conjunto de los natulares (enteros mayores o iguales que cero) -}\nconj N = { x en Z | x >= 0  }\n\n{- truncar un real a su parte entera -}\ntrunc :: R -> Z\ntrunc(x) = 0 si (x < 1, x > -1)\n         o trunc(x-1) + 1 si x >= 1\n         o trunc(x+1) - 1\n\n{- valor absoluto de un entero -}\nabs :: Z -> N\nabs(x) =  x  si x >= 0\n       o -x\n\n{- signo de un entero -}\nsigno :: Z -> Z\nsigno(x) =  1  si x >= 0\n         o -1\n\n{- predecesor de un entero -}\npred :: Z -> Z\npred (x) = x - 1\n\n{- sucesor de un entero -}\nsuc :: Z -> Z\nsuc (x) = x + 1\n\n\n{- division de dos enteros -}\ndiv :: Z X Z -> Z\ndiv (x,y) = signo(x) * signo(y) * divN(abs(x),abs(y))\n\n{- division de dos naturales -}\ndivN :: N X N -> N\ndivN (x,y) = 0 si x < y\n           o 1 + divN (x-y,y)\n\n{- resto de division de dos enteros -}\nmod :: Z X Z -> Z\nmod (x,y) = signo(x) * modN(abs(x),abs(y))\n\n{- resto de division de dos naturales -}\nmodN :: N X N -> N\nmodN (x,y) = x si x < y\n           o modN (x-y,y)\n\n\n{- factorial de un natural -}\nfact :: N -> N\nfact (x) = 1 si x == 0\n         o x * fact (x-1)\n";
 	}
 
 	private String getContenidoArchivoContinuo() {
diff --git a/Servidor JEE/src/main/java/edu/proygrado/ejb/UsuarioEJB.java b/Servidor JEE/src/main/java/edu/proygrado/ejb/UsuarioEJB.java
index 4ec0ddbb..aae433b3 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/ejb/UsuarioEJB.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/ejb/UsuarioEJB.java	
@@ -2,6 +2,7 @@ package edu.proygrado.ejb;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Date;
 
 import javax.ejb.Stateless;
 import javax.persistence.EntityManager;
@@ -86,7 +87,9 @@ public class UsuarioEJB {
 			return new BackupDocenteDTO((Docente) usuario);
 		}
 	}
-	
+
+
+    
 	public String restaurarAlumno(BackupAlumnoDTO backupAlumnoDTO) throws MatefunException {
 		Usuario usuario = em.find(Usuario.class, backupAlumnoDTO.getCedula());
 		if(usuario!=null){
@@ -148,6 +151,20 @@ public class UsuarioEJB {
 				em.persist(archivo);
 			}
 		}
+		else {
+		        System.out.println("No hay archivos");
+		    	Archivo root = new Archivo();
+			root.setCreador(alumno);
+			root.setDirectorio(true);
+			root.setNombre("root");
+			root.setFechaCreacion(new Date());
+			root.setEditable(true);
+			root.setEliminado(false);
+			root.setEstado(EstadoArchivo.Edicion);
+			alumno.addArchivo(root);
+			em.persist(root);
+		}
+
 		if(backupAlumnoDTO.getArchivosCompartidos()!=null){
 			for(ArchivoDTO archivoDTO : backupAlumnoDTO.getArchivosCompartidos()){
 				Archivo archivo = new Archivo();
@@ -260,6 +277,18 @@ public class UsuarioEJB {
 				}
 			}
 		}
+		else {
+		    	Archivo root = new Archivo();
+			root.setCreador(docente);
+			root.setDirectorio(true);
+			root.setNombre("root");
+			root.setFechaCreacion(new Date());
+			root.setEditable(true);
+			root.setEliminado(false);
+			root.setEstado(EstadoArchivo.Edicion);
+			docente.addArchivo(root);
+			em.persist(root);
+		}
 		em.persist(docente);
 		return "Docente ingresado. ";
 	}
diff --git a/Servidor JEE/src/main/java/edu/proygrado/matefun/AuthenticationFilter.java b/Servidor JEE/src/main/java/edu/proygrado/matefun/AuthenticationFilter.java
index 55a97d0c..ae5c355c 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/matefun/AuthenticationFilter.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/matefun/AuthenticationFilter.java	
@@ -27,6 +27,7 @@ public class AuthenticationFilter implements ContainerRequestFilter {
 		if(path.contains("login")){
 			return;
 		}
+
 		
 		String authorizationHeader = context.getHeaderString(HttpHeaders.AUTHORIZATION);
 
@@ -39,7 +40,8 @@ public class AuthenticationFilter implements ContainerRequestFilter {
 		// Extrae token de HTTP Authorization header
 		String token = authorizationHeader.substring("Bearer ".length()).trim();
 
-		if(!login.validarSesion(token)){
+		if(!login.validarSesion(token) ||
+		   ((path.contains("usuario") || path.contains("grupo")) && !login.validarDocente(token))){
 			abort(context, Response.Status.UNAUTHORIZED);
 		}else{
 			login.extendSession(token);
@@ -52,4 +54,4 @@ public class AuthenticationFilter implements ContainerRequestFilter {
 				.entity("Error de seguridad").build());
 	}
 
-}
\ No newline at end of file
+}
diff --git a/Servidor JEE/src/main/java/edu/proygrado/servicios/ghci/WebSocketEndpoint.java b/Servidor JEE/src/main/java/edu/proygrado/servicios/ghci/WebSocketEndpoint.java
index c6b79e68..527d6b49 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/servicios/ghci/WebSocketEndpoint.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/servicios/ghci/WebSocketEndpoint.java	
@@ -33,7 +33,7 @@ public class WebSocketEndpoint {
 
 	@OnMessage
 	public String onMessage(String message, Session session) {
-		System.out.println(message);
+	    //System.out.println(message);
 		commandsBean.ejecutarComandos(message, session);
 		JsonObject ackJson = Json.createObjectBuilder().add("tipo", "ack").build();
 		return ackJson.toString();
diff --git a/Servidor JEE/src/main/java/edu/proygrado/servicios/grupos/GruposRS.java b/Servidor JEE/src/main/java/edu/proygrado/servicios/grupos/GruposRS.java
index 4d63b759..cf919365 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/servicios/grupos/GruposRS.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/servicios/grupos/GruposRS.java	
@@ -26,14 +26,15 @@ public class GruposRS {
     private GruposEJB gruposEJB;
 	
 	@POST
-    @Path("/{liceoId}/{anio}/{grado}/{grupo}/archivo")
-    @Produces(MediaType.APPLICATION_JSON)
-    @Consumes(MediaType.APPLICATION_JSON)
-    public void asignarArchivo(@PathParam("liceoId") Long liceoId, @PathParam("anio") Integer anio, @PathParam("grado") Integer grado, @PathParam("grupo") String grupo, ArchivoDTO archivoDTO) throws Exception{
+	@Path("/{liceoId}/{anio}/{grado}/{grupo}/archivo")
+	@Produces(MediaType.APPLICATION_JSON)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public void asignarArchivo(@PathParam("liceoId") Long liceoId, @PathParam("anio") Integer anio,
+				   @PathParam("grado") Integer grado, @PathParam("grupo") String grupo, ArchivoDTO archivoDTO) throws Exception{
 		LiceoPK lpk = new LiceoPK(liceoId);
 		GrupoPK grupoPK = new GrupoPK(anio, grado, grupo, lpk);
-        gruposEJB.agregarArchivoGrupo(archivoDTO.getId(), grupoPK);
-    }
+		gruposEJB.agregarArchivoGrupo(archivoDTO.getId(), grupoPK);
+	}
 	
 	@GET
 	@Produces(MediaType.APPLICATION_JSON)
@@ -41,5 +42,14 @@ public class GruposRS {
 		return this.gruposEJB.getGruposDocente(cedula);
 	}
 	
-	
+
+	@POST
+	@Path("{cedula}/add")
+	@Produces(MediaType.APPLICATION_JSON)
+	@Consumes(MediaType.APPLICATION_JSON)
+	public String agregarUsuarioGrupo(@PathParam("cedula") String cedula, GrupoDTO grupoDTO) throws Exception {
+	    return this.gruposEJB.agregarUsuarioGrupo(cedula,grupoDTO);
+
+	}
+
 }
diff --git a/Servidor JEE/src/main/java/edu/proygrado/servicios/login/LoginRS.java b/Servidor JEE/src/main/java/edu/proygrado/servicios/login/LoginRS.java
index 1a713b4e..32119b59 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/servicios/login/LoginRS.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/servicios/login/LoginRS.java	
@@ -9,6 +9,8 @@ import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.HeaderParam;
 
 import edu.proygrado.dto.CredencialesDTO;
 import edu.proygrado.dto.UsuarioDTO;
@@ -27,11 +29,21 @@ public class LoginRS{
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
     public UsuarioDTO login(CredencialesDTO credenciales) throws MatefunException{
-    	System.out.println("LOGIN:"+loginEJB.toString());
     	UsuarioDTO user=  loginEJB.login(credenciales.getCedula(), credenciales.getPassword());
         return user;
     }
-    
+
+    @POST
+    @Path("{cedula}/logout")
+    @Produces(MediaType.APPLICATION_JSON)
+    @Consumes(MediaType.APPLICATION_JSON)
+    public String logout(@PathParam("cedula") String cedula, @HeaderParam("authorization") String auth) throws MatefunException{
+	String token = auth.substring("Bearer ".length()).trim();
+    	return loginEJB.logout(cedula,token);
+ 
+    }
+
+
     @GET
     @Path("/datosDePrueba")
     public String cargarDatosDePrueba(){
diff --git a/Servidor JEE/src/main/java/edu/proygrado/servicios/usuario/UsuarioRS.java b/Servidor JEE/src/main/java/edu/proygrado/servicios/usuario/UsuarioRS.java
index 16822ae3..24ce8b75 100644
--- a/Servidor JEE/src/main/java/edu/proygrado/servicios/usuario/UsuarioRS.java	
+++ b/Servidor JEE/src/main/java/edu/proygrado/servicios/usuario/UsuarioRS.java	
@@ -59,7 +59,8 @@ public class UsuarioRS {
 	public String restaurarDocente(BackupDocenteDTO backupDocenteDTO) throws MatefunException{
 		return usuarioEJB.restaurarDocente(backupDocenteDTO);
 	}
-	
+
+
 	@DELETE
 	@Path("{cedula}")
 	@Produces(MediaType.TEXT_PLAIN)
diff --git a/addToGrupo.sh b/addToGrupo.sh
new file mode 100644
index 00000000..58333222
--- /dev/null
+++ b/addToGrupo.sh
@@ -0,0 +1,39 @@
+#! /bin/bash
+
+# csv: user,liceo,anio,grupo,grado
+# todas las filas tienen que terminar con enter
+INPUT=usersGroup.csv
+
+SERVER=http:/localhost:8080/servicios #https://www.fing.edu.uy/proyectos/matefun/servicios
+
+# parametros del script: usuario y pass
+read USER # =  $1
+stty -echo
+read PASS # =  $2
+stty echo
+
+
+
+token=$(curl --header "Content-Type: application/json" \
+  --request POST \
+  --data '{"cedula":"'$USER'","password":"'$PASS'"}' \
+  "$SERVER/login" | \
+    python3 -c "import sys, json; print(json.load(sys.stdin)['token'])") 
+
+while IFS=, read -r user liceo anio grupo grado; do
+    echo "user: $user"
+    echo "token: $token"
+    data='{"anio":"'$anio'","grupo":"'$grupo'","grado":"'$grado'","liceoId":"'$liceo'"}'
+    echo $data
+    curl -H "Content-Type: application/json" -H "Authorization: Bearer $token" \
+         --request POST \
+         --data "$data" \
+         "$SERVER/grupo/$user/add" 
+    echo "\n"
+done < $INPUT
+
+curl -H "Content-Type: application/json" -H "Authorization: Bearer $token" \
+  --request POST \
+  "$SERVER/login/$USER/logout" 
+
+
diff --git a/addUsers.sh b/addUsers.sh
index 64a5d511..1a91d7d3 100644
--- a/addUsers.sh
+++ b/addUsers.sh
@@ -1,29 +1,40 @@
 #! /bin/bash
 
-#todas las filas tienen que terminar con enter
+
+# csv: user,nombre,apellido,pass,rol(docente,alumno)
+# todas las filas tienen que terminar con enter
 INPUT=users.csv
 
-SERVER=https://www.fing.edu.uy/proyectos/matefun/servicios
-ROLE=docente #alumno
+SERVER=http:/localhost:8080/servicios #https://www.fing.edu.uy/proyectos/matefun/servicios
+
+# parametros del script: usuario y pass
+read USER # =  $1
+stty -echo
+read PASS # =  $2
+stty echo
 
 token=$(curl --header "Content-Type: application/json" \
   --request POST \
-  --data '{"cedula":"invitado","password":"invitado"}' \
+  --data '{"cedula":"'$USER'","password":"'$PASS'"}' \
   "$SERVER/login" | \
     python3 -c "import sys, json; print(json.load(sys.stdin)['token'])") 
 
-while IFS=, read -r user name surname code; do
+while IFS=, read -r user name surname code role; do
     echo "user: $user"
     hcode=$(echo -n "$code" | sha1sum | awk '{print $1}')
     echo "pass: $hcode"
     echo "token: $token"
-    data='{ "rol": "'$ROLE'","cedula": "'$user'", "nombre": "'$name'","apellido": "'$surname'","password": "'$hcode'","configuracion": { "themeEditor": "dracula","fontSizeEditor": 12,"argumentoI": true,"argumentoF": true},"gruposAsignados": [],"archivos": []}'
+    data='{ "rol": "'$role'","cedula": "'$user'", "nombre": "'$name'","apellido": "'$surname'","password": "'$hcode'","configuracion": { "themeEditor": "dracula","fontSizeEditor": 12,"argumentoI": true,"argumentoF": true}}'
     echo $data
     curl -H "Content-Type: application/json" -H "Authorization: Bearer $token" \
          --request POST \
          --data "$data" \
-         "$SERVER/usuario/$ROLE/restore" 
+         "$SERVER/usuario/$role/restore"
+    echo "\n"
 
 done < $INPUT
 
+curl -H "Content-Type: application/json" -H "Authorization: Bearer $token" \
+  --request POST \
+  "$SERVER/login/$USER/logout" 
 
-- 
GitLab