El microservicio como base.#

El sistema estará dividido en diferentes microservicios, cada uno encargado de realizar una de las diferentes tareas que tiene que realizar el sistema en su conjunto.

La interfaz Slice#

Cómo ya sabéis, el alma de la comunicación entre clientes y servicios en un entorno RMI es la interfaz. En ZeroC ICE esa interfaz se define en el IDL específico del middleware, Slice.

El código de la interfaz podéis encontrarlo aquí. Se recomienda leer la descripción de los servicios con el fichero Slice, para identificar las interfaz, métodos y argumentos aquí especificados.

Servicio principal#

El primer microservicio actúa de entrada al sistema para los clientes. A través de su interfaz podrá obtener referencias a otros servicios.

Así mismo, el servicio debe recibir anunciamientos de los servicios de autenticación y catálogo para mantener las referencias actualizadas. Al arrancar, cada servicio enviará newService al servicio principal, y continuará enviando periódicamente un announce. Si pasados más de 30 segundos un servicio dejara de enviar sus announce, éste deberá ser borrado para no ser devuelto a los usuarios del sistema.

Este servicio debe implementar la interfaz Main del fichero Slice, la cual tiene estás funciones:

  • getAuthenticator() que devuelve un proxy a un servicio de autenticación.

  • getCatalog() que devuelve un proxy a un servicio de catalogo.

  • getFileService() que devuelve un proxy a un servicio de ficheros.

  • newService() acepta el proxy a un objeto. Debe comprobar de qué tipo de servicio se trata y almacenarlo en la caché.

  • announce(): igual que el anterior, sirve para renovar la vigencia de un servicio. Si un servicio pasara demasiado tiempo sin enviar su announce, deberá ser eliminado de la caché.

Servicio de autenticación.#

La autenticación en el servicio se gestiona a través de este servicio. El usuario debe enviar un usuario y contraseña periódicamente, obteniendo un token de autenticación que tendrá una validez limitada en el tiempo (2 minutos). También se encarga de realizar la comprobación de si un token es válido o no para el resto de servicios del sistema.

Para arrancar este servicio debe proporcionarse un token de administración, que deberá ser almacenado en memoria para poder realizar la comprobación de su validez en aquellas operaciones que requieren de dicho token. Éste token se pasará a través del fichero de configuración.

El servicio debe almacenar en una base de datos persistente entre reinicios (no necesariamente debe ser SQL) las credenciales de los usuarios. Los tokens, por su naturaleza temporal, no deben aparecer en ese almacenamiento persistente.

Adicionalmente proporciona al administrador la funcionalidad de añadir y eliminar usuarios.

Dicho servicio implementa la interfaz Authenticator:

  • refreshAuthorization(): crea un nuevo token de autorización de usuario si las credenciales son válidas.

  • isAuthorized(): indica si un token dado es válido o no.

  • whois(): permite descubrir el nombre del usuario a partir de un token válido.

  • isAdmin(): devuelve un valor booleano para comprobar si el token proporcionado corresponde o no con el administrativo.

  • addUser(): función administrativa que permite añadir unas nuevas credenciales en el almacén de datos si el token administrativo es correcto.

  • removeUser(): función administrativa que permite eliminar unas credenciales del almacén de datos si el token administrativo es correcto.

Envío de anunciamientos

Conforme a lo explicado en el apartado del servicio principal el servicio de autenticación deberá enviar una invocación newService() al arrancar, y continuar enviando periódicamente cada 25 segundos una invocación de announce().

Servicio de ficheros#

En lugar de implementar un servicio de streaming como se la plataforma real, en esta práctica se va a implementar un servicio de descargas.

El servicio de ficheros se encarga de enviar al usuario el fichero para que pueda visualizarlo. El servicio debe leer de un directorio en el disco duro, que será pasado al servicio a través de su configuración, los ficheros que serán compartidos.

El servicio deberá anunciar al servicio de catálogo cada archivo alojado en el directorio.

  • newMedia(): será emitido por el servicio cuando se encuentre un nuevo fichero o sea subido uno nuevo por el administrador.

  • removedMedia(): se emitirá cuando un fichero sea eliminado del servicio por el administrador.

El identificador de un medio, utilizado tanto por el servicio de ficheros como por el catálogo, se calculará en función del contenido del fichero (función hash). Para ello, puede utilizarse la suma SHA256 del fichero.

El servicio implementa la interfaz FileService:

  • openFile(): dado el identificador del medio devolverá un proxy al manejador del archivo (FileHandler), que permitirá descargarlo.

  • uploadFile(): dado el token de administrador y un proxy para la subida del archivo, lo guardará en el directorio y devolverá su identificador.

  • removeFile(): dado un identificador y el token de administrador, borrará el archivo del directorio.

Cuando un usuario solicite abrir un fichero, el servicio creará un sirviente para manejar su posible descarga. Ésta se manejará a través de la interfaz FileHandler, que para todas las operaciones solicitará el token del usuario, que debe ser siempre el mismo que solicitó su apertura

Las operaciones disponibles en la interfaz FileHandler son:

  • receive(): recibe el número indicado de bytes del archivo.

  • close(): indica al servidor que el proxy para este fichero ya no va a ser usado y puede ser eliminado.

Envío de anunciamientos

Conforme a lo explicado en el apartado del servicio principal el servicio de archivos deberá enviar una invocación newService() al arrancar, y continuar enviando periódicamente cada 25 segundos una invocación de announce().

Descarga de ficheros#

Cuando un usuario abre un fichero a través de openFile en el servicio, el manejador de fichero debe ser consciente en todo momento de a qué usuario pertenece el token y, si éste expírase en algún momento, devolver la excepción adecuada.

Si el cliente recibiera dicha excepción durante la descarga, deberá renovar su token y utilizar el nuevo para poder continuar la descarga.

Subida de ficheros#

Si el usuario es, además, administrador de la plataforma, puede utilizar el método uploadFile() del servicio para realizar una descarga.

Para ello el cliente deberá proporcionar un proxy a un sirviente de la interfaz FileUploader, a través del cuál el servicio irá solicitando la subida del fichero al cliente.