Commit f5651fec by Pablo Molina

Merge branch 'issue/357' into develop

Conflicts:
	.gitignore
	sails/README.md
	sails/Vagrantfile
	sails/install.sh
	sails/roles/database/README.md
	sails/roles/database/files/pictodb-schema.sql
	sails/roles/database/files/test-autismojaen.sql
	sails/roles/database/files/test-caja.sql
	sails/roles/mysql/tasks/main.yml
	sails/roles/server/tasks/main.yml
	sails/roles/server/vars/main.yml
	sails/roles/webapp/tasks/main.yml
	sails/src/package.json
parents 2c4b927e 6655da93
Showing with 1333 additions and 1975 deletions
...@@ -16,10 +16,13 @@ sails/src/assets/app/bower_components ...@@ -16,10 +16,13 @@ sails/src/assets/app/bower_components
sails/src/assets/app/modules sails/src/assets/app/modules
sails/src/assets/app/css sails/src/assets/app/css
sails/src/assets/app/js sails/src/assets/app/js
sails/src/assets/scripts/config.js
# Other # # Other #
######### #########
sails/src/config/ssl sails/src/config/ssl/**/*.key
sails/src/config/ssl/**/*.crt
sails/src/config/local.js
sails/src/node_modules sails/src/node_modules
sails/.vagrant sails/.vagrant
......
...@@ -47,15 +47,20 @@ todo el repositorio, organizadas en 3 categorías: ...@@ -47,15 +47,20 @@ todo el repositorio, organizadas en 3 categorías:
# Aspecto del código # Aspecto del código
- En el fichero [.editorconfig](./.editorconfig) se encuentra el estilo - En el fichero [.editorconfig][3] se encuentra el estilo utilizado en el código (en cuento a
utilizado en el código (en cuento a espacios, codificación y demás). Existen espacios, codificación y demás). Existen numerosos plugins que pueden encontrarse en
numerosos plugins que pueden encontrarse en [editorconfig.org][4].
[editorconfig.org](http://EditorConfig.org). - En el fichero [/sails/src/.eslintrc][5] se encuentran los estilos referentes a los ficheros de
- En el fichero [/sails/src/.eslintrc](./sails/src/eslintrc) se encuentran los javascript. Tanto `eslint` como las configuraciones necesarias se encuentran en el fichero
estilos referentes a los ficheros de javascript. Tanto `eslint` como las [/sails/src/package.json][6], y se instalarán como dependencias de desarrollo.
configuraciones necesarias se encuentran en el fichero
[/sails/src/package.json](./sails/src/package.json), y se instalarán como > Puede configurarse eslint en el editor usado o ejecutando `eslint [ficheros]` desde
dependencias de desarrollo. > el directorio [/sails/src][7].
> Puede configurarse eslint en el editor usado o ejecutando [1]: https://pre.yottacode.com/
> `eslint [ficheros]` desde el directorio [/sails/src](./sails/src). [2]: https://dev.yottacode.com/
[3]: /softuno/pictogram/blob/develop/.editorconfig
[4]: http://editorconfig.org
[5]: /softuno/pictogram/blob/develop/sails/src/.eslintrc
[6]: /softuno/pictogram/blob/develop/sails/src/package.json
[7]: /softuno/pictogram/tree/develop/sails/src
...@@ -10,7 +10,7 @@ En cada directorio puede leerse la descripción de dicha parte, incluyendo confi ...@@ -10,7 +10,7 @@ En cada directorio puede leerse la descripción de dicha parte, incluyendo confi
utilidades. La estructura del repositorio en sí y forma de contribución se describe en utilidades. La estructura del repositorio en sí y forma de contribución se describe en
[el fichero de contribuciones][1]. [el fichero de contribuciones][1].
[1]: ./CONTRIBUTING.md [1]: /softuno/pictogram/blob/develop/CONTRIBUTING.md
[2]: ./sails [2]: /softuno/pictogram/tree/develop/sails
[3]: ./sails/src/assets/app [3]: /softuno/pictogram/tree/develop/sails/src/assets/app
[4]: ./android/Pictogram [4]: /softuno/pictogram/tree/develop/android/Pictogram
...@@ -25,6 +25,10 @@ mostradas más adelante hacen todo el trabajo. ...@@ -25,6 +25,10 @@ mostradas más adelante hacen todo el trabajo.
``` ```
2. Ejecutar [./install.sh][3]. 2. Ejecutar [./install.sh][3].
3. Ejecutar [./bootstrap.sh][19] para lanzar el servidor. 3. Ejecutar [./bootstrap.sh][19] para lanzar el servidor.
4. Configurar los ficheros `/sails/src/config/local.js` y `/sails/src/assets/scripts/config.js`
generados si fuera necesario (estos ficheros no se encuentran en el repositorio, son generados
por ansible a partir de una plantilla).
5. Generar los [certificados ssl][21] si fuera necesario.
### Opción B (desarrollo): ejecución en una máquina virtual generada automáticamente ### Opción B (desarrollo): ejecución en una máquina virtual generada automáticamente
...@@ -39,11 +43,15 @@ mostradas más adelante hacen todo el trabajo. ...@@ -39,11 +43,15 @@ mostradas más adelante hacen todo el trabajo.
``` ```
2. Instalar [virtualbox][1] y [vagrant][2]. 2. Instalar [virtualbox][1] y [vagrant][2].
3. Ejecutar `vagrant up` desde este directorio. 3. Ejecutar `vagrant up` desde este directorio.
4. Configurar los ficheros `/sails/src/config/local.js` y `/sails/src/assets/scripts/config.js`
generados si fuera necesario (estos ficheros no se encuentran en el repositorio, son generados
por ansible a partir de una plantilla).
5. Generar los [certificados ssl][21] si fuera necesario.
> **Importante**: el script utilizado creará un entorno para el servidor desde > **Importante**: el script utilizado creará un entorno para el servidor desde cero, por lo que
> cero, por lo que **pueden perderse los datos** almacenados por usuarios. > **pueden perderse los datos** almacenados por usuarios.
## Ejecución del servidor ## Ejecución
Una vez lanzado sails con el servidor comienza con la compilación de la aplicación web mediante Una vez lanzado sails con el servidor comienza con la compilación de la aplicación web mediante
tareas de Grunt, para esta configuración existe, por un lado, un fichero [Gruntfile.js][11] que tareas de Grunt, para esta configuración existe, por un lado, un fichero [Gruntfile.js][11] que
...@@ -66,20 +74,22 @@ siguientes comandos**: ...@@ -66,20 +74,22 @@ siguientes comandos**:
[1]: https://www.virtualbox.org/ [1]: https://www.virtualbox.org/
[2]: https://www.vagrantup.com/ [2]: https://www.vagrantup.com/
[3]: ./install.sh [3]: /softuno/pictogram/blob/develop/sails/install.sh
[4]: ./roles/nodejs [4]: /softuno/pictogram/blob/develop/sails/roles/nodejs/README.md
[5]: ./roles/mysql [5]: /softuno/pictogram/blob/develop/sails/roles/mysql/README.md
[6]: ./roles/database [6]: /softuno/pictogram/blob/develop/sails/roles/database/README.md
[7]: ./roles/webapp [7]: /softuno/pictogram/blob/develop/sails/roles/webapp/README.md
[8]: ./roles/server [8]: /softuno/pictogram/blob/develop/sails/roles/server/README.md
[9]: https://www.ansible.com/ [9]: https://www.ansible.com/
[10]: ./src [10]: /softuno/pictogram/blob/develop/sails/src/README.md
[11]: ./src/Gruntfile.js [11]: /softuno/pictogram/blob/develop/sails/src/Gruntfile.js
[12]: ./src/tasks [12]: /softuno/pictogram/blob/develop/sails/src/tasks/README.md
[13]: ./src/tasks/config [13]: /softuno/pictogram/blob/develop/sails/src/tasks/config/README.md
[14]: ./src/tasks/register [14]: /softuno/pictogram/blob/develop/sails/src/tasks/register/README.md
[15]: ./src/tasks/register/default.js [15]: /softuno/pictogram/blob/develop/sails/src/tasks/register/default.js
[16]: ./src/tasks/register/prod.js [16]: /softuno/pictogram/blob/develop/sails/src/tasks/register/prod.js
[17]: ./src/tasks/register/build.js [17]: /softuno/pictogram/blob/develop/sails/src/tasks/register/build.js
[18]: ./src/tasks/register/buildProd.js [18]: /softuno/pictogram/blob/develop/sails/src/tasks/register/buildProd.js
[19]: ./bootstrap.sh [19]: /softuno/pictogram/blob/develop/sails/bootstrap.sh
[20]: https://localhost:1337/app
[21]: /softuno/pictogram/tree/develop/sails/src/config/ssl
# Documentación del servidor y el cliente web de pictogram
- [Esquema de la base de datos][1]
- [API del servidor][2]
- [Documento de estados y reglas de integridad (documento docx)][3]
[1]: /softuno/pictogram/blob/develop/sails/doc/assets/database-er-diagram.png
[2]: /softuno/pictogram/blob/develop/sails/doc/api.md
[3]: /softuno/pictogram/blob/develop/sails/doc/assets/states-and-database-integrity.docx
# API del servidor
La API de pictogram está manejada por sails, de forma que todas las peticiones procesadas y las
políticas de acceso se encuentran implementadas y documentadas en los siguientes ficheros:
- [config/routes.js][1] contiene un diccionario en el que se asocia una ruta (url de la API)
con un método de un controlador de sails. Estos métodos son las funciones que efectuarán las
acciones asociadas cuando se mande una petición a esta ruta. Por ejemplo:
```
'post /mi/primera/:par/ruta': 'MiCrontrolador.miMetodo'
```
En este caso, cuando el servidor reciba una petición POST a la url `/mi/primera/:par/ruta`
ejecutará el método `miMetodo` perteneciente al controlador `MiControlador`. La parte `:par`
de la ruta definida indica que `:par` es una variable, es decir, esta ruta se efectuará para
todas las llamadas del tipo:
- `/mi/primera/parametro1/ruta`
- `/mi/primera/1234/ruta`
- ...
> Para consultar los parámetros que se esperan recibir en cada ruta y las respuestas
> enviadas al cliente, hay que consultar la documentación del controlador asociado a ella.
- [api/controllers][2] es un directorio en el que se encuentran todos los controladores
descritos anteriormente con sus métodos. Aquí se encuentra la documentación de los parámetros
que se esperan y las respuestas enviadas. También se encuentra la implementación, pero no
es necesaria para el uso de la API. La estructura de un controlador es la siguiente:
- El nombre del fichero del controlador es del tipo `MiControladorController.js`
- La estructura del interior del fichero sería:
```
/**
* MiControladorController
* Descripción del controlador
*/
module.exports = {
/**
* Descripción del método (función que responde a la ruta)
* @param {Request} request Contiene los datos de la petición
* {
* param1: "Param A", // Se espera este parámetro
* ...
* }
* @param {Response} response Se utiliza para enviar la respuesta
* {
* datos: "" // Ejemplo de respuesta
* }
*/
miMetodo: function (request, response) {
// Contenido del método
}
};
```
- [config/policies.js][3] contiene reglas referentes a los permisos que se necesitan para
ejecutar un método de un controlador. La estructura del fichero es la siguiente:
```
module.exports.policies = {
'*': false, // No se puede acceder a esta url de ninguna forma
// (aplicado si ninguna otra regla se cumple)
MiControladorPublico: { // Reglas de acceso para este controlador
'*': true // Puede accederse a todos los métodos de este controlador
miPrimerMetodo: ['auth'] // Para acceder a este método
// se debe cumplir la restricción 'auth'
},
MiPrimerControlador: {
miMetodo: true // Puede accederse a este método del controlador
}
...
}
```
> 1. Las descripción de las diferentes restricciones se encuentra documentada en el
> directorio [api/policies][4].
> 2. Si un método no se encuentra en este fichero no se podrá acceder a él.
[1]: /softuno/pictogram/blob/develop/sails/src/config/routes.js
[2]: /softuno/pictogram/tree/develop/sails/src/api/controllers
[3]: /softuno/pictogram/blob/develop/sails/src/config/policies.js
[4]: /softuno/pictogram/tree/develop/sails/src/api/policies

87.8 KB | W: | H:

87.8 KB | W: | H:

sails/doc/EC.png
sails/doc/assets/database-er-diagram.png
sails/doc/EC.png
sails/doc/assets/database-er-diagram.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -20,13 +20,13 @@ Los ficheros SQL que importará este rol son los siguientes: ...@@ -20,13 +20,13 @@ Los ficheros SQL que importará este rol son los siguientes:
- [test-caja][9] contiene datos para el test de CAJA. - [test-caja][9] contiene datos para el test de CAJA.
- [test-autismojaen][10] añade los datos para el test de autismojaen. - [test-autismojaen][10] añade los datos para el test de autismojaen.
[1]: ./files/init.sql [1]: /softuno/pictogram/blob/develop/sails/roles/database/files/init.sql
[2]: ./files/init-ignoresymbolstix.sql [2]: /softuno/pictogram/blob/develop/sails/roles/database/files/init-ignoresymbolstix.sql
[3]: ./files/pictodb-schema.sql [3]: /softuno/pictogram/blob/develop/sails/roles/database/files/pictodb-schema.sql
[4]: ./files/pictodb-data.sql [4]: /softuno/pictogram/blob/develop/sails/roles/database/files/pictodb-data.sql
[5]: ./files/symbolstx-categories.sql [5]: /softuno/pictogram/blob/develop/sails/roles/database/files/symbolstx-categories.sql
[6]: ./files/symbolstx-metadata.sql [6]: /softuno/pictogram/blob/develop/sails/roles/database/files/symbolstx-metadata.sql
[7]: ./files/triggers-enrolments-integrity-constraints.sql [7]: /softuno/pictogram/blob/develop/sails/roles/database/files/triggers-enrolments-integrity-constraints.sql
[8]: ./files/triggers-sessions-integrity-constraints.sql [8]: /softuno/pictogram/blob/develop/sails/roles/database/files/triggers-sessions-integrity-constraints.sql
[9]: ./files/test-autismojaen.sql [9]: /softuno/pictogram/blob/develop/sails/roles/database/files/test-autismojaen.sql
[10]: ./files/test-caja.sql [10]: /softuno/pictogram/blob/develop/sails/roles/database/files/test-caja.sql
...@@ -15,13 +15,13 @@ SET foreign_key_checks=0; ...@@ -15,13 +15,13 @@ SET foreign_key_checks=0;
-- Default supervisor (ID -1) for PCB autonomous mode -- Default supervisor (ID -1) for PCB autonomous mode
-- --
INSERT INTO `supervisor` (`id`, `name`, `surname`, `gender`, `pic`, `address`, `country`, `email`, `phone`, `lang`, `tts_engine`, `password`, `id_off`, `active`) VALUES INSERT INTO `supervisor` (`id`, `name`, `surname`, `gender`, `pic`, `address`, `country`, `email`, `phone`, `lang`, `tts_engine`, `password`, `id_off`, `active`) VALUES
('-1', 'none', 'none', 'M', '/app/img/default.jpg', NULL, NULL, '', NULL, 'es-es', NULL, '', NULL, '0'); ('-1', 'none', 'none', 'M', 'defaultAvatar.jpg', NULL, NULL, '', NULL, 'es-es', NULL, '', NULL, '0');
-- --
-- Meta-method -- Meta-method
-- --
INSERT INTO `meta_method` (`id`, `name`, `description`, `id_sup`) VALUES INSERT INTO `meta_method` (`id`, `name`, `description`, `id_sup`) VALUES
(1, 'Comunicación Aumentativa y Adaptativa', NULL, NULL); (1, 'Comunicación Aumentativa y Adaptativa', NULL, NULL);
-- --
...@@ -274,7 +274,7 @@ INSERT INTO `picto_core_cat` (`id`, `id_pic`, `id_cat_pic`, `coord_x`, `coord_y` ...@@ -274,7 +274,7 @@ INSERT INTO `picto_core_cat` (`id`, `id_pic`, `id_cat_pic`, `coord_x`, `coord_y`
(186, 325, 54270, 2, 6, NULL), -- Change.turn on (186, 325, 54270, 2, 6, NULL), -- Change.turn on
(187, 328, 54270, 2, 7, NULL), -- Change.turn off (187, 328, 54270, 2, 7, NULL), -- Change.turn off
(188, 52670, 52736, 4, 5, NULL), -- Drinks.milk (188, 52670, 52736, 4, 5, NULL), -- Drinks.milk
(194, 4848,4724, 1, 2, NULL), -- Body parts.hair (194, 4848,4724, 1, 2, NULL), -- Body parts.hair
(195, 4872,4724, 1, 3, NULL), -- Body parts.head (195, 4872,4724, 1, 3, NULL), -- Body parts.head
(196, 50694,4724, 1, 4, NULL), -- Body parts.eye (196, 50694,4724, 1, 4, NULL), -- Body parts.eye
(197, 4787 ,4724, 1, 5, NULL), -- Body parts.ear (197, 4787 ,4724, 1, 5, NULL), -- Body parts.ear
......
...@@ -30,7 +30,6 @@ CREATE TABLE IF NOT EXISTS `action` ( ...@@ -30,7 +30,6 @@ CREATE TABLE IF NOT EXISTS `action` (
`timestamp` timestamp DEFAULT CURRENT_TIMESTAMP, `timestamp` timestamp DEFAULT CURRENT_TIMESTAMP,
`id_sup` int(11) DEFAULT NULL, `id_sup` int(11) DEFAULT NULL,
`id_stu` int(11) NOT NULL, `id_stu` int(11) NOT NULL,
`id_dev` int(11) DEFAULT NULL,
`id_try` int(11) DEFAULT NULL, `id_try` int(11) DEFAULT NULL,
`description` varchar(1024) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'serialization of properties of the picto at the time of the action', `description` varchar(1024) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'serialization of properties of the picto at the time of the action',
`gps_lat` float DEFAULT NULL, `gps_lat` float DEFAULT NULL,
...@@ -41,7 +40,6 @@ CREATE TABLE IF NOT EXISTS `action` ( ...@@ -41,7 +40,6 @@ CREATE TABLE IF NOT EXISTS `action` (
UNIQUE (id_stu,timestamp), UNIQUE (id_stu,timestamp),
KEY `fk_sup_act` (`id_sup`), KEY `fk_sup_act` (`id_sup`),
KEY `fk_stu_act` (`id_stu`), KEY `fk_stu_act` (`id_stu`),
KEY `id_dev` (`id_dev`),
KEY `id_try` (`id_try`) KEY `id_try` (`id_try`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
...@@ -64,20 +62,6 @@ CREATE TABLE IF NOT EXISTS `catexp`( ...@@ -64,20 +62,6 @@ CREATE TABLE IF NOT EXISTS `catexp`(
-- -------------------------------------------------------- -- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `device`
--
CREATE TABLE IF NOT EXISTS `device` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_firmware` varchar(40) COLLATE utf8_unicode_ci NOT NULL COMMENT 'id of the firmware of the device (e.g. Android Device ID)',
`desc` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_firmware` (`id_firmware`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=47 ;
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `method` -- Estructura de tabla para la tabla `method`
-- --
...@@ -199,21 +183,6 @@ CREATE TABLE IF NOT EXISTS `office` ( ...@@ -199,21 +183,6 @@ CREATE TABLE IF NOT EXISTS `office` (
-- -------------------------------------------------------- -- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `official_dev`
--
CREATE TABLE IF NOT EXISTS `official_dev` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_dev` int(11) DEFAULT NULL COMMENT 'is null when serial is registered but device is not registered yet',
`serial` varchar(40) NOT NULL,
PRIMARY KEY (`id`),
KEY `id_dev` (`id_dev`),
KEY `serial` (`serial`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=38 ;
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `picto` -- Estructura de tabla para la tabla `picto`
-- --
...@@ -365,7 +334,7 @@ CREATE TABLE IF NOT EXISTS `student` ( ...@@ -365,7 +334,7 @@ CREATE TABLE IF NOT EXISTS `student` (
`birthdate` date NOT NULL, `birthdate` date NOT NULL,
`gender` char(1) COLLATE utf8_unicode_ci NOT NULL, `gender` char(1) COLLATE utf8_unicode_ci NOT NULL,
`country` char(2) COLLATE utf8_unicode_ci NOT NULL, `country` char(2) COLLATE utf8_unicode_ci NOT NULL,
`pic` varchar(255) COLLATE utf8_unicode_ci DEFAULT '/app/img/default.jpg', `pic` varchar(255) COLLATE utf8_unicode_ci DEFAULT 'defaultAvatar.jpg',
`notes` varchar(1024) COLLATE utf8_unicode_ci DEFAULT NULL, `notes` varchar(1024) COLLATE utf8_unicode_ci DEFAULT NULL,
`lang` varchar(5) COLLATE utf8_unicode_ci NOT NULL, `lang` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`attributes` varchar(1024) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Attributes describing student along with his/her configuration', `attributes` varchar(1024) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Attributes describing student along with his/her configuration',
...@@ -411,21 +380,6 @@ CREATE TABLE IF NOT EXISTS `stu_sup` ( ...@@ -411,21 +380,6 @@ CREATE TABLE IF NOT EXISTS `stu_sup` (
-- -------------------------------------------------------- -- --------------------------------------------------------
-- --
-- Estructura de tabla para la tabla `stu_dev`
--
CREATE TABLE IF NOT EXISTS `stu_dev` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_stu` int(11) NOT NULL,
`id_dev` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `id_stu` (`id_stu`),
KEY `id_dev` (`id_dev`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='This table relates official devices with pairs student-supervisor' AUTO_INCREMENT=49 ;
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `supervisor` -- Estructura de tabla para la tabla `supervisor`
-- --
...@@ -434,7 +388,7 @@ CREATE TABLE IF NOT EXISTS `supervisor` ( ...@@ -434,7 +388,7 @@ CREATE TABLE IF NOT EXISTS `supervisor` (
`name` varchar(40) COLLATE utf8_unicode_ci NOT NULL, `name` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`surname` varchar(60) COLLATE utf8_unicode_ci NOT NULL, `surname` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`gender` char(1) COLLATE utf8_unicode_ci NOT NULL, `gender` char(1) COLLATE utf8_unicode_ci NOT NULL,
`pic` varchar(255) COLLATE utf8_unicode_ci DEFAULT '/app/img/default.jpg', `pic` varchar(255) COLLATE utf8_unicode_ci DEFAULT '/upload/supervisorAvatar/defaultAvatar.jpg',
`address` varchar(180) COLLATE utf8_unicode_ci DEFAULT NULL, `address` varchar(180) COLLATE utf8_unicode_ci DEFAULT NULL,
`country` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL, `country` varchar(2) COLLATE utf8_unicode_ci DEFAULT NULL,
`email` varchar(80) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(80) COLLATE utf8_unicode_ci NOT NULL,
...@@ -496,7 +450,6 @@ CREATE TABLE IF NOT EXISTS `working_session` ( ...@@ -496,7 +450,6 @@ CREATE TABLE IF NOT EXISTS `working_session` (
-- Filtros para la tabla `action` -- Filtros para la tabla `action`
-- --
ALTER TABLE `action` ALTER TABLE `action`
ADD CONSTRAINT `action_ibfk_1` FOREIGN KEY (`id_dev`) REFERENCES `device` (`id`),
ADD CONSTRAINT `fk_stu_act` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`), ADD CONSTRAINT `fk_stu_act` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`),
ADD CONSTRAINT `fk_sup_act` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`); ADD CONSTRAINT `fk_sup_act` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`);
...@@ -534,12 +487,6 @@ ALTER TABLE `office` ...@@ -534,12 +487,6 @@ ALTER TABLE `office`
ADD CONSTRAINT `office_ibfk_1` FOREIGN KEY (`admin`) REFERENCES `supervisor` (`id`); ADD CONSTRAINT `office_ibfk_1` FOREIGN KEY (`admin`) REFERENCES `supervisor` (`id`);
-- --
-- Filtros para la tabla `official_dev`
--
ALTER TABLE `official_dev`
ADD CONSTRAINT `official_dev_ibfk_1` FOREIGN KEY (`id_dev`) REFERENCES `device` (`id`);
--
-- Filtros para la tabla `picto` -- Filtros para la tabla `picto`
-- --
...@@ -592,13 +539,6 @@ ALTER TABLE `stu_sup` ...@@ -592,13 +539,6 @@ ALTER TABLE `stu_sup`
ADD CONSTRAINT `stu_sup_ibfk_2` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`); ADD CONSTRAINT `stu_sup_ibfk_2` FOREIGN KEY (`id_sup`) REFERENCES `supervisor` (`id`);
-- --
-- Filtros para la tabla `stu_dev`
--
ALTER TABLE `stu_dev`
ADD CONSTRAINT `stu_dev_ibfk_1` FOREIGN KEY (`id_stu`) REFERENCES `student` (`id`),
ADD CONSTRAINT `stu_dev_ibfk_2` FOREIGN KEY (`id_dev`) REFERENCES `device` (`id`);
--
-- Filtros para la tabla `student` -- Filtros para la tabla `student`
-- --
ALTER TABLE `student` ALTER TABLE `student`
...@@ -652,7 +592,7 @@ VIEW `v_stu_last_instruction` AS ...@@ -652,7 +592,7 @@ VIEW `v_stu_last_instruction` AS
I.`name` AS `ins_name`, I.`name` AS `ins_name`,
M.`name` AS `met_name`, M.`name` AS `met_name`,
M.`id_stu` AS `id_stu` M.`id_stu` AS `id_stu`
FROM FROM
`working_session` AS WS join `working_session` AS WS join
`instruction` AS I join `instruction` AS I join
`method` AS M join `method` AS M join
...@@ -670,7 +610,7 @@ VIEW `v_stu_last_instruction` AS ...@@ -670,7 +610,7 @@ VIEW `v_stu_last_instruction` AS
-- --
-- Vista materializada mv_stu_last_working_session_detail -- Vista materializada mv_stu_last_working_session_detail
-- Mantenida por -- Mantenida por
-- Utilizada por SAILS:StudentController.lasttries -- Utilizada por SAILS:StudentController.lasttries
-- --
-- --
......
/**
* Local environment settings
*
* Use this file to specify configuration settings for use while developing
* the app on your personal system: for example, this would be a good place
* to store database or email passwords that apply only to you, and shouldn't
* be shared with others in your organization.
*
* These settings take precedence over all other config files, including those
* in the env/ subfolder.
*
* PLEASE NOTE:
* local.js is included in your .gitignore, so if you're using git
* as a version control solution for your Sails app, keep in mind that
* this file won't be committed to your repository!
*
* Good news is, that means you can specify configuration for your local
* machine in this file without inadvertently committing personal information
* (like database passwords) to the repo. Plus, this prevents other members
* of your team from commiting their local configuration changes on top of yours.
*
* In a production environment, you probably want to leave this file out
* entirely and leave all your settings in env/production.js
*
*
* For more information, check out:
* http://sailsjs.org/#!/documentation/anatomy/myApp/config/local.js.html
*/
const path = require('path');
const fs = require('fs');
module.exports = {
/**
* Your SSL certificate and key, if you want to be able to serve HTTP
* responses over https:// and/or use websockets over the wss:// protocol
* (recommended for HTTP, strongly encouraged for WebSockets)
*/
ssl: {
ca: fs.readFileSync(path.join(__dirname, 'ssl', 'bundle.crt')),
key: fs.readFileSync(path.join(__dirname, 'ssl', 'key.key')),
cert: fs.readFileSync(path.join(__dirname, 'ssl', 'cert.crt')),
},
/**
* The `port` setting determines which TCP port your app will be
* deployed on.
*
* By default, if it's set, Sails uses the `PORT` environment variable.
* Otherwise it falls back to port 1337.
*
* In env/production.js, you'll probably want to change this setting
* to 80 (http://) or 443 (https://) if you have an SSL certificate
*/
port: process.env.PORT || 1337,
/*
* The runtime "environment" of your Sails app is either typically
* 'development' or 'production'.
*
* In development, your Sails app will go out of its way to help you
* (for instance you will receive more descriptive error and
* debugging output)
*
* In production, Sails configures itself (and its dependencies) to
* optimize performance. You should always put your app in production mode
* before you deploy it to a server. This helps ensure that your Sails
* app remains stable, performant, and scalable.
*
* By default, Sails sets its environment using the `NODE_ENV` environment
* variable. If NODE_ENV is not set, Sails will run in the
* 'development' environment.
*/
environment: process.env.NODE_ENV || 'development',
};
This diff could not be displayed because it is too large.
--- ---
- name: Install libselinux-python (necesary for copying files)
package:
name: libselinux-python
state: present
- name: Install NPM dependencies - name: Install NPM dependencies
npm: npm:
path: "{{ server_path }}/{{ server_relative_path }}" path: "{{ server_path }}/{{ server_relative_path }}"
- name: Create log directory - name: Create log directory
file: file:
path: "{{ server_path }}/{{ server_relative_path }}/logs" path: "{{ server_path }}/logs"
state: directory state: directory
- name: Create log file - name: Copy local.js file
file: copy:
path: "{{ server_path }}/{{ server_relative_path }}/logs/my_log_file.log" src: "{{ server_path }}/roles/server/files/local.js"
state: touch dest: "{{ server_path }}/{{ server_relative_path }}/config/local.js"
force: no
- name: Install sails globaly - name: Install sails globaly
npm: npm:
......
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
/* Configuration constants */ /* Configuration constants */
angular.module('dashboardConfig', []).constant('config', { angular.module('dashboardConfig', []).constant('config', {
backend: "http://localhost:1337" backend: "{{ server_backend_url }}"
}); });
/* global angular */
angular.module('dashboardConfig', []).constant('config', {
backend: 'https://localhost:1337',
});
--- ---
- name: Install libselinux-python (necesary for copying files)
package:
name: libselinux-python
state: present
- name: Install git - name: Install git
package: package:
name: git name: git
...@@ -11,5 +16,11 @@ ...@@ -11,5 +16,11 @@
state: present state: present
global: yes global: yes
- name: Copy config.js file
copy:
src: "{{ server_path }}/roles/webapp/files/config.js"
dest: "{{ server_path }}/src/assets/scripts/config.js"
force: no
- name: Install bower dependencies - name: Install bower dependencies
bower: path="{{ webapp_path }}" bower: path="{{ webapp_path }}"
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
"object-shorthand": 0, "object-shorthand": 0,
"prefer-arrow-callback": 0, "prefer-arrow-callback": 0,
"prefer-template": 0, "prefer-template": 0,
"strict": 0 "strict": 0,
"prefer-rest-params": 0
} }
} }
/**
* AclPictoController
*
* @description :: Server-side logic for managing aclpictoes
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/** /**
* ActionController * ActionController with methods for managing the Action Model.
* * Read it's documentation for further information.
* @description :: Server-side logic for managing actions * @type {Object}
* @help :: See http://links.sailsjs.org/docs/controllers
*/ */
module.exports = { module.exports = {
/**
* Create a new Action, which is executed by a student during a try. If now try is
* specified, the current try will be used as default. If there is no try openned it will
* return an error.
* @param {request} req
* {
* student: studentId,
* type: 'Add / Select / Delete / Show / Unshow / Pause / tryinit /
* tryend / initsession / endsession / pausesession / resumesession',
* timestamp: 'Date()', (optional)
* supervisor: supervisorId, (optional)
* _try: _tryId, (optional)
* description: '{ json description }', (optional)
* gpsLat: 'location lattitude', (optional)
* gpsLon: 'location longitude' (optional)
* }
* @param {response} res
* {
* id: actionId,
* student: studentId,
* type: 'action_type',
* timestamp: 'Date()',
* supervisor: supervisorId,
* _try: _tryId,
* description: '{ json description }',
* gpsLat: 'location lattitude',
* gpsLon: 'location longitude'
* }
*/
create: function(req, res) { create: function(req, res) {
var params = req.allParams(); var params = req.allParams();
// Mandatory params // Mandatory params
if (!params.student) return res.json(500, {error: "No student defined"}); if (!params.student) return res.json(500, {error: "No student defined"});
if (!params.type) return res.json(500, {error: "No type of action defined"}); if (!params.type) return res.json(500, {error: "No type of action defined"});
// Optional params // Optional params
var timestamp = null; if(params.timestamp) timestamp = params.timestamp; var timestamp = null; if(params.timestamp) timestamp = params.timestamp;
var sup = null; if(params.supervisor) sup = params.supervisor; var sup = null; if(params.supervisor) sup = params.supervisor;
var dev = null; if(params.device) dev = params.device;
var _try = null; if(params._try) _try = params._try; var _try = null; if(params._try) _try = params._try;
var description = null; if(params.description) description = params.description; var description = null; if(params.description) description = params.description;
var gpsLat = null; if(params.gpsLat) gpsLat = params.gpsLat; var gpsLat = null; if(params.gpsLat) gpsLat = params.gpsLat;
var gpsLon = null; if(params.gpsLon) gpsLon = params.gpsLon; var gpsLon = null; if(params.gpsLon) gpsLon = params.gpsLon;
// Create a generic Action. Return open (=current, new) try // Create a generic Action. Return open (=current, new) try
Action.create({ Action.create({
"type": params.type, "type": params.type,
"timestamp": timestamp, "timestamp": timestamp,
"supervisor": sup, "supervisor": sup,
"student": params.student, "student": params.student,
"device": dev,
"_try": _try, "_try": _try,
"description": description, "description": description,
"gpsLat": gpsLat, "gpsLat": gpsLat,
...@@ -39,15 +64,15 @@ module.exports = { ...@@ -39,15 +64,15 @@ module.exports = {
if(created) { if(created) {
StuOpenTry.findOne({id_stu : params.student}).exec(function(err, data){ StuOpenTry.findOne({id_stu : params.student}).exec(function(err, data){
if(err || !data){ if(err || !data){
sails.log.error("Error finding try for student "+params.student+ ' when creating action '+type); sails.log.error("Error finding try for student "+ params.student + ' when creating action '+ params.type);
return res.json(500, {error: 'Action '+type+' not created'}); return res.json(500, {error: 'Action '+ params.type +' not created'});
} }
sails.log.debug("Try for student "+params.student+ ":"+JSON.stringify(data)); sails.log.debug("Try for student "+params.student+ ":"+JSON.stringify(data));
return res.json(200,{open_try: data.openTry }); return res.json(200,{open_try: data.openTry });
}) })
} }
}); });
}, },
// createlist action // createlist action
// adds a list of actions // adds a list of actions
...@@ -56,12 +81,11 @@ module.exports = { ...@@ -56,12 +81,11 @@ module.exports = {
var params = req.allParams(); var params = req.allParams();
if (!params.actions || params.actions.length == 0) return res.json(500, {error: "No actions defined"}); if (!params.actions || params.actions.length == 0) return res.json(500, {error: "No actions defined"});
if (!params.student) return res.json(500, {error: "No student defined"}); if (!params.student) return res.json(500, {error: "No student defined"});
if (!params.device) return res.json(500, {error: "No device defined"});
var sup = null; var sup = null;
if(params.supervisor) sup = params.supervisor; if(params.supervisor) sup = params.supervisor;
sails.log.debug(params.actions.length + " Actions: " + JSON.stringify(params.actions)); sails.log.debug(params.actions.length + " Actions: " + JSON.stringify(params.actions));
// with .eachSeries the order of resulting array will be equal // with .eachSeries the order of resulting array will be equal
...@@ -73,13 +97,12 @@ module.exports = { ...@@ -73,13 +97,12 @@ module.exports = {
var desc = null; var desc = null;
if(a.attributes.picto) desc = a.attributes.picto; // select, add and delete actions data if(a.attributes.picto) desc = a.attributes.picto; // select, add and delete actions data
if(a.attributes.pictos) desc = a.attributes.pictos; // show action data if(a.attributes.pictos) desc = a.attributes.pictos; // show action data
Action.create({ Action.create({
type: a.action, type: a.action,
timestamp: a.attributes.timestamp, timestamp: a.attributes.timestamp,
supervisor: sup, supervisor: sup,
student: params.student, student: params.student,
device: params.device,
description: desc description: desc
}).exec(function(err, action){ }).exec(function(err, action){
if(err || !action) sails.log.debug("Creating new "+ a.action +" action: " + err); if(err || !action) sails.log.debug("Creating new "+ a.action +" action: " + err);
...@@ -88,7 +111,7 @@ module.exports = { ...@@ -88,7 +111,7 @@ module.exports = {
}); });
// Finish function when each callback is done // Finish function when each callback is done
// Optionaly it can be passed and err parameter // Optionaly it can be passed and err parameter
}, function(err){ }, function(err){
if( err ) { if( err ) {
// One of the iterations produced an error. // One of the iterations produced an error.
...@@ -97,11 +120,10 @@ module.exports = { ...@@ -97,11 +120,10 @@ module.exports = {
return res.json(500, { error: "Error saving one action: " + err }); return res.json(500, { error: "Error saving one action: " + err });
} else { } else {
// All end ok // All end ok
console.log('All actions have been processed successfully'); console.log('All actions have been processed successfully');
return res.json(200, { msg: "Actions saved successfully" }); return res.json(200, { msg: "Actions saved successfully" });
} }
}); });
} }
}; };
/** /**
* AdminController * AdminController which manages the administration login and login
* * @type {Object}
* @description :: Server-side logic for managing Pictogram administrators
* @help :: See http://links.sailsjs.org/docs/controllers
*/ */
module.exports = { module.exports = {
// // @TODO ¿?¿?
// login action login: function (req, res) {
// expected params in post body: email, password
//
login: function (req, res) {
var bcrypt = require('bcrypt-nodejs'); var bcrypt = require('bcrypt-nodejs');
var email = req.body.email; var email = req.body.email;
var password = req.body.password; var password = req.body.password;
...@@ -19,14 +13,14 @@ module.exports = { ...@@ -19,14 +13,14 @@ module.exports = {
// no credentials // no credentials
if (!email || !password) if (!email || !password)
return res.json(401, {error: 'No credentials sent'}); return res.json(401, {error: 'No credentials sent'});
// Check email // Check email
if (email != sails.config.pictogram.admin.email) if (email != sails.config.pictogram.admin.email)
return res.json(401, {error: 'User not found'}); return res.json(401, {error: 'User not found'});
// if found, check password in encrypted form // if found, check password in encrypted form
bcrypt.compare(password, sails.config.pictogram.admin.password, function (err, match) { bcrypt.compare(password, sails.config.pictogram.admin.password, function (err, match) {
if (err) if (err)
return res.json(500, { error: 'Server error' }); return res.json(500, { error: 'Server error' });
if (!match) // password do not match if (!match) // password do not match
return res.json(401, { error: 'Invalid password' }); return res.json(401, { error: 'Invalid password' });
...@@ -37,10 +31,8 @@ module.exports = { ...@@ -37,10 +31,8 @@ module.exports = {
}); });
}, },
// // @TODO 357
// logout action logout: function (req, res) {
//
logout: function (req, res) {
delete req.token; delete req.token;
res.json(200, {notice: 'Session closed'}); res.json(200, {notice: 'Session closed'});
} }
......
/**
* AttributeController
*
* @description :: Server-side logic for managing attributes
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/** // @TODO 357
* ConfigurationController
*
* @description :: Server-side logic for managing configurations
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = { module.exports = {
// Añade pictograma a la colección del usuario // Añade pictograma a la colección del usuario
create: function(req, res){ create: function(req, res){
var idStu = req.param('idStu'); var idStu = req.param('idStu');
var idPic = req.param('idPic'); var idPic = req.param('idPic');
var idPp = 0; // Inicialmente se crea sin propiedad var idPp = 0; // Inicialmente se crea sin propiedad
...@@ -27,7 +21,7 @@ module.exports = { ...@@ -27,7 +21,7 @@ module.exports = {
idPp: idPp idPp: idPp
} }
).exec( ).exec(
function (err, configuration) { function (err, configuration) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -52,7 +46,7 @@ module.exports = { ...@@ -52,7 +46,7 @@ module.exports = {
Configuration.findOne( Configuration.findOne(
idConf idConf
).exec( ).exec(
function (err, configuration) { function (err, configuration) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -80,7 +74,7 @@ module.exports = { ...@@ -80,7 +74,7 @@ module.exports = {
idPp: idPp idPp: idPp
} }
).exec( ).exec(
function (err, configuration) { function (err, configuration) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -105,7 +99,7 @@ module.exports = { ...@@ -105,7 +99,7 @@ module.exports = {
Configuration.destroy( Configuration.destroy(
idConf idConf
).exec( ).exec(
function (err, configuration) { function (err, configuration) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -116,4 +110,3 @@ module.exports = { ...@@ -116,4 +110,3 @@ module.exports = {
); );
} }
}; };
/**
* DeviceController
*
* @description :: Server-side logic for managing devices
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
//
// create action
// The system generates a new entry in official_device table with a
// random serial number returned to the client
//
create: function(req, res) {
OfficialDevice.create({}).exec(function (err, created) {
if (err) {
console.log(err);
res.serverError(err.details);
}
else if (created)
res.json(200, {serial: created.serial});
});
},
//
// list action
// The system list the entries in official_device table with
// the serial not assigned to a device
//
list: function(req, res) {
OfficialDevice.find({ device: null }).exec(function (err, serials) {
if (err)
res.serverError('DB error');
else if (serials)
res.json(200, serials);
else
res.serverError('No free serials found');
});
},
//
// register action
// Registers a new device with a (optional) serial number and a id_firmware
// If a valid serial number is provided then a official device is registered
// and a permanent JWT token is issued
//
register: function(req, res) {
var params = req.params.all();
if (!params.idFirmware)
res.badRequest('No firmware ID provided');
else if (params.serial) { // Register official device
OfficialDevice.findBySerial(params.serial).exec(function(err, devs) {
if (err)
res.serverError(err.details);
else if (devs.length == 0)
res.badRequest('Invalid serial number');
else {
Device.create(params).exec(function (err, created) {
if (err)
res.serverError(err.details);
else if (created) {
// update official device with dev id
var attrs = {
id_dev: created.id,
serial: devs[0].serial
};
OfficialDevice.update({id: devs[0].id}, attrs).exec(function(err, updated){
if (err)
res.serverError(err.details);
else
res.json({device: created, token: sailsTokenAuth.issueToken(created)});
});
}
});
}
});
}
else { // Register non official device
Device.create(params).exec(function (err, created) {
if (err)
res.serverError(err.details);
else if (created)
res.json({device: created, token: sailsTokenAuth.issueToken(created)});
});
}
},
//
// This action returns pairs <student/supervisor> that are associated to the device
//
users: function(req, res) {
if (!req.params.id)
return res.badRequest("Device ID must be specified");
var list = Device.users(req.params.id, function(err, list) {
if (err || !list)
return res.json(200, []);
return res.json(200, list);
});
},
};
\ No newline at end of file
/**
* ExpressionController
*
* @description :: Server-side logic for managing expressions
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/* global Instruction, Method */
/** /**
* InstructionController * InstructionController manages the requests related to the Instruction model.
* * Read it's documentation for further information.
* @description :: Server-side logic for managing instructions * @type {Object}
* @help :: See http://links.sailsjs.org/docs/controllers
*/ */
module.exports = { module.exports = {
//
// Returns all tries for the given instruction /**
// * Create a new Instruction, which is associated to the given method
* @param {request} req
// Do a method to retrieve all tries by workingSessions attribute * {
* method: methodId,
* name: 'New instruction' (optional)
* objective: 'This instruction has an objective... description' (optional)
* status: 'progress' (optional)
* begin: Date() (optional)
* end: Date() (optional)
* }
* @param {response} res
* {
* id (instructionId)
* method
* name
* objective
* status
* begin
* end
* }
*/
create: function (req, res) {
Method.findOne({ id: req.param('method') }).then(function (method) {
if (!method) {
res.badRequest();
throw new Error('method not found');
}
Instruction.create({
method: method.id,
name: req.param('name'),
objective: req.param('objective'),
status: req.param('status'),
begin: req.param('begin'),
end: req.param('end')
}).then(function (instruction) {
if (instruction) {
res.ok(instruction);
} else {
res.badRequest();
}
})
.catch(function () {
res.serverError();
});
})
.catch(function () {
res.serverError();
});
},
/**
* Update an existing Instruction, known by it's ID
* @param {request} req (with instruction id as url parameter)
* {
* method: methodId, (optional)
* name: 'New instruction' (optional)
* objective: 'This instruction has an objective... description' (optional)
* status: 'progress' (optional)
* begin: Date() (optional)
* end: Date() (optional)
* }
* @param {response} res
* {
* id
* method
* name
* objective
* status
* begin
* end
* }
*/
update: function (req, res) {
Instruction.findOne({ id: req.params.id }).then(function (instruction) {
if (!instruction) {
res.badRequest();
throw new Error('instruction not found');
}
instruction.method = req.param('method') || instruction.method;
instruction.name = req.param('name') || instruction.name;
instruction.objective = req.param('objective') || instruction.objective;
instruction.status = req.param('status') || instruction.status;
instruction.begin = req.param('begin') || instruction.begin;
instruction.end = req.param('end') || instruction.end;
instruction.save(function (error) {
if (error) {
res.serverError();
} else {
res.ok(instruction);
}
});
})
.catch(function () {
res.serverError();
});
},
/**
* Delete an instruction by its ID
* @param {request} req {} (with instructionId as url parameter)
* @param {response} res {}
*/
destroy: function (req, res) {
Instruction.destroy({ id: req.params.id }).exec(function (error) {
if (error) {
res.badRequest();
throw error;
}
res.ok();
});
},
ws: function(req, res) { ws: function(req, res) {
if (!req.params.id_ins) { if (!req.params.id_ins) {
...@@ -23,4 +132,3 @@ module.exports = { ...@@ -23,4 +132,3 @@ module.exports = {
}); });
} }
}; };
/**
* LearningUnitController
*
* @description :: Server-side logic for managing learningunits
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/**
* MetaStuController
*
* @description :: Server-side logic for managing Metastus
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/* global sails, Method, MetaMethod */
/** /**
* MethodController * MethodController
* *
...@@ -7,10 +9,29 @@ ...@@ -7,10 +9,29 @@
module.exports = { module.exports = {
// /**
// create action * Creates a new method for a student using a template (metamethod)
// adds a method * @param {request} req
// * {
* id_mmethod: metaMethodId,
* id_stu: studentId
* }
* @param {response} res
* {
* id: methodId,
* name: 'MetaMethod Name',
* description: 'MetaMethod Description',
* instructions: [
* {
* id: instructionId,
* name: 'Instruction Name',
* objective: 'Instruction Objective',
* method: methodId
* },
* ...
* ]
* }
*/
create: function(req, res) { create: function(req, res) {
var params = req.allParams(); var params = req.allParams();
...@@ -30,10 +51,9 @@ module.exports = { ...@@ -30,10 +51,9 @@ module.exports = {
Method.create({ name: mmethod.name, description: mmethod.description, student: params.id_stu}).exec(function (err, created) { Method.create({ name: mmethod.name, description: mmethod.description, student: params.id_stu}).exec(function (err, created) {
if (err) { if (err) {
sails.log.debug("Creating new method: " + err); sails.log.debug("Creating new method: " + err);
return res.json(500, {error: 'Method not created'}); return res.json(500, {error: 'Method not created'});
} }
if (created) { if (created) {
// Find meta instructions associated to meta method // Find meta instructions associated to meta method
MetaInstruction.find({id_met: params.id_mmethod}).exec(function(err, minstructions) { MetaInstruction.find({id_met: params.id_mmethod}).exec(function(err, minstructions) {
...@@ -43,8 +63,8 @@ module.exports = { ...@@ -43,8 +63,8 @@ module.exports = {
} }
sails.log.debug("Meta instructions found: " + JSON.stringify(minstructions)); sails.log.debug("Meta instructions found: " + JSON.stringify(minstructions));
console.log("Meta instructions found: " + JSON.stringify(minstructions));
var l_ins = []; var l_ins = [];
// Every meta instruction is going to be created in 'Instruction' // Every meta instruction is going to be created in 'Instruction'
...@@ -54,8 +74,8 @@ module.exports = { ...@@ -54,8 +74,8 @@ module.exports = {
sails.log.debug("Loop adding meta instruction: " + mins.name + " to method " + created.id); sails.log.debug("Loop adding meta instruction: " + mins.name + " to method " + created.id);
Instruction.create({ Instruction.create({
method: created.id, method: created.id,
name: mins.name, name: mins.name,
objective: mins.objective objective: mins.objective
}).exec(function(err, added){ }).exec(function(err, added){
...@@ -63,21 +83,21 @@ module.exports = { ...@@ -63,21 +83,21 @@ module.exports = {
if(added){ if(added){
l_ins.push(added); l_ins.push(added);
sails.log.debug("Instruction " + added.name + " added to method " + created.id); sails.log.debug("Instruction " + added.name + " added to method " + created.id);
console.log("Instruction " + added.name + " added to method " + created.id);
} }
callback(); callback();
}); });
// Finish function when each callback is done // Finish function when each callback is done
// Optionaly it can be passed and err parameter // Optionaly it can be passed and err parameter
}, function(err){ }, function(err){
if( err ) { if( err ) {
// One of the iterations produced an error. // One of the iterations produced an error.
// All processing will now stop. // All processing will now stop.
console.log('An error ocurred with a metainstruction');
} else { } else {
console.log('All metainstructions have been processed successfully');
return res.json({ return res.json({
"name": created.name, "name": created.name,
"description": created.description, "description": created.description,
...@@ -89,55 +109,75 @@ module.exports = { ...@@ -89,55 +109,75 @@ module.exports = {
}); });
}); });
} }
}); });
});
},
// Create new empty method });
newMethod: function(req, res) {
var params = req.allParams();
if (!params.id_stu) return res.json(500, {error: "No student defined"});
if (!params.name) return res.json(500, {error: "No method name defined"});
Method.create({ name: params.name, student: params.id_stu }).exec(function (err, created) {
if (err) {
sails.log.debug("Creating new method: " + err);
return res.json(500, {error: 'Method not created'});
}
if (created) {
return res.json(created);
}
});
}, },
meta_methods: function(req, res) { /**
* Creates a new method from scratch (without using a template)
* @param {request} req
* {
* id_stu: studentId,
* name: 'Method name'
* }
* @param {response} res
* {
* id: methodId,
* student: studentId,
* name: 'Method name'
* }
*/
newMethod: function (req, res) {
if (req.param('name') && req.param('id_stu')) {
Method.create({
name: req.param('name'),
student: req.param('id_stu')
}).then(function (method) {
if (!method) {
res.badRequest();
throw new Error('method not created');
}
res.ok(method);
})
.catch(function () {
res.serverError();
});
} else {
res.badRequest();
}
},
/**
* Return all the metamethods of a given supervisor (including the public metamethods)
* not associated to a concrete supervisor.
* @param {request} req {} (with idSup specified as url parameter)
* @param {response} res
* [
* {
* id: metamethodId
* name: 'Metamethod Name'
* description: 'Metamethod description, which can be longer'
* },
* ...
* ]
*/
meta_methods: function (req, res) {
var params = req.allParams();
MetaMethod.find({ or: [
{ supervisor: null },
{ supervisor: params.id_sup }
] }).then(function (metaMethods) {
res.ok(metaMethods);
})
.catch(function () {
res.serverError();
});
},
var params = req.allParams();
MetaMethod.find({
or : [
{ supervisor : null }, // General MetaMethods
{ supervisor : params.id_sup } // Supervisor MetaMethods (templates)
]
}).exec(function(err, methods) {
if (err || !methods || methods.length == 0){
sails.log.debug("MetaMethods: " + err);
return res.json([]); // empty array
}
sails.log.debug("MetaMethods: " + methods.length);
sails.log.debug(methods);
return res.json(methods);
});
},
// FERNANDO: avoid method name duplicates // FERNANDO: avoid method name duplicates
save: function(req, res){ save: function(req, res){
...@@ -145,14 +185,14 @@ module.exports = { ...@@ -145,14 +185,14 @@ module.exports = {
if (!params.id_met) return res.json(500, {error: "No method defined"}); if (!params.id_met) return res.json(500, {error: "No method defined"});
if (!params.id_sup) return res.json(500, {error: "No supervisor defined"}); if (!params.id_sup) return res.json(500, {error: "No supervisor defined"});
Method.findOne(params.id_met).populate('instructions').exec(function(err, method) { Method.findOne(params.id_met).populate('instructions').exec(function(err, method) {
if (err){ if (err){
sails.log.debug("Find Method: " + err); sails.log.debug("Find Method: " + err);
return res.json(500, {error: "No method found"}); // empty array return res.json(500, {error: "No method found"}); // empty array
} }
console.log("Method found:" + JSON.stringify(method));
MetaMethod.create({ MetaMethod.create({
"name": method.name, "name": method.name,
...@@ -172,30 +212,29 @@ module.exports = { ...@@ -172,30 +212,29 @@ module.exports = {
sails.log.debug("Loop adding meta instruction: " + mins.name + " from method " + createdMethod.id); sails.log.debug("Loop adding meta instruction: " + mins.name + " from method " + createdMethod.id);
MetaInstruction.create({ MetaInstruction.create({
id_met: createdMethod.id, id_met: createdMethod.id,
name: mins.name, name: mins.name,
objective: mins.objective objective: mins.objective
}).exec(function(err, added){ }).exec(function(err, added){
if(err) sails.log.debug("MetaInstruction.create: " + err); if(err) sails.log.debug("MetaInstruction.create: " + err);
if(added){ if(added){
sails.log.debug("MetaInstruction " + added.name + " added from method " + createdMethod.id); sails.log.debug("MetaInstruction " + added.name + " added from method " + createdMethod.id);
console.log("MetaInstruction " + added.name + " added from method " + createdMethod.id);
} }
callback(); callback();
}); });
// Finish function when each callback is done // Finish function when each callback is done
// Optionaly it can be passed and err parameter // Optionaly it can be passed and err parameter
}, function(err){ }, function(err){
if( err ) { if( err ) {
// One of the iterations produced an error. // One of the iterations produced an error.
// All processing will now stop. // All processing will now stop.
console.log('An error ocurred with a meta instruction');
} else { } else {
console.log('All meta instructions have been processed successfully');
return res.json(createdMethod);
return res.json(createdMethod);
} }
}); });
...@@ -219,24 +258,24 @@ module.exports = { ...@@ -219,24 +258,24 @@ module.exports = {
if (err || !instructions){ if (err || !instructions){
sails.log.debug("Destroy Instructions: " + err); sails.log.debug("Destroy Instructions: " + err);
return res.json(500, {error: "Cannot delete instructions"}); return res.json(500, {error: "Cannot delete instructions"});
} }
// Destroy method // Destroy method
Method.destroy({ id: params.id }).exec(function(err, method) { Method.destroy({ id: params.id }).exec(function(err, method) {
console.log("Method ID: " + params.id);
console.log("Found: " + JSON.stringify(method));
if (err || !method){ if (err || !method){
sails.log.debug("Destroy Method: " + err); sails.log.debug("Destroy Method: " + err);
return res.json(500, {error: "No method found"}); return res.json(500, {error: "No method found"});
} }
return res.json(method); return res.json(method);
}); });
}); });
}, },
...@@ -254,25 +293,24 @@ module.exports = { ...@@ -254,25 +293,24 @@ module.exports = {
if (err || !metainstructions){ if (err || !metainstructions){
sails.log.debug("Destroy MetaInstructions: " + err); sails.log.debug("Destroy MetaInstructions: " + err);
return res.json(500, {error: "No meta instructions found"}); return res.json(500, {error: "No meta instructions found"});
} }
// Destroy method // Destroy method
MetaMethod.destroy({ id: params.id_mmet }).exec(function(err, metamethod) { MetaMethod.destroy({ id: params.id_mmet }).exec(function(err, metamethod) {
console.log("Meta Method ID: " + params.id_mmet);
console.log("Found: " + JSON.stringify(metamethod));
if (err || !metamethod){ if (err || !metamethod){
sails.log.debug("Destroy MetaMethod: " + err); sails.log.debug("Destroy MetaMethod: " + err);
return res.json(500, {error: "No meta method found"}); return res.json(500, {error: "No meta method found"});
} }
return res.json(metamethod); return res.json(metamethod);
}); });
}); });
} }
};
};
/* global Office */
/** /**
* OfficeController * OfficeController
* *
* @description :: Server-side logic for managing offices * @description :: Server-side logic for managing offices
* @help :: See http://links.sailsjs.org/docs/controllers * @help :: See http://links.sailsjs.org/docs/controllers
*/ */
module.exports = { module.exports = {
/** /**
* `OfficeController.create()` * Return an Office found by id
*/ * @param {request} req {} (with officeId as url parameter)
create: function (req, res) { * @param {response} res
* {
var params = req.params.all(); * supervisors: [Empty array],
// Search if the email is in the BDD (must be unique for Office) * admin: {
Office.findOneByEmail(params.email).exec(function (err, office) { * "name": "John"
if (err) * "surname": "Doe"
return res.json(500, { error: 'DB error' }); * "gender": "F/M"
* "password": "1234"
if (office) * "pic": "url/to/photo.jpg"
return res.json(400, {error: 'Email already exists in DB'}); * "address": "Nice street"
* "country": "ES/UK/..."
Office.create(params).exec(function (err, created) { * "email": "john@doe.com"
if (err) * "phone": "+123456789"
return res.json(500, {error: 'Office not created'}); * "lang": "ES/EN/..."
* "tts_engine": "IVONA Text-to-Speech HQ"
if (created){ * },
// If the admin is specified in the office * id: 3123,
// update the office for the admin too * name: 'First Office in the World',
if(created.admin){ * address: 'The World, Earth',
Supervisor.update({id:created.admin},{office:created.id}).exec(function (err, updated) { * email: 'the_office@world.com',
if(err) console.log("Error updating office of supervisor") * phone1: '+34 123 123 123',
if(updated) console.log(updated); * phone2: null,
}); * lang: 'es-es',
} * contactPerson: 'John Doe'
return res.json({office: created}); * }
}
});
});
},
/**
* `OfficeController.update()` by sails default
*/
/**
* `OfficeController.destroy()` by sails default
*/
/**
* `OfficeController.get()`
* Returns the office with the given id
*/ */
get: function (req, res) { get: function (req, res) {
if (!req.params.id) Office.findOne({ id: req.params.id }).populate('admin').then(function (office) {
return res.json(500, {err: "Office ID must be specified"}); if (office) {
Office.findOne(req.params.id).populate('admin').exec(function(err, office) { res.ok(office);
if (err) return res.json(500, {err: err.details}); } else {
if (office) res.notFound();
return res.json(200, office); }
return res.json({error: "Office not found"}); })
.catch(function () {
res.badRequest();
}); });
}, },
/** /**
* `OfficeController.getAll()` * Return all offices
* Returns all possible offices * @param {request} req {}
* @param {response} res
* [
* {
* supervisors: [Empty array],
* admin: {
* "name": "John"
* "surname": "Doe"
* "gender": "F/M"
* "password": "1234"
* "pic": "url/to/photo.jpg"
* "address": "Nice street"
* "country": "ES/UK/..."
* "email": "john@doe.com"
* "phone": "+123456789"
* "lang": "ES/EN/..."
* "tts_engine": "IVONA Text-to-Speech HQ"
* },
* id: 3123,
* name: 'First Office in the World',
* address: 'The World, Earth',
* email: 'the_office@world.com',
* phone1: '+34 123 123 123',
* phone2: null,
* lang: 'es-es',
* contactPerson: 'John Doe'
* },
* ...
* ]
*/ */
getAll: function (req, res) { getAll: function (req, res) {
Office.find().populate('admin').exec(function(err, offices) { Office.find().populate('admin').then(function (offices) {
if (err) return res.json(500, {err: err.details}); res.ok(offices);
if (offices) })
return res.json(200, offices); .catch(function () {
return res.json({error: "Offices not found"}); res.serverError();
}); });
}, },
/** /**
* `OfficeController.supervisors()` * Get all supervisors from an office
* Returns all supervisors of an office * @param {request} req {} (with officeId as url parameter)
* @param {response} res
* [
* {
* "name": "John"
* "surname": "Doe"
* "gender": "F/M"
* "password": "1234"
* "pic": "url/to/photo.jpg"
* "address": "Nice street"
* "country": "ES/UK/..."
* "email": "john@doe.com"
* "phone": "+123456789"
* "lang": "ES/EN/..."
* "tts_engine": "IVONA Text-to-Speech HQ"
* },
* ...
* ]
*/ */
supervisors: function (req, res) { supervisors: function (req, res) {
if (!req.params.id) Office
return res.json(500, {err: "Office ID must be specified"}); .findOne({ id: req.params.id })
.populate('supervisors')
Office.findOne(req.params.id).populate('supervisors').exec(function(err, off) { .then(function (office) {
if (err) if (office) {
return res.json(500, {error: 'DB error'}); res.ok(office.supervisors);
return res.json(200, off.supervisors); } else {
res.notFound();
}
})
.catch(function () {
res.badRequest();
}); });
}, },
}; };
/**
* PagesController
*
* @description :: This controller sends back AngularJS pages
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
login: function (req, res) {
res.view('login');
},
signin: function (req, res) {
res.view('signin');
}
};
\ No newline at end of file
/**
* PendingRegistrationController
*
* @description :: Server-side logic for managing pendingregistrations
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/**
* PictoPropController
*
* @description :: Server-side logic for managing pictoprops
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/**
* PictoTagController
*
* @description :: Server-side logic for managing pictotags
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/** // @TODO 357
* ProfileController
*
* @description :: Server-side logic for managing profiles
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = { module.exports = {
// Añade atributo al perfil de usuario // Añade atributo al perfil de usuario
create: function(req, res){ create: function(req, res){
var idStu = req.param('idStu'); var idStu = req.param('idStu');
var idAtt = req.param('idAtt'); var idAtt = req.param('idAtt');
var value = ""; // Inicialmente sin valor asignado var value = ""; // Inicialmente sin valor asignado
...@@ -27,7 +21,7 @@ module.exports = { ...@@ -27,7 +21,7 @@ module.exports = {
value: value value: value
} }
).exec( ).exec(
function (err, profile) { function (err, profile) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -51,7 +45,7 @@ module.exports = { ...@@ -51,7 +45,7 @@ module.exports = {
Profile.findOne( Profile.findOne(
idProf idProf
).exec( ).exec(
function (err, profile) { function (err, profile) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -79,7 +73,7 @@ module.exports = { ...@@ -79,7 +73,7 @@ module.exports = {
value: value value: value
} }
).exec( ).exec(
function (err, profile) { function (err, profile) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -105,7 +99,7 @@ module.exports = { ...@@ -105,7 +99,7 @@ module.exports = {
Profile.destroy( Profile.destroy(
idProf idProf
).exec( ).exec(
function (err, profile) { function (err, profile) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -116,4 +110,3 @@ module.exports = { ...@@ -116,4 +110,3 @@ module.exports = {
); );
} }
}; };
...@@ -4,21 +4,23 @@ ...@@ -4,21 +4,23 @@
* @description :: Server-side logic for managing server * @description :: Server-side logic for managing server
* @help :: See http://links.sailsjs.org/docs/controllers * @help :: See http://links.sailsjs.org/docs/controllers
*/ */
module.exports = { module.exports = {
// /**
// ping action * Returns ok (checking if the server is online)
// This action simply return OK to ensure connection is up from device * @param {request} req {}
// * @param {response} res {}
ping: function(req, res) { */
return res.json(200, {result: "OK"}); ping: function (req, res) {
}, res.ok();
},
// /**
// ping_session action * Returns ok (checking if the server is online).
// Same as 'ping' but token is required (see config/policies.js) * This method needs a previous authentication (check policies.js)
// * @param {request} req {}
ping_session: function(req, res) { * @param {response} res {}
return res.json(200, {result: "OK"}); */
} ping_session: function (req, res) {
}; res.ok();
\ No newline at end of file }
};
/**
* SourceController
*
* @description :: Server-side logic for managing sources
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/**
* StuOpenTryController
*
* @description :: Server-side logic for managing StuOpenTry
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/**
* StuSupController
*
* @description :: Server-side logic for managing stusups
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/** // @TODO 357
* SupPictoTagController
*
* @description :: Server-side logic for managing suppictotags
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = { module.exports = {
// Mostrar etiquetas propias del supervisor para un pictograma // Mostrar etiquetas propias del supervisor para un pictograma
// Blueprint // Blueprint
// GET /supervisor/:idSup/pictos/:idAclPicto/tags -> Tutor.find // GET /supervisor/:idSup/pictos/:idAclPicto/tags -> Tutor.find
// NO BORRAR: Necesario cuando hay más de 2 niveles en la URL // NO BORRAR: Necesario cuando hay más de 2 niveles en la URL
find: function(req, res){ find: function(req, res){
var idAclPicto = req.param('idAclPicto'); var idAclPicto = req.param('idAclPicto');
// Comprobación de que se envían los campos // Comprobación de que se envían los campos
...@@ -23,7 +17,7 @@ module.exports = { ...@@ -23,7 +17,7 @@ module.exports = {
SupPictoTag.find({ SupPictoTag.find({
idAclPicto: idAclPicto idAclPicto: idAclPicto
}).exec( }).exec(
function (err, tags) { function (err, tags) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -34,4 +28,3 @@ module.exports = { ...@@ -34,4 +28,3 @@ module.exports = {
); );
} }
}; };
/**
* TagController
*
* @description :: Server-side logic for managing tags
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = {
};
/** // @TODO 357
* TeacherController
*
* @description :: Server-side logic for managing teachers
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = { module.exports = {
// Crear teacher/supervisor // Crear teacher/supervisor
...@@ -26,13 +20,13 @@ module.exports = { ...@@ -26,13 +20,13 @@ module.exports = {
// id: "17", Es autoincrement // id: "17", Es autoincrement
idOff: idOff, idOff: idOff,
supervisor:{ supervisor:{
name: name, name: name,
surname: surname, surname: surname,
contactEmail: contactEmail, contactEmail: contactEmail,
preferedLanguage: preferedLanguage preferedLanguage: preferedLanguage
} }
}).exec( }).exec(
function (err, teacher) { function (err, teacher) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -45,7 +39,7 @@ module.exports = { ...@@ -45,7 +39,7 @@ module.exports = {
// Elimina teacher/supervisor // Elimina teacher/supervisor
// CUSTOM Blueprint // CUSTOM Blueprint
// DELETE /teacher/:idSup -> Teacher.destroy // DELETE /teacher/:idSup -> Teacher.destroy
destroy: function(req, res){ destroy: function(req, res){
var idSup = req.param('idSup'); var idSup = req.param('idSup');
...@@ -59,7 +53,7 @@ module.exports = { ...@@ -59,7 +53,7 @@ module.exports = {
Teacher.destroy( Teacher.destroy(
{"supervisor": idSup} {"supervisor": idSup}
).exec( ).exec(
function (err, teacher) { function (err, teacher) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -68,7 +62,7 @@ module.exports = { ...@@ -68,7 +62,7 @@ module.exports = {
Supervisor.destroy( Supervisor.destroy(
idSup idSup
).exec( ).exec(
function (err, supervisor) { function (err, supervisor) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -84,7 +78,6 @@ module.exports = { ...@@ -84,7 +78,6 @@ module.exports = {
} }
); );
} }
}; };
/** // @TODO 357
* TryController
*
* @description :: Server-side logic for managing learningunits
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = { module.exports = {
// create action // create action
// adds a try // adds a try
// //
create: function(req, res) { create: function(req, res) {
var params = req.allParams(); var params = req.allParams();
if (!params.ws) return res.json(500, {error: "No workingSession defined"}); if (!params.ws) return res.json(500, {error: "No workingSession defined"});
if (!params.begin) return res.json(500, {error: "No begin defined"}); if (!params.begin) return res.json(500, {error: "No begin defined"});
if (!params.end) return res.json(500, {error: "No end defined"}); if (!params.end) return res.json(500, {error: "No end defined"});
...@@ -19,7 +13,6 @@ module.exports = { ...@@ -19,7 +13,6 @@ module.exports = {
if (!params.supervisor) return res.json(500, {error: "No supervisor in try defined"}); if (!params.supervisor) return res.json(500, {error: "No supervisor in try defined"});
if (!params.student) return res.json(500, {error: "No student in try defined"}); if (!params.student) return res.json(500, {error: "No student in try defined"});
if (!params.device) return res.json(500, {error: "No device in try defined"});
Try.create({ Try.create({
"workingSession":params.ws, "workingSession":params.ws,
...@@ -40,7 +33,7 @@ module.exports = { ...@@ -40,7 +33,7 @@ module.exports = {
async.eachSeries(params.actions, function(a, callback) { async.eachSeries(params.actions, function(a, callback) {
sails.log.debug("Loop adding actions: " + a.action + " to try " + tr.id); sails.log.debug("Loop adding actions: " + a.action + " to try " + tr.id);
var desc = null; var desc = null;
if(a.attributes.picto) desc = a.attributes.picto; // select, add and delete actions data if(a.attributes.picto) desc = a.attributes.picto; // select, add and delete actions data
if(a.attributes.pictos) desc = a.attributes.pictos; // show action data if(a.attributes.pictos) desc = a.attributes.pictos; // show action data
...@@ -50,7 +43,6 @@ module.exports = { ...@@ -50,7 +43,6 @@ module.exports = {
timestamp: a.attributes.timestamp, timestamp: a.attributes.timestamp,
supervisor: params.supervisor, supervisor: params.supervisor,
student: params.student, student: params.student,
device: params.device,
description: desc, description: desc,
_try: tr.id _try: tr.id
}).exec(function(err, action){ }).exec(function(err, action){
...@@ -63,14 +55,14 @@ module.exports = { ...@@ -63,14 +55,14 @@ module.exports = {
}); });
// Finish function when each callback is done // Finish function when each callback is done
// Optionaly it can be passed and err parameter // Optionaly it can be passed and err parameter
}, function(err){ }, function(err){
if( err ) { if( err ) {
// One of the iterations produced an error. // One of the iterations produced an error.
// All processing will now stop. // All processing will now stop.
console.log('An error ocurred with an action'); console.log('An error ocurred with an action');
} else { } else {
console.log('All actions have been processed successfully'); console.log('All actions have been processed successfully');
// Return the try // Return the try
// with the array of actions // with the array of actions
...@@ -92,7 +84,6 @@ module.exports = { ...@@ -92,7 +84,6 @@ module.exports = {
"timestamp": ws.begin, "timestamp": ws.begin,
"supervisor": ws.supervisor, "supervisor": ws.supervisor,
"student": ws.student, "student": ws.student,
"device": 58
}).exec(function(err, action){ }).exec(function(err, action){
if(err || !action) sails.log.debug("Creating new Action InitSession: " + err); if(err || !action) sails.log.debug("Creating new Action InitSession: " + err);
if(action) sails.log.debug("Created Action: " + action.type); if(action) sails.log.debug("Created Action: " + action.type);
...@@ -104,14 +95,13 @@ module.exports = { ...@@ -104,14 +95,13 @@ module.exports = {
"timestamp": ws.begin, "timestamp": ws.begin,
"supervisor": ws.supervisor, "supervisor": ws.supervisor,
"student": ws.student, "student": ws.student,
"device": 58,
"_try": tr.id "_try": tr.id
}).exec(function(err, action){ }).exec(function(err, action){
if(err || !action) sails.log.debug("Creating new Action TryInit: " + err); if(err || !action) sails.log.debug("Creating new Action TryInit: " + err);
if(action){ if(action){
sails.log.debug("Created Action: " + action.type); sails.log.debug("Created Action: " + action.type);
// Return the working session created // Return the working session created
// with the array of one try (the first) // with the array of one try (the first)
// with the array of one action (the first too) // with the array of one action (the first too)
return res.json({ return res.json({
...@@ -119,7 +109,7 @@ module.exports = { ...@@ -119,7 +109,7 @@ module.exports = {
"begin": ws.begin, "begin": ws.begin,
"student": ws.student, "student": ws.student,
"supervisor": ws.supervisor, "supervisor": ws.supervisor,
"tries": [ "tries": [
{ {
"id": tr.id, "id": tr.id,
"instruction": tr.instruction, "instruction": tr.instruction,
...@@ -134,9 +124,8 @@ module.exports = { ...@@ -134,9 +124,8 @@ module.exports = {
*/ */
} }
}); });
} }
}; };
/** // @TODO 357
* TutorController
*
* @description :: Server-side logic for managing tutors
* @help :: See http://links.sailsjs.org/docs/controllers
*/
module.exports = { module.exports = {
// Crear tutor/supervisor // Crear tutor/supervisor
// Blueprint // Blueprint
// POST /tutor -> Tutor.create // POST /tutor -> Tutor.create
create: function(req, res){ create: function(req, res){
var name = req.param('name'); var name = req.param('name');
var surname = req.param('surname'); var surname = req.param('surname');
var contactEmail = req.param('contactEmail'); var contactEmail = req.param('contactEmail');
...@@ -26,13 +20,13 @@ module.exports = { ...@@ -26,13 +20,13 @@ module.exports = {
Tutor.create({ Tutor.create({
// id: "17", Es autoincrement // id: "17", Es autoincrement
supervisor:{ supervisor:{
name: name, name: name,
surname: surname, surname: surname,
contactEmail: contactEmail, contactEmail: contactEmail,
preferedLanguage: preferedLanguage preferedLanguage: preferedLanguage
} }
}).exec( }).exec(
function (err, tutor) { function (err, tutor) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -43,10 +37,10 @@ module.exports = { ...@@ -43,10 +37,10 @@ module.exports = {
); );
}, },
// Elimina tutor/supervisor // Elimina tutor/supervisor
// CUSTOM Blueprint // CUSTOM Blueprint
// DELETE /tutor/:idSup -> Tutor.destroy // DELETE /tutor/:idSup -> Tutor.destroy
destroy: function(req, res){ destroy: function(req, res){
var idSup = req.param('idSup'); var idSup = req.param('idSup');
...@@ -60,7 +54,7 @@ module.exports = { ...@@ -60,7 +54,7 @@ module.exports = {
Tutor.destroy( Tutor.destroy(
{"supervisor": idSup} {"supervisor": idSup}
).exec( ).exec(
function (err, tutor) { function (err, tutor) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -69,7 +63,7 @@ module.exports = { ...@@ -69,7 +63,7 @@ module.exports = {
Supervisor.destroy( Supervisor.destroy(
idSup idSup
).exec( ).exec(
function (err, supervisor) { function (err, supervisor) {
if(err){ if(err){
res.json(err.status, {err: err}); res.json(err.status, {err: err});
return; return;
...@@ -85,6 +79,6 @@ module.exports = { ...@@ -85,6 +79,6 @@ module.exports = {
} }
); );
} }
}; };
\ No newline at end of file
...@@ -12,13 +12,13 @@ module.exports = { ...@@ -12,13 +12,13 @@ module.exports = {
// close a WS // close a WS
// //
close: function(req, res) { close: function(req, res) {
if (!req.params.id_ws) return res.json(500, {error: "No working session defined"}); if (!req.params.id_ws) return res.json(500, {error: "No working session defined"});
StuOpenTry.findOne( { id_ws : req.params.id_ws } ).exec(function(err, t) { StuOpenTry.findOne( { id_ws : req.params.id_ws } ).exec(function(err, t) {
if (err) { if (err) {
sails.log.error("Error Recovering from ws "+err); sails.log.error("Error Recovering from ws "+err);
return res.json(500, {error: 'recovering from ws:'+err}); return res.json(500, {error: 'recovering from ws:'+err});
} }
if(t && t.openTry!=null) /*WS recovery*/ { if(t && t.openTry!=null) /*WS recovery*/ {
sails.log.debug("Recovering WS required for WS "+req.params.id_ws); sails.log.debug("Recovering WS required for WS "+req.params.id_ws);
...@@ -31,7 +31,7 @@ module.exports = { ...@@ -31,7 +31,7 @@ module.exports = {
return res.json(500, {error: 'Working Session could not be closed'}); return res.json(500, {error: 'Working Session could not be closed'});
}}); }});
return res.json(200, {end: ws_end.toISOString()}); return res.json(200, {end: ws_end.toISOString()});
} }
else else
return res.json(200, {result:'no recovery required'}); return res.json(200, {result:'no recovery required'});
...@@ -41,9 +41,10 @@ module.exports = { ...@@ -41,9 +41,10 @@ module.exports = {
// create action // create action
// adds a working session and a InitSession action // adds a working session and a InitSession action
// //
// @TODO 357
create: function(req, res) { create: function(req, res) {
var params = req.allParams(); var params = req.allParams();
if (!params.id_sup) return res.json(500, {error: "No supervisor defined"}); if (!params.id_sup) return res.json(500, {error: "No supervisor defined"});
if (!params.id_ins) return res.json(500, {error: "No instruction defined"}); if (!params.id_ins) return res.json(500, {error: "No instruction defined"});
if (!params.id_stu) return res.json(500, {error: "No student defined"}); if (!params.id_stu) return res.json(500, {error: "No student defined"});
...@@ -51,24 +52,24 @@ module.exports = { ...@@ -51,24 +52,24 @@ module.exports = {
var data = {}; var data = {};
data.supervisor = params.id_sup; data.supervisor = params.id_sup;
data.instruction = params.id_ins; data.instruction = params.id_ins;
data.description = params.desc; data.description = params.desc;
StuOpenTry.findOne( {or: [ StuOpenTry.findOne( {or: [
{ id_sup : params.id_sup }, { id_sup : params.id_sup },
{ id_stu : params.id_stu } { id_stu : params.id_stu }
]} ).exec(function(err, t) { ]} ).exec(function(err, t) {
if (err) { if (err) {
sails.log.error("Error Recovering from ws "+err); sails.log.error("Error Recovering from ws "+err);
return res.json(500, {error: 'recovering from ws:'+err}); return res.json(500, {error: 'recovering from ws:'+err});
} }
if(!t || t.openTry==null) //WS closed correctly if(!t || t.openTry==null) //WS closed correctly
WorkingSession.create(data).exec(function(err, ws){ WorkingSession.create(data).exec(function(err, ws){
if(err || !ws){ if(err || !ws){
sails.log.error("Creating new Working Sesion error "+err); sails.log.error("Creating new Working Sesion error "+err);
return res.json(500, {error: 'Working Session not created'}); return res.json(500, {error: 'Working Session not created'});
} }
// Create the InitSession Action // Create the InitSession Action
Action.create({ Action.create({
"type": "initsession", "type": "initsession",
...@@ -77,16 +78,16 @@ module.exports = { ...@@ -77,16 +78,16 @@ module.exports = {
"student": params.id_stu "student": params.id_stu
}).exec(function(err, action){ }).exec(function(err, action){
if(err || !action) { if(err || !action) {
sails.log.error("Creating initial action for new Working Sesion. Error "+err); sails.log.error("Creating initial action for new Working Sesion. Error "+err);
return res.json(500, {error: 'Working Session not created'}); return res.json(500, {error: 'Working Session not created'});
} }
StuOpenTry.findOne( {id_stu : params.id_stu } ).exec(function(err, t) { StuOpenTry.findOne( {id_stu : params.id_stu } ).exec(function(err, t) {
if (err) { if (err) {
sails.log.error("Error Recovering from ws "+err); sails.log.error("Error Recovering from ws "+err);
return res.json(500, {error: 'recovering from ws:'+err}); return res.json(500, {error: 'recovering from ws:'+err});
} }
// Return the working session and try created // Return the working session and try created
sails.log.debug("Initial action for new Working Sesion "+JSON.stringify(ws)+". Action:"+JSON.stringify(action)); sails.log.debug("Initial action for new Working Sesion "+JSON.stringify(ws)+". Action:"+JSON.stringify(action));
return res.json({ return res.json({
"id": ws.id, "id": ws.id,
"first_try_id":t.openTry, "first_try_id":t.openTry,
...@@ -94,7 +95,7 @@ module.exports = { ...@@ -94,7 +95,7 @@ module.exports = {
}) })
}) })
}); });
}); });
else { //Not closed previous WS must be recovered and closed else { //Not closed previous WS must be recovered and closed
sails.log.debug("Recovering WS required for student "+params.id_stu); sails.log.debug("Recovering WS required for student "+params.id_stu);
var ws_end; var ws_end;
...@@ -105,12 +106,12 @@ module.exports = { ...@@ -105,12 +106,12 @@ module.exports = {
sails.log.error("Error updating no closed WS " + t.id_ws); sails.log.error("Error updating no closed WS " + t.id_ws);
return res.json(500, {error: 'Working Session not created'}); return res.json(500, {error: 'Working Session not created'});
} }
WorkingSession.create(data).exec(function(err, ws){ WorkingSession.create(data).exec(function(err, ws){
if(err || !ws){ if(err || !ws){
sails.log.error("Creating new Working Sesion error "+err); sails.log.error("Creating new Working Sesion error "+err);
return res.json(500, {error: 'Working Session not created'}); return res.json(500, {error: 'Working Session not created'});
} }
// Create the InitSession Action // Create the InitSession Action
Action.create({ Action.create({
"type": "initsession", "type": "initsession",
...@@ -118,17 +119,17 @@ module.exports = { ...@@ -118,17 +119,17 @@ module.exports = {
"supervisor": ws.supervisor, "supervisor": ws.supervisor,
"student": params.id_stu "student": params.id_stu
}).exec(function(err, action){ }).exec(function(err, action){
if(err || !action) { if(err || !action) {
sails.log.error("Creating initial action for new Working Sesion. Error "+err); sails.log.error("Creating initial action for new Working Sesion. Error "+err);
return res.json(500, {error: 'Working Session not created'}); return res.json(500, {error: 'Working Session not created'});
} }
StuOpenTry.findOne( {id_stu : params.id_stu} ).exec(function(err, t) { StuOpenTry.findOne( {id_stu : params.id_stu} ).exec(function(err, t) {
if (err) { if (err) {
sails.log.error("Error Recovering from ws "+err); sails.log.error("Error Recovering from ws "+err);
return res.json(500, {error: 'recovering from ws:'+err}); return res.json(500, {error: 'recovering from ws:'+err});
} }
// Return the working session and try created // Return the working session and try created
sails.log.debug("Initial action for new Working Sesion "+JSON.stringify(action)); sails.log.debug("Initial action for new Working Sesion "+JSON.stringify(action));
return res.json({ return res.json({
"id": ws.id, "id": ws.id,
"first_try_id":t.openTry, "first_try_id":t.openTry,
...@@ -136,18 +137,19 @@ module.exports = { ...@@ -136,18 +137,19 @@ module.exports = {
}) })
}) })
}); });
}); });
}); });
} }
}); });
}, },
// update action // update action
// ends a working session and a creates an EndSession action // ends a working session and a creates an EndSession action
// //
// @TODO 357
update: function(req, res) { update: function(req, res) {
var params = req.allParams(); var params = req.allParams();
WorkingSession.update({id:params.id}, params).exec(function(err, ws){ WorkingSession.update({id:params.id}, params).exec(function(err, ws){
if(err || !ws){ if(err || !ws){
sails.log.error("Updating Working Sesion error: " + err); sails.log.error("Updating Working Sesion error: " + err);
...@@ -165,15 +167,15 @@ module.exports = { ...@@ -165,15 +167,15 @@ module.exports = {
"student": params.id_stu "student": params.id_stu
}).exec(function(err, action){ }).exec(function(err, action){
if(err || !action) { if(err || !action) {
sails.log.debug("Error creating new Action EndSession: " + err); sails.log.debug("Error creating new Action EndSession: " + err);
return res.json(500, {error: 'Working Session not updated'}); return res.json(500, {error: 'Working Session not updated'});
} }
}); });
// Implementation of Integrity rule #8 for sessions management // Implementation of Integrity rule #8 for sessions management
Try.findOne( { id_ws : params.id } ).exec(function(err, t) { //Deleting empty WS (no tries) Try.findOne( { id_ws : params.id } ).exec(function(err, t) { //Deleting empty WS (no tries)
if (err) { if (err) {
sails.log.error("Error Recovering from ws "+err); sails.log.error("Error Recovering from ws "+err);
return res.json(500, {error: 'recovering from ws:'+err}); return res.json(500, {error: 'recovering from ws:'+err});
} }
if (typeof(t) == 'undefined') /*Empty WS must be deleted*/{ if (typeof(t) == 'undefined') /*Empty WS must be deleted*/{
sails.log.debug("Empty WS to be deleted, id: "+params.id); sails.log.debug("Empty WS to be deleted, id: "+params.id);
...@@ -183,12 +185,12 @@ module.exports = { ...@@ -183,12 +185,12 @@ module.exports = {
return res.json(500, {error: 'Error deleting empty WS (no tries)'}); return res.json(500, {error: 'Error deleting empty WS (no tries)'});
}}); }});
} }
}); });
} }
// Return the working session updated // Return the working session updated
return res.json(ws); return res.json(ws);
}); });
}, },
...@@ -199,7 +201,7 @@ module.exports = { ...@@ -199,7 +201,7 @@ module.exports = {
per_year: function(req, res) { per_year: function(req, res) {
if (!req.params.id_stu) if (!req.params.id_stu)
return res.json(500, {error: "No student defined"}); return res.json(500, {error: "No student defined"});
if (!req.params.year) if (!req.params.year)
return res.json(500, {error: "No year defined"}); return res.json(500, {error: "No year defined"});
...@@ -215,7 +217,7 @@ module.exports = { ...@@ -215,7 +217,7 @@ module.exports = {
per_month: function(req, res) { per_month: function(req, res) {
if (!req.params.id_stu) if (!req.params.id_stu)
return res.json(500, {error: "No student defined"}); return res.json(500, {error: "No student defined"});
if (!req.params.month) if (!req.params.month)
return res.json(500, {error: "No month defined"}); return res.json(500, {error: "No month defined"});
...@@ -227,7 +229,8 @@ module.exports = { ...@@ -227,7 +229,8 @@ module.exports = {
// //
// Returns all tries for the given instruction // Returns all tries for the given instruction
// //
// @TODO 357
tries: function(req, res) { tries: function(req, res) {
if (!req.params.id_ws) { if (!req.params.id_ws) {
return res.json(500, {error: "No working session defined"}); return res.json(500, {error: "No working session defined"});
...@@ -236,9 +239,9 @@ module.exports = { ...@@ -236,9 +239,9 @@ module.exports = {
WorkingSession: req.params.id_ws, // With this working session id WorkingSession: req.params.id_ws, // With this working session id
or : [ or : [
{ result: null }, // This is necessary here because it's not enough with the following query to recover null results { result: null }, // This is necessary here because it's not enough with the following query to recover null results
{ result: { '!' : ['BROKEN', 'DISCARDED'] }} // And without this results { result: { '!' : ['BROKEN', 'DISCARDED'] }} // And without this results
] ]
}).populate('actions').exec(function(err, tries) { }).populate('actions').exec(function(err, tries) {
if (err) throw err; if (err) throw err;
if(!tries || tries.length == 0) return res.json([]); // Empty array of tries if(!tries || tries.length == 0) return res.json([]); // Empty array of tries
...@@ -247,4 +250,3 @@ module.exports = { ...@@ -247,4 +250,3 @@ module.exports = {
}, },
}; };
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* information to send. * information to send.
* @type {Object} * @type {Object}
*/ */
module.exports = function eventsHook (sails) { module.exports = function eventsHook(sails) {
return { return {
/** /**
* Speacial Function wrapping sails.sockets.broadcast that uses a room * Speacial Function wrapping sails.sockets.broadcast that uses a room
...@@ -38,12 +38,14 @@ module.exports = function eventsHook (sails) { ...@@ -38,12 +38,14 @@ module.exports = function eventsHook (sails) {
rooms = [rooms]; rooms = [rooms];
} }
sails.log.debug('"websocketEvent":', JSON.stringify({ // Ensure data is an object
rooms: rooms, if (!(typeof event.data === 'object' && event.data !== null)) {
name: event.name, event.data = {};
data: event.data, }
socketToOmit: socketToOmit ? socketToOmit.id : undefined
})); sails.log.debug("Websocket event '%s' with data '%j' sent to '%s'",
event.name, event.data, rooms.join(', ')
);
sails.sockets.broadcast( sails.sockets.broadcast(
rooms, rooms,
...@@ -70,6 +72,22 @@ module.exports = function eventsHook (sails) { ...@@ -70,6 +72,22 @@ module.exports = function eventsHook (sails) {
}, },
/** /**
* A supervisor has been unlinked from a student.
* @param {ID} supId ID of the supervisor
* @param {ID} stu_id ID of the student
* @return {Object} {name, data}
*/
unlinkSupervisorFromStudent: function (supId, stuId) {
return {
name: 'unlinkSupervisorFromStudent',
data: {
sup_id: supId,
stu_id: stuId
}
};
},
/**
* Someone has subscribed/unsubscribed to/from a room. The number * Someone has subscribed/unsubscribed to/from a room. The number
* of subscribes is sent * of subscribes is sent
* @param {number} subscriberCount Number of subscribers * @param {number} subscriberCount Number of subscribers
......
...@@ -13,7 +13,7 @@ module.exports = { ...@@ -13,7 +13,7 @@ module.exports = {
autoPK : false, autoPK : false,
autoCreatedAt : false, autoCreatedAt : false,
autoUpdatedAt : false, autoUpdatedAt : false,
attributes: { attributes: {
id: { id: {
type: "integer", type: "integer",
...@@ -23,11 +23,23 @@ module.exports = { ...@@ -23,11 +23,23 @@ module.exports = {
}, },
type: { type: {
required: true, required: true,
type: "string", type: 'string',
size: 20 enum: [
'Add',
'Select',
'Delete',
'Show',
'Unshow',
'Pause',
'tryinit',
'tryend',
'initsession',
'endsession',
'pausesession',
'resumesession'
]
}, },
timestamp: { timestamp: {
//required: true,
type: "datetime" type: "datetime"
}, },
supervisor: { // FK de Supervisor. 1 a N supervisor: { // FK de Supervisor. 1 a N
...@@ -42,23 +54,17 @@ module.exports = { ...@@ -42,23 +54,17 @@ module.exports = {
required: true, required: true,
model: "Student" model: "Student"
}, },
device: { // FK de Device
columnName: 'id_dev',
type: 'integer',
required: false,
model: 'Device'
},
_try: { // FK de Try _try: { // FK de Try
columnName: 'id_try', columnName: 'id_try',
type: 'integer', type: 'integer',
required: false, required: false,
model: 'Try' model: 'Try'
}, },
description: { description: {
type: "json", type: "json",
required: false, required: false,
size: 1024 size: 1024
}, },
gpsLat: { gpsLat: {
columnName: "gps_lat", columnName: "gps_lat",
type: "float" type: "float"
...@@ -68,4 +74,4 @@ module.exports = { ...@@ -68,4 +74,4 @@ module.exports = {
type: "float" type: "float"
} }
} }
}; };
\ No newline at end of file
/**
* Device.js
*
* @description :: This are non-official devices connecto to Pictogram
* @docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
tableName : 'device',
migrate : 'safe',
schema : true,
autoPK : false,
autoCreatedAt : false,
autoUpdatedAt : false,
attributes: {
id: {
type: "integer",
autoIncrement: true,
primaryKey: true,
unique: true
},
idFirmware: {
columnName: 'id_firmware',
type: 'string',
size: 40,
unique: true,
required: true
},
desc: {
type: 'string',
size: 40
},
stuDevs: {
collection: 'StuDev',
via: 'device'
},
actions: {
collection: 'Action',
via: 'device'
},
},
//
// Model hook for creating a new device
// If a valid serial number is passed, id_dev is updated in official_device table
//
beforeCreate: function(attrs, next) {
// Check if firmware ID is provided
if (!attrs.idFirmware)
return next(new Error('No firmware ID provided'));
// Check if id_firmware is not already registered
Device.findById_firmware(attrs.idFirmware).exec(function(err, devs) {
if (err)
return next(err);
if (devs.length > 0) // device already registered
return next(new Error('Device already registered with that firmware ID'));
next();
});
},
//
// Class method to get the pairs <student, supervisor> associated with the device
//
users: function(dev_id, callback) {
var list = [];
// Get stuDevs with the dev_id
StuDev.find({device: dev_id})
.exec(function(err, stuDevs) {
if (err) return callback(err, []);
//console.log("stuDevs: " + JSON.stringify(stuDevs));
// Get stuSups with every student id of stuDevs
async.eachSeries(stuDevs, function(stuDev, cb) {
StuSup.find({student: stuDev.student})
.populate('student')
.populate('supervisor')
.exec(function(err, stuSups) {
if (err) throw err;
//console.log("stuSups: " + JSON.stringify(stuSups));
for (var i = 0; i < stuSups.length; i++)
list.push(stuSups[i]);
// next in series
cb();
});
},
function(err) {
if (err) throw err;
//console.log("Final list: " + JSON.stringify(list));
callback(err, list); // out loop finished, return result
// Return the list when finish asynch series
});
});
}
};
/**
* OfficialDevice.js
*
* @description :: This are official devices sold by us
* @docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
tableName : 'official_dev',
migrate : 'safe',
schema : true,
autoPK : false,
autoCreatedAt : false,
autoUpdatedAt : false,
attributes: {
id: {
type: "integer",
autoIncrement: true,
primaryKey: true,
unique: true
},
device: {
columnName: 'id_dev',
type: 'integer',
required: false,
model: 'Device'
},
serial: {
type: 'string',
size: 40,
required: true,
unique: true
}
},
//
// Model hook for creating a new device
// and generate a new serial number
//
beforeValidate: function(attrs, next) {
//
// Generate random serial with 10 hexadecial digits
//
if (!attrs.serial) {
var serial = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < sails.config.pictogram.serialSize; i++ )
serial += possible.charAt(Math.floor(Math.random() * possible.length));
attrs.serial = serial;
}
next();
}
};
/* global sails */
/** /**
* picto.js * picto.js
* *
* @description :: TODO: Write a short summary of how this model works and what it represents here. * @description :: TODO: Write a short summary of how this model works and what it represents here.
* @docs :: http://sailsjs.org/#!documentation/models * @docs :: http://sailsjs.org/#!documentation/models
*/ */
module.exports = { module.exports = {
tableName : 'picto', tableName: 'picto',
migrate : 'safe', migrate: 'safe',
schema : true, schema: true,
autoPK : false, autoPK: false,
autoCreatedAt : false, autoCreatedAt: false,
autoUpdatedAt : false, autoUpdatedAt: false,
attributes: { attributes: {
id: { id: {
type: "integer", type: 'integer',
autoIncrement: true, autoIncrement: true,
primaryKey: true, primaryKey: true,
unique: true unique: true
}, },
uri: { uri: {
required: true, required: true,
type: "string", type: 'string',
size: 250 size: 250
}, },
source: { // FK de Source. 1 source to N pictos source: { // 1 Source to N Pictos
columnName: "id_src", columnName: 'id_src',
required: true, required: true,
type: "integer", type: 'integer',
model: "Source" model: 'Source'
}, },
owner: { // FK de Supervisor. 1 a N owner: { // 1 Supervisor to N Owners
columnName: "id_owner", columnName: 'id_owner',
type: "integer", type: 'integer',
required: false, required: false,
model: "Supervisor" model: 'Supervisor'
}, },
category:{ category: {
columnName: "id_cat", columnName: 'id_cat',
type: "integer" type: 'integer'
}, },
// Relación con Expression. [1 Picto to N Expression] expressions: { // 1 Picto to N PictoExp
expressions: { collection: 'PictoExp',
collection: "PictoExp", via: 'picto'
via: "picto"
}, },
// Relación con PictoTag. [1 Picto to N PictoTag] tags: { // 1 Picto to N PictoTag
tags: { collection: 'PictoTag',
collection: "PictoTag", via: 'picto'
via: "picto"
}, },
tagsSup: { // tags created by supervisors tagsSup: {
collection: "PictoTagSup", collection: 'PictoTagSup',
via: "picto" via: 'picto'
}, },
// Relación con PictoAcl. [1 Picto to N PictoAcl] pictoAcls: { // 1 Picto to N PictoAcl
pictoAcls:{ collection: 'PictoAcl',
collection: "PictoAcl", via: 'picto'
via: "picto"
}, },
stusPicto: { stusPicto: {
collection: 'StuPicto', collection: 'StuPicto',
...@@ -66,44 +65,11 @@ module.exports = { ...@@ -66,44 +65,11 @@ module.exports = {
} }
}, },
// toJSON: function () {
// Returns all categories for the given supercategory with the expression in the supervisor language var picto = this.toObject();
// if (picto.owner !== null) {
categories: function(id_sup, id_cat, callback) { picto.uri = sails.config.pictogram.urls.getSupervisorCustomPictoUrl(picto.uri);
Supervisor.findOne(id_sup).exec(function(err, sup) { }
if (err) { return picto;
console.log("Error retrieving categories for supervisor " + id_sup + ": " + err);
return callback(err, []);
}
// 0 for the main categories --> null in DB
// if(id_cat == 0) id_cat = null;
PictoCat.find({id_supercat: id_cat}).populate('exps', {lang: sup.lang}).exec(function(err, pictoCats) {
if (err || !pictoCats || pictoCats.length == 0)
return callback(err, []);
else
return callback(err, pictoCats);
});
});
},
//
// Returns all pictos from a given category with the expression in the supervisor language
//
fromcategory: function(id_sup, id_cat, callback) {
Supervisor.findOne(id_sup).exec(function(err, sup) {
if (err) {
console.log("Error retrieving categories for supervisor " + id_sup + ": " + err);
return callback(err, []);
}
Picto.find({category: id_cat}).populate('expressions', {lang: sup.lang}).exec(function(err, pictos) {
if (err || !pictos || pictos.length == 0)
return callback(err, []);
else
return callback(err, pictos);
});
});
} }
}; };
\ No newline at end of file
/**
* StuDev.js
*
* @description :: TODO: You might write a short summary of how this model works and what it represents here.
* @docs :: http://sailsjs.org/#!documentation/models
*/
module.exports = {
tableName : 'stu_dev',
migrate : 'safe',
schema : true,
autoPK : false,
autoCreatedAt : false,
autoUpdatedAt : false,
attributes: {
id: {
type: "integer",
autoIncrement: true,
primaryKey: true,
unique: true
},
student: {
columnName: 'id_stu',
type: 'integer',
required: true,
model: 'Student'
},
device: {
columnName: 'id_dev',
type: 'integer',
required: true,
model: 'Device'
}
}
};
/** /**
* StuPicto.js * StuPicto.js
* *
* @description :: This model represents the collection of pictos for a student, * @description :: This model represents the collection of pictos for a student,
* with the properties associated to it * with the properties associated to it
* @docs :: http://sailsjs.org/#!documentation/models * @docs :: http://sailsjs.org/#!documentation/models
*/ */
...@@ -13,7 +13,7 @@ module.exports = { ...@@ -13,7 +13,7 @@ module.exports = {
autoPK : false, autoPK : false,
autoCreatedAt : false, autoCreatedAt : false,
autoUpdatedAt : false, autoUpdatedAt : false,
attributes: { attributes: {
id: { id: {
type: "integer", type: "integer",
...@@ -54,7 +54,7 @@ module.exports = { ...@@ -54,7 +54,7 @@ module.exports = {
"id_cat" : null, "id_cat" : null,
"coord_x" : null, "coord_x" : null,
"coord_y" : null, "coord_y" : null,
"status": "enabled" "status": "enabled"
}; };
*/ */
...@@ -79,8 +79,6 @@ module.exports = { ...@@ -79,8 +79,6 @@ module.exports = {
if(attrs.attributes.color !== undefined) if(attrs.attributes.color !== undefined)
var previous_color = attrs.attributes.color; var previous_color = attrs.attributes.color;
console.log(configuration.toString());
attrs.attributes = JSON.parse("{" + configuration.toString() + "}"); attrs.attributes = JSON.parse("{" + configuration.toString() + "}");
// And we store them (If the picto is from picto_core, it has defined the coords) // And we store them (If the picto is from picto_core, it has defined the coords)
...@@ -98,9 +96,8 @@ module.exports = { ...@@ -98,9 +96,8 @@ module.exports = {
if(previous_color !== undefined) if(previous_color !== undefined)
attrs.attributes.color = previous_color; attrs.attributes.color = previous_color;
//console.log(attrs.attributes);
next(); next();
}); });
} }
} }
\ No newline at end of file
/* global sails */
/** /**
* student.js * student.js
* *
...@@ -12,7 +14,7 @@ module.exports = { ...@@ -12,7 +14,7 @@ module.exports = {
autoPK : false, autoPK : false,
autoCreatedAt : false, autoCreatedAt : false,
autoUpdatedAt : false, autoUpdatedAt : false,
attributes: { attributes: {
id: { id: {
type: "integer", type: "integer",
...@@ -83,36 +85,28 @@ module.exports = { ...@@ -83,36 +85,28 @@ module.exports = {
collection: "StuSup", collection: "StuSup",
via: "student" via: "student"
}, },
// Relación con StuDev // Relación con Method. [1 Student to N Method]
stuDevs: {
collection: 'StuDev',
via: 'student'
},
// Relación con Method. [1 Student to N Method]
methods: { methods: {
collection: "Method", collection: "Method",
via: "student" via: "student"
}, },
// Relación con StuPicto. [1 Student to N StuPicto] // Relación con StuPicto. [1 Student to N StuPicto]
stuPicto: { stuPicto: {
collection: "StuPicto", collection: "StuPicto",
via: "student" via: "student"
}, },
// toJSON: function () {
// JSON limitations var student = this.toObject();
// student.pic = sails.config.pictogram.urls.getStudentAvatarUrl(student.pic);
toJSON: function() { delete student.password;
var obj = this.toObject(); return student;
// avoid sending this fields
delete obj.password;
return obj;
}, },
}, },
// //
// Model hook for storing default device configuration adding a new account // Model hook for storing default configuration adding a new account
// //
beforeCreate: function(attrs, next) { beforeCreate: function(attrs, next) {
...@@ -153,7 +147,7 @@ module.exports = { ...@@ -153,7 +147,7 @@ module.exports = {
var bcrypt = require('bcrypt-nodejs'); var bcrypt = require('bcrypt-nodejs');
bcrypt.genSalt(10, function(err, salt) { bcrypt.genSalt(10, function(err, salt) {
if (err) if (err)
return next(err); return next(err);
bcrypt.hash(attrs.password, salt, null, function(err, hash) { bcrypt.hash(attrs.password, salt, null, function(err, hash) {
if (err) if (err)
...@@ -162,22 +156,21 @@ module.exports = { ...@@ -162,22 +156,21 @@ module.exports = {
next(); next();
}); });
}); });
}); });
}, },
// //
// Class method for getting the list of supervisors (therapist + tutors) associated to a given // Class method for getting the list of supervisors (therapist + tutors) associated to a given
// student // student
supervisors: function(id_stu, callback) { supervisors: function(id_stu, callback) {
StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) { StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) {
var l = []; var l = [];
if (err || !stuSups || stuSups.length == 0) if (err || !stuSups || stuSups.length == 0)
return callback(err, l); return callback(err, l);
async.eachSeries(stuSups, async.eachSeries(stuSups,
function(stuSup, next) { function(stuSup, next) {
delete stuSup.supervisor.password;
l.push(stuSup.supervisor); l.push(stuSup.supervisor);
next(); next();
}, },
...@@ -194,15 +187,14 @@ module.exports = { ...@@ -194,15 +187,14 @@ module.exports = {
therapists: function(id_stu, callback) { therapists: function(id_stu, callback) {
StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) { StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) {
var l = []; var l = [];
if (err || !stuSups || stuSups.length == 0) if (err || !stuSups || stuSups.length == 0)
return callback(err, l); return callback(err, l);
async.eachSeries(stuSups, async.eachSeries(stuSups,
function(stuSup, next) { function(stuSup, next) {
// stuSup.supervisor.id > 0 for not retrieving the -1 default supervisor // stuSup.supervisor.id > 0 for not retrieving the -1 default supervisor
if (stuSup.supervisor && stuSup.supervisor.office && stuSup.supervisor.id > 0) { if (stuSup.supervisor && stuSup.supervisor.office && stuSup.supervisor.id > 0) {
delete stuSup.supervisor.password;
l.push(stuSup.supervisor); l.push(stuSup.supervisor);
} }
next(); next();
...@@ -221,15 +213,14 @@ module.exports = { ...@@ -221,15 +213,14 @@ module.exports = {
tutors: function(id_stu, callback) { tutors: function(id_stu, callback) {
StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) { StuSup.find({id_stu: id_stu}).populate('supervisor').exec(function(err, stuSups) {
var l = []; var l = [];
if (err || !stuSups || stuSups.length == 0) if (err || !stuSups || stuSups.length == 0)
return callback(err, l); return callback(err, l);
async.eachSeries(stuSups, async.eachSeries(stuSups,
function(stuSup, next) { function(stuSup, next) {
// stuSup.supervisor.id > 0 for not retrieving the -1 default supervisor // stuSup.supervisor.id > 0 for not retrieving the -1 default supervisor
if (stuSup.supervisor && !stuSup.supervisor.office && stuSup.supervisor.id > 0) { if (stuSup.supervisor && !stuSup.supervisor.office && stuSup.supervisor.id > 0) {
delete stuSup.supervisor.password;
l.push(stuSup.supervisor); l.push(stuSup.supervisor);
} }
next(); next();
...@@ -250,119 +241,56 @@ module.exports = { ...@@ -250,119 +241,56 @@ module.exports = {
StuPicto.find({student: id_stu}).populate('picto').exec(function(err, stuPictos) { StuPicto.find({student: id_stu}).populate('picto').exec(function(err, stuPictos) {
var l = []; var l = [];
if (err || !stuPictos || stuPictos.length == 0) if (err || !stuPictos || stuPictos.length == 0)
return callback(err, l); return callback(err, l);
async.eachSeries(stuPictos, function(stuPicto, cb) { async.eachSeries(stuPictos, function(stuPicto, cb) {
// Populate expressions to get it with the picto // Populate expressions to get it with the picto
Picto.findOne(stuPicto.picto.id) Picto.findOne(stuPicto.picto.id)
.populate('expressions', {lang: student.lang}) .populate('expressions', {lang: student.lang})
.exec(function(err, picto) { .exec(function(err, picto) {
if (err) throw err; if (err) throw err;
var stuPictoToAdd = { var stuPictoToAdd = {
"id": stuPicto.id, "id": stuPicto.id,
"picto": stuPicto.picto, "picto": stuPicto.picto,
"expression": picto.expressions[0], "expression": picto.expressions[0],
"attributes": stuPicto.attributes "attributes": stuPicto.attributes
}; };
l.push(stuPictoToAdd); l.push(stuPictoToAdd);
cb(); // next in the series cb(); // next in the series
}); });
}, },
function(err) { function(err) {
callback(err, l); // out loop finished, return result callback(err, l); // out loop finished, return result
}); });
}); });
} }
});
},
//
// Class method for getting devices associated to student
//
devices: function(id_stu, callback) {
var list = [];
// Get devices for that student id
StuDev.find({student: id_stu})
.exec(function(err, stuDevs) {
if (err) return callback(err, []);
async.eachSeries(stuDevs, function(stuDev, cb) {
Device.findOne(stuDev.device)
.exec(function(err, dev) {
if (err) throw err;
list.push(dev);
cb(); // next in the series
});
},
function(err) {
if (err) throw err;
return callback(err, list); // loop finished, next in the outer loop
});
});
},
//
// Class method for link a device to a student (stu_dev)
//
link_device: function(id_stu, id_dev_firm, callback) {
// Find the student by student id
Student.findOne({id: id_stu}).exec(function(err, student) {
if (err || !student){
console.log("student not found");
return callback(err, null);
}
// Find the device id by device id firmware
Device.findOne({idFirmware: id_dev_firm}).exec(function(err, device){
if (err || !device){
console.log("Device not found");
return callback(err, null);
}
// Create a new entry in stuDev by id_stu and id_dev
StuDev.create({student: student.id, device: device.id}).exec(function(err, stuDev){
if (err || !stuDev){
console.log("StuDev not created");
return callback(err, null);
}
// Concat the description of device to stuDev and get it back
console.log(JSON.stringify(stuDev));
// It is is created
return callback(err, device);
});
});
}); });
}, },
// //
// Returns all the tries of the student // Returns all the tries of the student
// //
tries: function(id_stu, callback) { tries: function(id_stu, callback) {
var l_met = []; var l_met = [];
Method.find({ id_stu: id_stu }).exec(function(err, methods) { Method.find({ id_stu: id_stu }).exec(function(err, methods) {
if (err || !methods || methods.length == 0) if (err || !methods || methods.length == 0)
return callback(err, []); return callback(err, []);
// eachSeries // eachSeries
async.eachSeries( async.eachSeries(
// 1st array of items // 1st array of items
methods, methods,
// 2nd function to operate over one item // 2nd function to operate over one item
function(method, next) { function(method, next) {
// Original: Devolver el objeto con el método completo / instructions / workinSessions / Tries // Original: Devolver el objeto con el método completo / instructions / workinSessions / Tries
...@@ -371,7 +299,7 @@ module.exports = { ...@@ -371,7 +299,7 @@ module.exports = {
Instruction.find({ id_met: method.id }).populate('workingSessions').exec(function(err, instructions) { Instruction.find({ id_met: method.id }).populate('workingSessions').exec(function(err, instructions) {
if (err || !instructions || instructions.length == 0) if (err || !instructions || instructions.length == 0)
console.log("error finding instructions"); console.log("error finding instructions");
// Push method // Push method
l_met.push({ l_met.push({
"id": method.id, "id": method.id,
...@@ -381,14 +309,14 @@ module.exports = { ...@@ -381,14 +309,14 @@ module.exports = {
"registration": method.registration, "registration": method.registration,
"notes": method.notes, "notes": method.notes,
"instructions": instructions, "instructions": instructions,
}); });
next(); next();
}); });
}, },
// 3rd final function when all is ready // 3rd final function when all is ready
function (err){ function (err){
console.log("Final function"); console.log("Final function");
console.log(JSON.stringify(l_met)); console.log(JSON.stringify(l_met));
return callback(err, l_met); return callback(err, l_met);
...@@ -405,28 +333,13 @@ module.exports = { ...@@ -405,28 +333,13 @@ module.exports = {
Student.findOne(id_stu).exec(function(err, student) { Student.findOne(id_stu).exec(function(err, student) {
if (err || !student) if (err || !student)
throw err; throw err;
// set office to NULL to unlink it // set office to NULL to unlink it
student.office = null; student.office = null;
student.save(function(err, saved) { student.save(function(err, saved) {
if (err) return cb(err); if (err) return cb(err);
return cb(); return cb();
}); });
});
},
sqlquery: function(query, callback) {
//code
Student.query(query, function (err,result) {
// Error handling
if (err) {
sails.log.debug(err);
return callback(err, {});
} else {
console.log("Data from raw sql query:", result);
return callback(err, result);
}
}); });
}, },
...@@ -435,7 +348,7 @@ module.exports = { ...@@ -435,7 +348,7 @@ module.exports = {
// and to check that the user new username is not already registered // and to check that the user new username is not already registered
// //
beforeUpdate: function(attrs, next) { beforeUpdate: function(attrs, next) {
// remove username as it shouldn't be changed // remove username as it shouldn't be changed
delete attrs.username; delete attrs.username;
...@@ -445,7 +358,7 @@ module.exports = { ...@@ -445,7 +358,7 @@ module.exports = {
var bcrypt = require('bcrypt-nodejs'); var bcrypt = require('bcrypt-nodejs');
bcrypt.genSalt(10, function(err, salt) { bcrypt.genSalt(10, function(err, salt) {
if (err || !attrs.password) if (err || !attrs.password)
return next(err); return next(err);
bcrypt.hash(attrs.password, salt, null, function(err, hash) { bcrypt.hash(attrs.password, salt, null, function(err, hash) {
if (err) if (err)
......
/* global Supervisor, sails */
/** /**
* supervisor.js * supervisor.js
* *
...@@ -5,18 +7,6 @@ ...@@ -5,18 +7,6 @@
* @docs :: http://sailsjs.org/#!documentation/models * @docs :: http://sailsjs.org/#!documentation/models
*/ */
// Returns a 32 digit number from a string
String.prototype.hashCode = function() {
var hash = 0, i, chr, len;
if (this.length == 0) return hash;
for (i = 0, len = this.length; i < len; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer (| or bit a bit)
}
return hash;
};
module.exports = { module.exports = {
connection : 'localMysql', connection : 'localMysql',
tableName : 'supervisor', tableName : 'supervisor',
...@@ -25,7 +15,7 @@ module.exports = { ...@@ -25,7 +15,7 @@ module.exports = {
autoPK : false, autoPK : false,
autoCreatedAt : false, autoCreatedAt : false,
autoUpdatedAt : false, autoUpdatedAt : false,
attributes: { attributes: {
id: { id: {
type: "integer", type: "integer",
...@@ -94,17 +84,17 @@ module.exports = { ...@@ -94,17 +84,17 @@ module.exports = {
required: false, required: false,
model: 'Office' model: 'Office'
}, },
// Relación con WorkingSession. [1 Supervisor to N WorkingSession] // Relación con WorkingSession. [1 Supervisor to N WorkingSession]
workingSessions:{ workingSessions:{
collection: "WorkingSession", collection: "WorkingSession",
via: "supervisor" via: "supervisor"
}, },
// Relación con Picto. [1 Supervisor to N Picto] // Relación con Picto. [1 Supervisor to N Picto]
ownPictos:{ ownPictos:{
collection: "Picto", collection: "Picto",
via: "owner" via: "owner"
}, },
// Relación con PictoAcl. [1 Supervisor to N PictoAcl] // Relación con PictoAcl. [1 Supervisor to N PictoAcl]
aclPictos:{ aclPictos:{
collection: "PictoAcl", collection: "PictoAcl",
via: "supervisor" via: "supervisor"
...@@ -114,12 +104,12 @@ module.exports = { ...@@ -114,12 +104,12 @@ module.exports = {
collection: "StuSup", collection: "StuSup",
via: "supervisor" via: "supervisor"
}, },
// Relación con Action. [1 Supervisor to N Action] // Relación con Action. [1 Supervisor to N Action]
actions: { actions: {
collection: "Action", collection: "Action",
via: "supervisor" via: "supervisor"
}, },
// Relación con MetaMethods. [1 Supervisor to N MetaMethods] // Relación con MetaMethods. [1 Supervisor to N MetaMethods]
metaMethods: { metaMethods: {
collection: "MetaMethod", collection: "MetaMethod",
via: "supervisor" via: "supervisor"
...@@ -128,21 +118,21 @@ module.exports = { ...@@ -128,21 +118,21 @@ module.exports = {
// //
// JSON limitations // JSON limitations
// //
toJSON: function() { toJSON: function () {
var obj = this.toObject(); var supervisor = this.toObject();
// avoid sending this fields supervisor.pic = sails.config.pictogram.urls.getSupervisorAvatarUrl(supervisor.pic);
delete obj.password; delete supervisor.password;
return obj; return supervisor;
}, },
// //
// sendMail // sendMail
// adds a new entry into pending_registration // adds a new entry into pending_registration
// and send an email confirmation to the user // and send an email confirmation to the user
sendMail: function() { sendMail: function() {
var hash_code = (this.name + this.email + this.phone);
var hash_code = (this.name + this.email + this.phone).hashCode(); // Send email confirmation
// Send email confirmation
var nodemailer = require('nodemailer'); var nodemailer = require('nodemailer');
// create reusable transporter object using SMTP transport // create reusable transporter object using SMTP transport
...@@ -165,7 +155,7 @@ module.exports = { ...@@ -165,7 +155,7 @@ module.exports = {
to: this.email, // list of receivers to: this.email, // list of receivers
subject: 'Account activation', // Subject line subject: 'Account activation', // Subject line
//text: 'plain text', // plaintext body //text: 'plain text', // plaintext body
html: textBody // html body html: textBody // html body
}; };
// send mail with defined transport object // send mail with defined transport object
...@@ -184,104 +174,79 @@ module.exports = { ...@@ -184,104 +174,79 @@ module.exports = {
// Model hook for storing encrypted password when adding a new account // Model hook for storing encrypted password when adding a new account
// and to check that the user is not already registered // and to check that the user is not already registered
// //
beforeCreate: function(attrs, next) { beforeCreate: function (attrs, next) {
var async = require('async');
// We have to encryption AFTER checking user does not exist
// so... we use async.series to ensure task completion async.series(
[
function (cb) {
Supervisor.findOne({ email: attrs.email }).then(function (supervisor) {
if (supervisor) {
cb(new Error('Email being used'));
} else {
cb();
}
})
.catch(function () {
cb();
});
},
async.series([ function (cb) {
function(cb) { // check email is new var bcrypt = require('bcrypt-nodejs');
Supervisor.findByEmail(attrs.email).exec(function(err, users) { if (attrs.password) {
if (err) return cb(err); attrs.password = bcrypt.hashSync(attrs.password, bcrypt.genSaltSync());
if (users.length > 0) }
return cb(new Error('User exists')); cb();
cb(); }
}); ],
}, function (err) {
function(cb) { // encrypt password if (err) {
var bcrypt = require('bcrypt-nodejs'); next(err);
bcrypt.genSalt(10, function(err, salt) { } else {
if (err) return cb(err); next();
bcrypt.hash(attrs.password, salt, null, function(err, hash) { }
if (err) return cb(err); }
attrs.password = hash; );
cb();
});
});
}
], function(err) {
if (err) return next(err);
next();
});
}, },
// //
// Model hook for storing encrypted password when updating an account // Model hook for storing encrypted password when updating an account
// and to check that the user new email is not already registered // and to check that the user new email is not already registered
// //
beforeUpdate: function(attrs, next) { beforeUpdate: function (attrs, next) {
var async = require('async');
async.series([
function(cb) { async.series(
// [
// Check that user email does not exist function (cb) {
// Supervisor.findOne({ email: attrs.email }).then(function (supervisor) {
if(attrs.email){ if (supervisor && supervisor.id !== attrs.id) {
Supervisor.findByEmail(attrs.email).exec(function(err, users) { cb(new Error('Email being used'));
if (err) } else {
return cb(err); cb();
if (users.length > 0) }
return cb(new Error('User email already exists')); })
cb(); .catch(function () {
}); cb();
} else { });
return cb(new Error('No email in user attributes')); },
}
},
function(cb) {
//
// Encrypt password before insertion
//
if(attrs.password){
var bcrypt = require('bcrypt-nodejs');
bcrypt.genSalt(10, function(err, salt) {
if (err) return cb(err);
bcrypt.hash(attrs.password, salt, null, function(err, hash) {
if (err) return cb(err);
attrs.password = hash;
cb();
});
});
}else{
cb();
}
}], function(err) {
if (err) return next(err);
next();
});
},
//
// Class method for getting the list of students associated to a given
// supervisor
students: function(id_sup, callback) {
StuSup.find({id_sup: id_sup}).populate('student').exec(function(err, stuSups) {
var l = [];
if (err || !stuSups || stuSups.length == 0)
return callback(err, l);
async.eachSeries(stuSups, function (cb) {
function(stuSup, next) { var bcrypt = require('bcrypt-nodejs');
l.push(stuSup.student); if (attrs.password) {
attrs.password = bcrypt.hashSync(attrs.password, bcrypt.genSaltSync());
}
cb();
}
],
function (err) {
if (err) {
next(err);
} else {
next(); next();
},
function (err) {
return callback(err, l);
} }
); }
}); );
} }
}; };
...@@ -11,7 +11,7 @@ principal: ...@@ -11,7 +11,7 @@ principal:
- Los estilos se encuentran [/sails/src/assets/styles][3] - Los estilos se encuentran [/sails/src/assets/styles][3]
- Los scripts y vistas se encuentran en [/sails/src/assets/scripts][4] - Los scripts y vistas se encuentran en [/sails/src/assets/scripts][4]
[1]: ../../../install.sh [1]: /softuno/pictogram/blob/develop/sails/install.sh
[2]: ../../../README.md [2]: /softuno/pictogram/tree/develop/sails
[3]: ../styles [3]: /softuno/pictogram/tree/develop/sails/src/assets/styles
[4]: ../scripts [4]: /softuno/pictogram/tree/develop/sails/src/assets/scripts
...@@ -64,12 +64,6 @@ ...@@ -64,12 +64,6 @@
"delete": "Delete", "delete": "Delete",
"delete_template": "Delete from templates", "delete_template": "Delete from templates",
"description": "Description", "description": "Description",
"dev_not_found": "There is no device with this ID.",
"device_id_firmware": "Device ID Firmware",
"device_not_registered": "Device not registered",
"device_registered": "Device registered with firmware id {{idFirmware}} and serial {{serial}}",
"device_setup": "Device setup",
"devices": "Devices",
"disabled": "Disabled. Clic for invisible", "disabled": "Disabled. Clic for invisible",
"double_click": "Double click", "double_click": "Double click",
"down": "Down", "down": "Down",
...@@ -186,8 +180,6 @@ ...@@ -186,8 +180,6 @@
"previous_sessions": "Previous sessions", "previous_sessions": "Previous sessions",
"read_picto": "Read picto", "read_picto": "Read picto",
"register": "Sign in", "register": "Sign in",
"register_button": "Register",
"register_device": "Register device",
"remember": "Remember me", "remember": "Remember me",
"reports": "Reports", "reports": "Reports",
"save": "Save", "save": "Save",
......
...@@ -65,11 +65,6 @@ ...@@ -65,11 +65,6 @@
"delete_template": "Eliminar de plantillas", "delete_template": "Eliminar de plantillas",
"description": "Descripción", "description": "Descripción",
"dev_not_found": "No se ha encontrado dispositivo con ese ID.", "dev_not_found": "No se ha encontrado dispositivo con ese ID.",
"device_id_firmware": "ID firmware del dispositivo",
"device_not_registered": "Dispositivo no registrado",
"device_registered": "Dispositivo registrado con id firmware: {{idFirmware}} y número de serie: {{serial}}",
"device_setup": "Configuración dispositivos",
"devices": "Dispositivos",
"disabled": "Desactivado. Clic para invisible", "disabled": "Desactivado. Clic para invisible",
"double_click": "Double clic", "double_click": "Double clic",
"down": "Abajo", "down": "Abajo",
...@@ -187,7 +182,6 @@ ...@@ -187,7 +182,6 @@
"read_picto": "Leer picto", "read_picto": "Leer picto",
"register": "Regístrate", "register": "Regístrate",
"register_button": "Registrar", "register_button": "Registrar",
"register_device": "Registrar dispositivo",
"remember": "No cerrar sesión", "remember": "No cerrar sesión",
"reports": "Informes", "reports": "Informes",
"save": "Guardar", "save": "Guardar",
......
...@@ -16,7 +16,7 @@ var dashboardApp = angular.module('dashboardApp', [ ...@@ -16,7 +16,7 @@ var dashboardApp = angular.module('dashboardApp', [
'ngAnimate', 'ngAnimate',
'ngSanitize', 'ngSanitize',
'ngToast', // This is for pop-up notifications 'ngToast', // This is for pop-up notifications
'ng-context-menu', 'ng-context-menu',
'chart.js', // Interactive charts! 'chart.js', // Interactive charts!
'ngLodash' 'ngLodash'
//'ngWebsocket' //'ngWebsocket'
...@@ -36,7 +36,7 @@ dashboardApp.config(['ngToastProvider', function(ngToast) { ...@@ -36,7 +36,7 @@ dashboardApp.config(['ngToastProvider', function(ngToast) {
dashboardApp.config(function($translateProvider) { dashboardApp.config(function($translateProvider) {
/* i18n */ /* i18n */
$translateProvider.useStaticFilesLoader({ $translateProvider.useStaticFilesLoader({
'prefix': '/app/i18n/', 'prefix': '/app/i18n/',
'suffix': '.json' 'suffix': '.json'
...@@ -149,12 +149,6 @@ dashboardApp.config(function($stateProvider, $urlRouterProvider) { ...@@ -149,12 +149,6 @@ dashboardApp.config(function($stateProvider, $urlRouterProvider) {
controller: 'AdminCtrl', controller: 'AdminCtrl',
abstract: true, abstract: true,
}) })
.state('devices', {
url: '/devices',
parent: 'admin',
templateUrl: 'modules/admin/views/devices.html',
controller: 'AdminDevicesCtrl',
})
.state('offices', { .state('offices', {
url: '/offices', url: '/offices',
parent: 'admin', parent: 'admin',
...@@ -170,8 +164,8 @@ dashboardApp.config(function($stateProvider, $urlRouterProvider) { ...@@ -170,8 +164,8 @@ dashboardApp.config(function($stateProvider, $urlRouterProvider) {
; ;
$urlRouterProvider.otherwise('/login'); $urlRouterProvider.otherwise('/login');
}); });
/* reCAPTCHA */ /* reCAPTCHA */
...@@ -211,4 +205,3 @@ dashboardApp.factory("newconfirm", function ($window, $q, $timeout) { ...@@ -211,4 +205,3 @@ dashboardApp.factory("newconfirm", function ($window, $q, $timeout) {
return newconfirm; return newconfirm;
}); });
//// template file for sails/src/config/local.js
/**
* Local environment settings
*
* Use this file to specify configuration settings for use while developing
* the app on your personal system: for example, this would be a good place
* to store database or email passwords that apply only to you, and shouldn't
* be shared with others in your organization.
*
* These settings take precedence over all other config files, including those
* in the env/ subfolder.
*
* PLEASE NOTE:
* local.js is included in your .gitignore, so if you're using git
* as a version control solution for your Sails app, keep in mind that
* this file won't be committed to your repository!
*
* Good news is, that means you can specify configuration for your local
* machine in this file without inadvertently committing personal information
* (like database passwords) to the repo. Plus, this prevents other members
* of your team from commiting their local configuration changes on top of yours.
*
* In a production environment, you probably want to leave this file out
* entirely and leave all your settings in env/production.js
*
*
* For more information, check out:
* http://sailsjs.org/#!/documentation/anatomy/myApp/config/local.js.html
*/
module.exports = {
/***************************************************************************
* Your SSL certificate and key, if you want to be able to serve HTTP *
* responses over https:// and/or use websockets over the wss:// protocol *
* (recommended for HTTP, strongly encouraged for WebSockets) *
* *
* In this example, we'll assume you created a folder in your project, *
* `config/ssl` and dumped your certificate/key files there: *
***************************************************************************/
ssl: {
ca: require('fs').readFileSync(__dirname + '/ssl/goddady/gd.yottacode.com.bundle.crt'),
key: require('fs').readFileSync(__dirname + '/ssl/goddady/gd.yottacode.com.key'),
cert: require('fs').readFileSync(__dirname + '/ssl/goddady/gd.yottacode.com.crt')
},
/***************************************************************************
* The `port` setting determines which TCP port your app will be *
* deployed on. *
* *
* Ports are a transport-layer concept designed to allow many different *
* networking applications run at the same time on a single computer. *
* More about ports: *
* http://en.wikipedia.org/wiki/Port_(computer_networking) *
* *
* By default, if it's set, Sails uses the `PORT` environment variable. *
* Otherwise it falls back to port 1337. *
* *
* In env/production.js, you'll probably want to change this setting *
* to 80 (http://) or 443 (https://) if you have an SSL certificate *
***************************************************************************/
port: process.env.PORT || 1337,
/***************************************************************************
* The runtime "environment" of your Sails app is either typically *
* 'development' or 'production'. *
* *
* In development, your Sails app will go out of its way to help you *
* (for instance you will receive more descriptive error and *
* debugging output) *
* *
* In production, Sails configures itself (and its dependencies) to *
* optimize performance. You should always put your app in production mode *
* before you deploy it to a server. This helps ensure that your Sails *
* app remains stable, performant, and scalable. *
* *
* By default, Sails sets its environment using the `NODE_ENV` environment *
* variable. If NODE_ENV is not set, Sails will run in the *
* 'development' environment. *
***************************************************************************/
// environment: process.env.NODE_ENV || 'development'
};
'use strict';
//--------------------------
// Admin Devices Controller
//--------------------------
dashboardControllers.controller('AdminDevicesCtrl', function AdminDevicesCtrl($scope, $http, config) {
// The last parameter, config, is injected from config.js (defined in dashboardConfig module)
// Don't show the message at the begining and clean form
$scope.showmessagedevice = false;
// For message
$scope.tdata = {
idFirmware: '',
serial: '',
};
$scope.formdatadevice = {
idFirmware: '',
desc: '',
serial: ''
};
// List of free serials
$scope.freeserials = [];
$http
.get(config.backend+'/dev/freeserials')
.success(function(data, status, headers, config) {
// Add to list
$scope.freeserials = data;
console.log("Free serials listed");
})
.error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
});
// Generate serial
$scope.generate_serial = function(){
$http
.post(config.backend+'/dev/create')
.success(function(data, status, headers, config) {
$scope.showmessagedevice = true;
$scope.alertdevice = "alert-success";
$scope.messagedevice = "serial_created";
$scope.tdata.serial = data.serial;
console.log("Serial number created: " + data.serial);
// Add to list
$scope.freeserials.push(data);
})
.error(function(data, status, headers, config) {
$scope.showmessagedevice = true;
$scope.alertdevice = "alert-danger";
$scope.messagedevice = "serial_not_created";
console.log("Error from API: " + data.error);
});
};
// Register device with a free serial
$scope.register_device = function(){
$http
.post(config.backend+'/dev/register', $scope.formdatadevice)
.success(function(data, status, headers, config) {
$scope.showmessagedevice = true;
$scope.alertdevice = "alert-success";
$scope.messagedevice = "device_registered";
// For message
$scope.tdata.serial = $scope.formdatadevice.serial;
$scope.tdata.idFirmware = $scope.formdatadevice.idFirmware;
// Delete in view of free serials
for(var i=0; i < $scope.freeserials.length; i++) {
if($scope.formdatadevice.serial == $scope.freeserials[i].serial)
$scope.freeserials.splice(i,1);
}
console.log("Device registered with id firmware "+ $scope.formdatadevice.idFirmware +" and serial " + $scope.formdatadevice.serial);
// Clean form
$scope.formdatadevice = {
idFirmware: '',
desc: '',
serial: ''
};
})
.error(function(data, status, headers, config) {
$scope.showmessagedevice = true;
$scope.alertdevice = "alert-danger";
$scope.messagedevice = "device_not_registered";
console.log("Error from API: " + data.error);
});
};
});
\ No newline at end of file
...@@ -97,7 +97,7 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -97,7 +97,7 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
lang: office.lang, lang: office.lang,
id: office.id, id: office.id,
maxStudents: office.maxStudents maxStudents: office.maxStudents
}; };
$scope.formdataoffice.admin = { $scope.formdataoffice.admin = {
id: office.admin.id, id: office.admin.id,
...@@ -109,18 +109,18 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -109,18 +109,18 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
// Save an Office updated // Save an Office updated
$scope.save_office = function(){ $scope.save_office = function(){
var office = $scope.formdataoffice; var office = $scope.formdataoffice;
console.log("1) Before searching admin id by email: " + JSON.stringify(office)); console.log("1) Before searching admin id by email: " + JSON.stringify(office));
// If email admin is filled // If email admin is filled
// search id by email admin // search id by email admin
console.log("2) Searching admin id by email"); console.log("2) Searching admin id by email");
$http $http
.get(config.backend+'/sup?where={"email":"'+ office.admin.email +'"}') .get(config.backend + '/sup/email/' + office.admin.email)
.then(function(result) { .then(function(result) {
// result <-- data, status, headers, config // result <-- data, status, headers, config
console.log("2.0) Data recovered: " + JSON.stringify(result.data[0])); console.log("2.0) Data recovered: " + JSON.stringify(result.data[0]));
// If exists the email // If exists the email
if(result.data.length > 0){ if(result.data.length > 0){
office.admin.id = result.data[0].id; office.admin.id = result.data[0].id;
console.log("2.1) Exists: " + office.admin.id); console.log("2.1) Exists: " + office.admin.id);
// Delete the email, the id and id_off is the only needed // Delete the email, the id and id_off is the only needed
...@@ -130,12 +130,12 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -130,12 +130,12 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
office.admin.id = null; office.admin.id = null;
delete(office.admin.email); delete(office.admin.email);
} }
console.log("3) Inside search by email admin: " + JSON.stringify(office)); console.log("3) Inside search by email admin: " + JSON.stringify(office));
// Returns the put request // Returns the put request
return $http.put(config.backend+'/office/'+office.id, office); return $http.put(config.backend+'/office/'+office.id, office);
}) })
.then(function(result){ .then(function(result){
console.log("4) Inside 2º then: " + JSON.stringify(result.data)); console.log("4) Inside 2º then: " + JSON.stringify(result.data));
// Show success message // Show success message
$scope.showmessageoffice = true; $scope.showmessageoffice = true;
...@@ -148,14 +148,14 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -148,14 +148,14 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
// Update the view: Se recorre el array de objetos json para buscarlo // Update the view: Se recorre el array de objetos json para buscarlo
for(var i=0; i < $scope.offices.length; i++) { for(var i=0; i < $scope.offices.length; i++) {
if(office.id == $scope.offices[i].id){ if(office.id == $scope.offices[i].id){
$scope.offices[i].name = result.data.name; $scope.offices[i].name = result.data.name;
$scope.offices[i].address = result.data.address; $scope.offices[i].address = result.data.address;
$scope.offices[i].contactPerson = result.data.contactPerson; $scope.offices[i].contactPerson = result.data.contactPerson;
$scope.offices[i].email = result.data.email; $scope.offices[i].email = result.data.email;
$scope.offices[i].phone1 = result.data.phone1; $scope.offices[i].phone1 = result.data.phone1;
$scope.offices[i].phone2 = result.data.phone2; $scope.offices[i].phone2 = result.data.phone2;
$scope.offices[i].lang = result.data.lang; $scope.offices[i].lang = result.data.lang;
$scope.offices[i].maxStudents = result.data.maxStudents; $scope.offices[i].maxStudents = result.data.maxStudents;
// Only if returns an admin // Only if returns an admin
...@@ -163,7 +163,7 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -163,7 +163,7 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
$scope.offices[i].admin.id = result.data.admin.id; $scope.offices[i].admin.id = result.data.admin.id;
$scope.offices[i].admin.name = result.data.admin.name; $scope.offices[i].admin.name = result.data.admin.name;
$scope.offices[i].admin.surname = result.data.admin.surname; $scope.offices[i].admin.surname = result.data.admin.surname;
$scope.offices[i].admin.email = result.data.admin.email; $scope.offices[i].admin.email = result.data.admin.email;
$scope.offices[i].admin.phone = result.data.admin.phone; $scope.offices[i].admin.phone = result.data.admin.phone;
}else{ }else{
delete($scope.offices[i].admin); delete($scope.offices[i].admin);
...@@ -193,13 +193,13 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -193,13 +193,13 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
// search id by email admin // search id by email admin
console.log("2) Searching admin id by email"); console.log("2) Searching admin id by email");
$http $http
.get(config.backend+'/sup?where={"email":"'+ office.admin.email +'"}') .get(config.backend + '/sup/email/' + office.admin.email)
.then(function(result) { .then(function(result) {
// result <-- data, status, headers, config // result <-- data, status, headers, config
console.log("2.0) Data recovered: " + JSON.stringify(result.data[0])); console.log("2.0) Data recovered: " + JSON.stringify(result.data[0]));
// If exists the email // If exists the email
if(result.data.length > 0){ if(result.data.length > 0){
sup = result.data[0]; sup = result.data[0];
office.admin.id = result.data[0].id; office.admin.id = result.data[0].id;
console.log("2.1) Exists: " + office.admin.id); console.log("2.1) Exists: " + office.admin.id);
// Delete the email, the id is the only needed // Delete the email, the id is the only needed
...@@ -208,12 +208,12 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -208,12 +208,12 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
}else{ }else{
delete(office.admin); delete(office.admin);
} }
console.log("3) Inside search by email admin: " + JSON.stringify(office)); console.log("3) Inside search by email admin: " + JSON.stringify(office));
// Returns the put request // Returns the put request
return $http.post(config.backend+'/office', office); return $http.post(config.backend+'/office', office);
}) })
.then(function(result){ .then(function(result){
console.log("4) Inside 2º then: " + JSON.stringify(result.data)); console.log("4) Inside 2º then: " + JSON.stringify(result.data));
// Show success message // Show success message
$scope.showmessageoffice = true; $scope.showmessageoffice = true;
...@@ -244,7 +244,7 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -244,7 +244,7 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
} }
// Add to the list of office in view // Add to the list of office in view
$scope.offices.push(result.data.office); $scope.offices.push(result.data.office);
}) })
.catch(function(result){ .catch(function(result){
console.log("Error: " + result.data.error); console.log("Error: " + result.data.error);
...@@ -265,10 +265,10 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -265,10 +265,10 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
$http $http
.delete(config.backend+'/office/'+ office.id) .delete(config.backend+'/office/'+ office.id)
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
// Eliminar de la vista: Se recorre el array de objetos json para buscarlo // Eliminar de la vista: Se recorre el array de objetos json para buscarlo
for(var i=0; i < $scope.offices.length; i++) { for(var i=0; i < $scope.offices.length; i++) {
if(office.id == $scope.offices[i].id) if(office.id == $scope.offices[i].id)
$scope.offices.splice(i,1); $scope.offices.splice(i,1);
} }
console.log("Office deleted:" + office.name); console.log("Office deleted:" + office.name);
...@@ -288,4 +288,4 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s ...@@ -288,4 +288,4 @@ dashboardControllers.controller('AdminOfficesCtrl', function AdminOfficesCtrl($s
}); });
} }
}; };
}); });
\ No newline at end of file
...@@ -23,7 +23,7 @@ dashboardControllers.controller('AdminSupervisorsCtrl', function AdminSupervisor ...@@ -23,7 +23,7 @@ dashboardControllers.controller('AdminSupervisorsCtrl', function AdminSupervisor
// List of supervisors // List of supervisors
$http $http
.get(config.backend+'/sup') .get(config.backend+'/sup/all')
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
$scope.supervisors = data; $scope.supervisors = data;
}) })
...@@ -104,7 +104,7 @@ dashboardControllers.controller('AdminSupervisorsCtrl', function AdminSupervisor ...@@ -104,7 +104,7 @@ dashboardControllers.controller('AdminSupervisorsCtrl', function AdminSupervisor
delete supervisor.id; delete supervisor.id;
$http $http
.put(config.backend+'/supervisor/'+supid, supervisor) .put(config.backend + '/sup/' + supid, supervisor)
.success(function(data, status, headers, config) { .success(function(data, status, headers, config) {
$translate('supervisor_updated').then(function (translation) { $translate('supervisor_updated').then(function (translation) {
ngToast.success({ content: translation }); ngToast.success({ content: translation });
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
<header-admin></header-admin> <header-admin></header-admin>
<!-- Tab menu --> <!-- Tab menu -->
<ul class="nav nav-pills nav-justified" ng-init="selectedTab = 'devices'"> <ul class="nav nav-pills nav-justified" ng-init="selectedTab = 'supervisors'">
<li role="presentation" ng-click="selectedTab = 'devices'" ng-class="{'active':selectedTab === 'devices'}"> <li role="presentation" ng-click="selectedTab = 'supervisors'" ng-class="{'active':selectedTab === 'supervisors'}">
<a href="#devices">{{ 'devices' | translate }}</a> <a href="#supervisors">{{ 'supervisors' | translate }}</a>
</li> </li>
<li role="presentation" ng-click="selectedTab = 'offices'" ng-class="{'active':selectedTab === 'offices'}"> <li role="presentation" ng-click="selectedTab = 'offices'" ng-class="{'active':selectedTab === 'offices'}">
<a href="#offices">{{ 'offices' | translate }}</a> <a href="#offices">{{ 'offices' | translate }}</a>
...@@ -23,4 +23,4 @@ ...@@ -23,4 +23,4 @@
<!-- Fin de container --> <!-- Fin de container -->
<!-- Footer Translate --> <!-- Footer Translate -->
<footer-translate></footer-translate> <footer-translate></footer-translate>
\ No newline at end of file
<!-- Admin Devices -->
<div class="row">
<div class="col-sm-6">
<h3 translate>generate_serial</h3>
<form name="GenerateSerialForm" role="form" ng-submit="generate_serial()">
<fieldset>
<div class="form-group">
<button type="submit" class="btn btn-primary" translate>generate</button>
</div>
</fieldset>
</form>
<!-- Alert and success messages -->
<div ng-show="{{ 'showmessagedevice' }}" class="alert" ng-class="alertdevice" translate translate-values="{{tdata}}">{{ messagedevice}}</div>
<h3 translate>register_device</h3>
<form name="RegisterDeviceForm" role="form" ng-submit="register_device()">
<fieldset>
<div class="form-group">
<input type="text" class="form-control" id="device_firmware" name="device_firmware" placeholder="{{ 'firmware' | translate }}" required ng-model="formdatadevice.idFirmware" pattern="[a-zA-Z0-9]+" oninvalid="setCustomValidity('Only admitted letters in upercase or lowercase and digits')" onchange="try{setCustomValidity('')}catch(e){}" />
</div>
<div class="form-group">
<input type="text" class="form-control" id="device_description" name="device_description" placeholder="{{ 'description' | translate }}" required ng-model="formdatadevice.desc" pattern="[a-zA-Z0-9\s.,-_]+" oninvalid="setCustomValidity('Only admitted letters in upercase or lowercase, digits, commas and point.')" onchange="try{setCustomValidity('')}catch(e){}" />
</div>
<div class="form-group">
<input type="text" class="form-control" id="device_serial" name="device_serial" placeholder="{{ 'serial' | translate }}" ng-model="formdatadevice.serial" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary" translate>register_button</button>
</div>
</fieldset>
</form>
</div>
<div class="col-sm-6">
<h3 translate>serial_list</h3>
<ul class="list-group">
<li class="list-group-item" ng-repeat="freeserial in freeserials track by $index">{{freeserial.serial}}</li>
</ul>
</div>
</div>
\ No newline at end of file
...@@ -108,12 +108,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -108,12 +108,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
// Search supervisor by email // Search supervisor by email
$scope.search_sup = function () { $scope.search_sup = function () {
// Find tutor by email // Find tutor by email
$http.get([ $http.get(config.backend + '/sup/email/' + $scope.email_sup)
config.backend,
'/sup?where={"email":"',
$scope.email_sup,
'", "office":{"!": null}}'
].join(''))
.success(function (data) { .success(function (data) {
if (data.length > 0) { if (data.length > 0) {
$scope.supToAdd = data[0]; $scope.supToAdd = data[0];
...@@ -190,7 +185,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -190,7 +185,7 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
// Search tutor by email // Search tutor by email
$scope.search_tutor = function () { $scope.search_tutor = function () {
// Find tutor by email // Find tutor by email
$http.get(config.backend + '/sup?where={"email":"' + $scope.email_tutor + '", "office":null}') $http.get(config.backend + '/sup/email/' + $scope.email_tutor)
.success(function (data) { .success(function (data) {
// If it found the length is > 0 // If it found the length is > 0
if (data.length > 0) { if (data.length > 0) {
...@@ -271,64 +266,8 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl( ...@@ -271,64 +266,8 @@ dashboardControllers.controller('StudentSetupCtrl', function StudentSetupCtrl(
} }
}; };
// TODO issue/357
$scope.delete_device = function (id_dev){
var deleteDevice = $window.confirm('Are you absolutely sure you want to delete?');
if (deleteDevice) {
$http.delete(config.backend + '/stu/' + $scope.studentData.id + '/dev/' + id_dev)
.success(function(data, status, headers, config) {
var i;
// Eliminar de la vista: Se recorre el array de objetos json para buscarlo
for (i = 0; i < $scope.studentDevices.length; i++) {
if (id_dev == $scope.studentDevices[i].id) {
$scope.studentDevices.splice(i,1);
}
}
console.log("Device deleted with id " + id_dev);
})
.error(function(data, status, headers, config) {
$scope.showmessagedevnotfound = true;
$scope.messagedev = "dev_not_deleted";
console.log("Error from API: " + data.error);
});
}
};
// TODO issue/357
$scope.associate_dev = function(){
var stu_dev = {
"id_stu": $scope.studentData.id,
"id_dev_firm": $scope.device_id_firmware
}
$http
.post(config.backend+'/stu/dev/', stu_dev)
.success(function(data, status, headers, config) {
console.log("Created relation");
console.log(JSON.stringify(data));
// Add to the list of devices in view
$scope.studentDevices.push(data);
// Remove the id from the input text form
$scope.device_id_firmware = '';
// Hide not found message if it is displayed
$scope.showmessagedevnotfound = false;
})
.error(function(data, status, headers, config) {
console.log("Error from API: " + data.error);
$scope.showmessagedevnotfound = true;
$scope.messagedev = "dev_not_found";
});
};
// ******************************************************* // *******************************************************
// Devices Setup // Setup
// $scope.studentData.attributes // $scope.studentData.attributes
// Update options attributes // Update options attributes
// //
......
...@@ -206,13 +206,4 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl( ...@@ -206,13 +206,4 @@ dashboardControllers.controller('StudentCtrl', function StudentCtrl(
.error(function () { .error(function () {
// TODO show error with ngToast // TODO show error with ngToast
}); });
$scope.studentDevices = [];
$http.get(config.backend + '/stu/' + $scope.studentData.id + '/devices')
.success(function (data) {
$scope.studentDevices = data;
})
.error(function () {
// TODO show error with ngToast
});
}); });
...@@ -175,41 +175,6 @@ ...@@ -175,41 +175,6 @@
<div class="alert alert-info">{{ 'supervisor_note' | translate }}</div> <div class="alert alert-info">{{ 'supervisor_note' | translate }}</div>
</div> </div>
<!-- Fin de id student-tutors --> <!-- Fin de id student-tutors -->
<!-- Student devices -->
<div id="student_devices">
<h4 translate>devices</h4>
<!-- Formulario para introducir ID de dispositivo -->
<p>
<form role="search" ng-submit="associate_dev()">
<div class="input-group">
<input type="text" class="form-control" placeholder="{{ 'device_id_firmware' | translate }}" name="srch-term-device" id="srch-term-device" ng-model="device_id_firmware" required />
<div class="input-group-btn">
<button class="btn btn-success" type="submit" title="{{ 'add' | translate }}">
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
</div>
</form>
</p>
<!-- Fin del formulario para añadir dispositivo -->
<!-- Alert messages for device not found -->
<div ng-show="{{ 'showmessagedevnotfound' }}" class="alert alert-warning">{{ messagedev | translate }}</div>
<!-- Dispositivos asignados -->
<ul class="list-group" id="user_devices">
<li class="list-group-item" ng-repeat="dev in studentDevices">
<span class="glyphicon glyphicon-phone" aria-hidden="true"></span> {{dev.desc}}
<!-- aquí mejor stusupdev.id -->
<a ng-click="delete_device(dev.id)" class="delete_device" title="{{ 'unlink' | translate }}">
<span class="color_red glyphicon glyphicon-remove-circle" aria-hidden="true"></span>
</a>
</li>
</ul>
<!-- Fin de Dispositivos asignados -->
</div>
<!-- Fin de id student-devices -->
</div> </div>
</div> </div>
<!-- Fin de row --> <!-- Fin de row -->
......
...@@ -92,7 +92,7 @@ dashboardControllers.controller('SetupCtrl', function SetupCtrl( ...@@ -92,7 +92,7 @@ dashboardControllers.controller('SetupCtrl', function SetupCtrl(
delete supervisor.email; delete supervisor.email;
} }
$http.put(config.backend + '/sup', supervisor) $http.put(config.backend + '/sup/' + supervisor.id, supervisor)
.success(function (data) { .success(function (data) {
$translate('data_saved').then(function (translation) { $translate('data_saved').then(function (translation) {
ngToast.success({ content: translation }); ngToast.success({ content: translation });
......
...@@ -87,7 +87,7 @@ img.preview{ ...@@ -87,7 +87,7 @@ img.preview{
legend{ padding-top: 20px; } legend{ padding-top: 20px; }
/* Estilos aplicados por defecto /* Estilos aplicados por defecto
(Móviles y pantallas menores de 992px) (Móviles y pantallas menores de 992px)
*/ */
...@@ -122,7 +122,7 @@ div.languages { ...@@ -122,7 +122,7 @@ div.languages {
padding-top: 10px; padding-top: 10px;
margin: 0; margin: 0;
background-color: #f8f8f8; background-color: #f8f8f8;
border-top: 1px solid #e7e7e7; border-top: 1px solid #e7e7e7;
font-size: 1.2em; font-size: 1.2em;
text-align: center; text-align: center;
} }
...@@ -188,7 +188,7 @@ tr:hover .ops a{ ...@@ -188,7 +188,7 @@ tr:hover .ops a{
#supervisor_header .img_profile{ #supervisor_header .img_profile{
margin-top: 10px; margin-top: 10px;
margin-left: 10px; margin-left: 10px;
margin-bottom: 0; margin-bottom: 0;
width: 50px; width: 50px;
height: 50px; height: 50px;
...@@ -233,11 +233,6 @@ tr:hover .ops a{ ...@@ -233,11 +233,6 @@ tr:hover .ops a{
height: 40px; height: 40px;
} }
/* Panel dipositivos del estudiante */
#student_devices{
margin-top: 30px;
}
/* Panel del estudiante (sin borde superior para pestañas) */ /* Panel del estudiante (sin borde superior para pestañas) */
.student_tab_panel{ .student_tab_panel{
border-top: none; border-top: none;
...@@ -279,7 +274,7 @@ tr:hover .ops a{ ...@@ -279,7 +274,7 @@ tr:hover .ops a{
/* Celdas con input para editar */ /* Celdas con input para editar */
td.editable{ td.editable{
padding: 0px !important; padding: 0px !important;
height: 40px; height: 40px;
} }
...@@ -293,7 +288,7 @@ td.editable input{ ...@@ -293,7 +288,7 @@ td.editable input{
.elipsis{ .elipsis{
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
...@@ -305,7 +300,7 @@ input.editable{ ...@@ -305,7 +300,7 @@ input.editable{
} }
.editable:focus { .editable:focus {
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
border-radius: 5px; border-radius: 5px;
outline: none; outline: none;
...@@ -321,7 +316,7 @@ textarea.editable{ ...@@ -321,7 +316,7 @@ textarea.editable{
padding: 6px; padding: 6px;
margin-bottom: 8px; margin-bottom: 8px;
} }
/* Panel Colecciones */ /* Panel Colecciones */
.drag { opacity: 0.5; } .drag { opacity: 0.5; }
...@@ -427,7 +422,7 @@ textarea.editable{ ...@@ -427,7 +422,7 @@ textarea.editable{
/* Class for pictos when are deactivated to the student, but are visibles */ /* Class for pictos when are deactivated to the student, but are visibles */
/*.picto img.deactivate { /*.picto img.deactivate {
filter: url('#grayscale'); / Versión SVG para IE10, Chrome 17, FF3.5, Safari 5.2 and Opera 11.6 / filter: url('#grayscale'); / Versión SVG para IE10, Chrome 17, FF3.5, Safari 5.2 and Opera 11.6 /
-webkit-filter: grayscale(100%); -webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%); -moz-filter: grayscale(100%);
...@@ -439,9 +434,9 @@ textarea.editable{ ...@@ -439,9 +434,9 @@ textarea.editable{
.picto img.disabled { .picto img.disabled {
position: absolute; position: absolute;
bottom: 0px; /* position will be on bottom */ bottom: 0px; /* position will be on bottom */
left: 0px; left: 0px;
width: 100%; width: 100%;
} }
/* Class for pictos that aren't saw by the student */ /* Class for pictos that aren't saw by the student */
...@@ -521,7 +516,7 @@ textarea.editable{ ...@@ -521,7 +516,7 @@ textarea.editable{
/* Para que la altura de los li de la lista se adapte al tamaño automáticamente */ /* Para que la altura de los li de la lista se adapte al tamaño automáticamente */
.list-group-item{ .list-group-item{
overflow:hidden; overflow:hidden;
} }
/* Etiquetas dentro de las ventanas modales de info y etiquetas de los pictos */ /* Etiquetas dentro de las ventanas modales de info y etiquetas de los pictos */
...@@ -662,7 +657,7 @@ textarea.editable{ ...@@ -662,7 +657,7 @@ textarea.editable{
/* Link to show the try actions */ /* Link to show the try actions */
.try_details{ .try_details{
visibility: hidden; visibility: hidden;
font-size: 2em; font-size: 2em;
} }
.try:hover .try_details{ .try:hover .try_details{
...@@ -689,7 +684,7 @@ textarea.editable{ ...@@ -689,7 +684,7 @@ textarea.editable{
/* Para que se vea el menú contextual por encima del resto de paneles */ /* Para que se vea el menú contextual por encima del resto de paneles */
#options{ #options{
z-index: 10000; z-index: 10000;
width: 200px; width: 200px;
} }
...@@ -739,7 +734,7 @@ textarea.editable{ ...@@ -739,7 +734,7 @@ textarea.editable{
text-decoration: none; text-decoration: none;
} }
/* Reports */ /* Reports */
#year_select{ #year_select{
max-width: 300px; max-width: 300px;
display: inline-block; display: inline-block;
...@@ -778,7 +773,6 @@ img.profile{ ...@@ -778,7 +773,6 @@ img.profile{
#user_tutors .list-group-item:hover .delete_tutor, #user_tutors .list-group-item:hover .delete_tutor,
#user_sups .list-group-item:hover .delete_sup, #user_sups .list-group-item:hover .delete_sup,
#user_devices .list-group-item:hover .delete_device,
#table_students tr:hover .delete_stu{ #table_students tr:hover .delete_stu{
visibility: visible; visibility: visible;
} }
...@@ -794,10 +788,10 @@ label.student_setup{ ...@@ -794,10 +788,10 @@ label.student_setup{
input[type=range] { input[type=range] {
/*removes default webkit styles*/ /*removes default webkit styles*/
-webkit-appearance: none; -webkit-appearance: none;
/*fix for FF unable to apply focus style bug */ /*fix for FF unable to apply focus style bug */
border: 1px solid white; border: 1px solid white;
/*required for proper track sizing in FF*/ /*required for proper track sizing in FF*/
width: 300px; width: 300px;
} }
...@@ -848,10 +842,10 @@ input[type=range]:-moz-focusring{ ...@@ -848,10 +842,10 @@ input[type=range]:-moz-focusring{
input[type=range]::-ms-track { input[type=range]::-ms-track {
width: 300px; width: 300px;
height: 5px; height: 5px;
/*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */ /*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
background: transparent; background: transparent;
/*leave room for the larger thumb to overflow with a transparent border */ /*leave room for the larger thumb to overflow with a transparent border */
border-color: transparent; border-color: transparent;
border-width: 6px 0; border-width: 6px 0;
...@@ -898,9 +892,9 @@ input[type=range]:focus::-ms-fill-upper { ...@@ -898,9 +892,9 @@ input[type=range]:focus::-ms-fill-upper {
/* Se aplica de Dispositivos medianos en adelante /* Se aplica de Dispositivos medianos en adelante
(tablets, ordenadores, anchura mayor o igual a 768px) */ (tablets, ordenadores, anchura mayor o igual a 768px) */
@media (min-width: 768px) { @media (min-width: 768px) {
/* Estilos generales */ /* Estilos generales */
/* Estilos para el panel de login*/ /* Estilos para el panel de login*/
#login{ #login{
...@@ -912,7 +906,7 @@ input[type=range]:focus::-ms-fill-upper { ...@@ -912,7 +906,7 @@ input[type=range]:focus::-ms-fill-upper {
} }
#signin .help-block{ #signin .help-block{
} }
} }
...@@ -923,11 +917,11 @@ input[type=range]:focus::-ms-fill-upper { ...@@ -923,11 +917,11 @@ input[type=range]:focus::-ms-fill-upper {
width: 36px; width: 36px;
height: 36px; height: 36px;
padding: 8px; padding: 8px;
background: #fff; background: #fff;
border: 2px solid #3071a9; border: 2px solid #3071a9;
color: #3071a9; color: #3071a9;
text-align: center; text-align: center;
font: 32px Arial, sans-serif; font: 32px Arial, sans-serif;
} }
\ No newline at end of file
/**
* This tiny configuration tells sails that the assets folder should be served as public.
* These way we can send our application (and all the uploaded assets) as normal.
* @type {Object}
*/
module.exports = { module.exports = {
paths: { paths: {
public: __dirname+'/../assets' // or wherever public: __dirname + '/../assets'
} }
}; };
\ No newline at end of file
...@@ -8,48 +8,27 @@ ...@@ -8,48 +8,27 @@
* For more information on bootstrapping your app, check out: * For more information on bootstrapping your app, check out:
* http://sailsjs.org/#/documentation/reference/sails.config/sails.config.bootstrap.html * http://sailsjs.org/#/documentation/reference/sails.config/sails.config.bootstrap.html
*/ */
var fs = require('fs') var fs = require('fs');
, path = require('path'); var path = require('path');
module.exports.bootstrap = function (cb) { module.exports.bootstrap = function (callback) {
// Whatever else you want to bootstrap... var i;
var directories = ['upload', 'symbolstx'];
var source = path.join(process.cwd(), '../upload'),
dest = path.join(process.cwd(), 'assets/upload'); function createSymlink(source, destination) {
fs.readlink(destination, function (error, linkString) {
fs.readlink(dest, function(err, linkString){ if (!linkString) {
// If symlin don't exists, it is created fs.symlink(source, destination, 'dir', function () {});
if(!linkString){ }
console.log("Created symlink from " + source + " to " + dest);
fs.symlink(source, dest, 'dir', function(err) {
if (err) console.log(err);
});
}else{
console.log("Symlink to upload exists!");
}
});
var source2 = path.join(process.cwd(), '../symbolstx'),
dest2 = path.join(process.cwd(), 'assets/symbolstx');
fs.readlink(dest2, function(err, linkString2){
// If symlin don't exists, it is created
if(!linkString2){
console.log("Created symlink from " + source2 + " to " + dest2);
fs.symlink(source2, dest2, 'dir', function(err) {
if (err) console.log(err);
}); });
}
}else{ for (i = 0; i < directories.length; i++) {
console.log("Symlink to symbolstx exists!"); createSymlink(
} path.join(process.cwd(), '..', directories[i]),
}); path.join(process.cwd(), 'assets', directories[i])
);
}
cb(); callback();
}; };
\ No newline at end of file
...@@ -10,34 +10,53 @@ ...@@ -10,34 +10,53 @@
* http://sailsjs.org/#/documentation/concepts/Logging * http://sailsjs.org/#/documentation/concepts/Logging
*/ */
var winston = require('winston'); const winston = require('winston');
const path = require('path');
var customLogger = new winston.Logger({ const customLogger = new winston.Logger({
transports: [ level: 'silly'
new(winston.transports.File)({
level: 'debug',
filename: './logs/my_log_file.log'
}),
],
}); });
module.exports.log = { customLogger.add(winston.transports.File, {
name: 'silly-json',
silent: false,
colorize: false,
level: 'silly',
showLevel: true,
timestamp: true,
json: true,
tailable: true,
maxsize: 5 * 1024 * 1024, // 5 MegaByte
filename: path.resolve(__dirname, '..', 'logs', 'silly.json')
});
/*************************************************************************** customLogger.add(winston.transports.File, {
* * name: 'debug-json',
* Valid `level` configs: i.e. the minimum log level to capture with * silent: false,
* sails.log.*() * colorize: false,
* * level: 'debug',
* The order of precedence for log levels from lowest to highest is: * showLevel: true,
* silly, verbose, info, debug, warn, error * timestamp: true,
* * json: true,
* You may also set the level to "silent" to suppress all logs. * tailable: true,
* * maxsize: 5 * 1024 * 1024, // 5 MegaByte
***************************************************************************/ filename: path.resolve(__dirname, '..', 'logs', 'debug.json')
});
// level: 'info' customLogger.add(winston.transports.File, {
// level: 'debug' name: 'error-json',
silent: false,
colorize: false,
level: 'error',
showLevel: true,
timestamp: true,
json: true,
tailable: true,
maxsize: 5 * 1024 * 1024, // 5 MegaByte
filename: path.resolve(__dirname, '..', 'logs', 'error.json')
});
colors: false, // To get clean logs without prefixes or color codings module.exports.log = {
custom: customLogger level: 'silly',
inspect: false,
custom: customLogger,
}; };
/* global sails */
var path = require('path');
var ASSETS_PATH = path.join(__dirname, '..', 'assets');
var UPLOAD_PATH = path.join(__dirname, '..', '..', 'upload');
module.exports.pictogram = { module.exports.pictogram = {
// admin: {
// Administrator credentials email: 'amontejo@ujaen.es',
// password: '$2a$10$omHwM62JNI5O1hbkfFGncOYwq3mZATmh8NnTQhN3f7JV3Q1/S9fGG'
admin: { },
email: 'amontejo@ujaen.es', serialSize: 10, // number of characters in generated serial numbers
//password: '$2a$10$ZLdXN6OqROnE1eEC7D7mleqhwWDEemTswXhKh53qC5e3GEMm3Ch6q', pageLimit: 10, // number of elements per "page"
password: '$2a$10$omHwM62JNI5O1hbkfFGncOYwq3mZATmh8NnTQhN3f7JV3Q1/S9fGG'
}, urls: {
serialSize: 10, // number of characters in generated serial numbers /**
pageLimit: 10 // number of elements per "page" * Gets the public url of a supervisor avatar
}; * @param {String} filename filename of the avatar (stored in database)
\ No newline at end of file * @return {String} Public url of user's avatar
*/
getSupervisorAvatarUrl: function (filename) {
return `/upload/supervisorAvatar/${filename}`;
},
/**
* Gets the public url of a student avatar
* @param {String} filename filename of the avatar (stored in database)
* @return {String} Public url of student's avatar
*/
getStudentAvatarUrl: function (filename) {
return `/upload/studentAvatar/${filename}`;
},
/**
* Gets the public url of a supervisor custom picto
* @param {String} filename filename of the custom picto (stored in database)
* @return {String} Public url of supervisor's custom picto
*/
getSupervisorCustomPictoUrl: function (filename) {
return `/upload/supervisorCustomPicto/${filename}`;
}
},
paths: {
public: ASSETS_PATH,
upload: UPLOAD_PATH,
defaultAvatarFileName: 'defaultAvatar.jpg',
supervisorAvatarDirectory: path.join(UPLOAD_PATH, 'supervisorAvatar'),
studentAvatarDirectory: path.join(UPLOAD_PATH, 'studentAvatar'),
supervisorCustomPictoDirectory: path.join(UPLOAD_PATH, 'supervisorCustomPicto'),
/**
* Get a random name used for uploaded file names
* @param {string} randomString String used for generating the name
* @param {number} randomNumber Number used for generating the name
* @return {string} Random name
*/
_getRandomFileName: function (randomString, randomNumber) {
var bcrypt = require('bcrypt-nodejs');
var randomDate = (new Date())
.getTime();
var randomFloat = Math.random();
return bcrypt.hashSync(
[randomString, randomDate, randomNumber, randomFloat].join(''),
bcrypt.genSaltSync()
)
.replace(/\W/g, '') + '.jpg';
},
/**
* Gets the supervisor avatar filename
* @param {supervisorId} supervisorId
* @return {string} fileName
*/
getSupervisorAvatarFileName: function (supervisorId) {
return sails.config.pictogram.paths._getRandomFileName(
'SUPERVISOR_AVATAR',
supervisorId
);
},
/**
* Gets the student avatar filename
* @param {studentId} studentId
* @return {string} fileName
*/
getStudentAvatarFileName: function (studentId) {
return sails.config.pictogram.paths._getRandomFileName(
'SUPERVISOR_AVATAR',
studentId
);
},
/**
* Gets the supervisor custom picto filename
* @param {supervisorId} supervisorId supervisorId
* @return {string} fileName
*/
getSupervisorCustomPictoFileName: function (supervisorId) {
return sails.config.pictogram.paths._getRandomFileName(
'SUPERVISOR_CUSTOM_PICTO',
supervisorId
);
}
}
};
...@@ -15,175 +15,111 @@ ...@@ -15,175 +15,111 @@
* For more information on configuring policies, check out: * For more information on configuring policies, check out:
* http://sailsjs.org/#/documentation/reference/sails.config/sails.config.policies.html * http://sailsjs.org/#/documentation/reference/sails.config/sails.config.policies.html
*/ */
module.exports.policies = { module.exports.policies = {
// Sorted as they appear in routes.js
// Grouped by controller, sorted by HTTP method
/***************************************************************************
* *
* Default policy for all controllers and actions (`true` allows public *
* access) *
* *
***************************************************************************/
'*': false, '*': false,
PagesController: { // all static pages all publicy available
'*': true ActionController: {
}, create: ['tokenAuth'],
ServerController: { createlist: ['tokenAuth']
ping: true,
ping_session: ['tokenAuth'],
},
SupervisorController: {
find: ['tokenAuth'],
findOne: ['tokenAuth'],
login: true,
create: true,
update: ['tokenAuth'],
activate: true,
list: ['tokenAuth', 'isAdmin'],
destroy: ['tokenAuth', 'isAdmin'],
students: ['tokenAuth'],
pictos: ['tokenAuth'],
upload: ['tokenAuth'],
subscribe: ['tokenAuth'],
unsubscribe: ['tokenAuth']
},
DeviceController: {
register: true,
create: ['tokenAuth', 'isAdmin'],
users: ['tokenAuth'],
list: ['tokenAuth', 'isAdmin'],
// From here, there are blueprint actions
// IMPORTANT: do not place implemented methods beyond this point
findOne: ['tokenAuth'],
find: ['tokenAuth'],
update: ['tokenAuth', 'isAdmin'],
}, },
AdminController: { AdminController: {
login: true login: true
}, },
InstructionController: {
ws: ['tokenAuth'],
update: ['tokenAuth'],
create: ['tokenAuth'],
destroy: ['tokenAuth']
},
MethodController: {
update: ['tokenAuth'],
create: ['tokenAuth'],
newMethod: ['tokenAuth'],
save: ['tokenAuth'],
destroy: ['tokenAuth'],
destroyTemplate: ['tokenAuth'],
meta_methods: ['tokenAuth']
},
OfficeController: { OfficeController: {
get: ['tokenAuth'],
findOne: ['tokenAuth'],
getAll: ['tokenAuth', 'isAdmin'], getAll: ['tokenAuth', 'isAdmin'],
create: ['tokenAuth', 'isAdmin'], get: ['tokenAuth'],
update: ['tokenAuth', 'isAdmin'], supervisors: ['tokenAuth', 'isAdmin']
destroy: ['tokenAuth', 'isAdmin'],
supervisors: ['tokenAuth', 'isAdmin'],
populate: ['tokenAuth']
}, },
PictoController: {
upload: ['tokenAuth'],
add_tag: ['tokenAuth'],
change_exp: ['tokenAuth'],
destroy: ['tokenAuth'],
del_tag: ['tokenAuth'],
categories: ['tokenAuth'],
fromcategory: ['tokenAuth']
},
ServerController: {
ping: true,
ping_session: ['tokenAuth']
},
StudentController: { StudentController: {
login: true,
find: ['tokenAuth'],
findOne: ['tokenAuth'],
getInfo: ['tokenAuth'], getInfo: ['tokenAuth'],
create: ['tokenAuth',], // isSupAdmin too
update: ['tokenAuth'],
delete: ['tokenAuth'],
//destroy: ['tokenAuth'], // isSupAdmin too
devices: ['tokenAuth' ], // isSupAdmin is supervisor of the
supervisors: ['tokenAuth'], supervisors: ['tokenAuth'],
therapists: ['tokenAuth'], therapists: ['tokenAuth'],
tutors: ['tokenAuth'], // isSupervisorOfStudent falla en Student.supervisors tutors: ['tokenAuth'],
link_supervisor: ['tokenAuth'], link_supervisor: ['tokenAuth'],
unlink_supervisor: ['tokenAuth'],
link_device: ['tokenAuth'],
unlink_device: ['tokenAuth'],
subscribe: ['tokenAuth'], // websockets
unsubscribe: true, // websockets
vocabulary: true, // websockets
action: true, // websockets
config: true, // websockets
pictos: ['tokenAuth'], pictos: ['tokenAuth'],
add_picto: ['tokenAuth', 'isSupervisorOfStudent'],
delete_picto: ['tokenAuth', 'isSupervisorOfStudent'],
update_picto: ['tokenAuth', 'isSupervisorOfStudent'],
upload: ['tokenAuth'],
methods: ['tokenAuth'], methods: ['tokenAuth'],
lasttries: ['tokenAuth'], lasttries: ['tokenAuth'],
tries: ['tokenAuth'], tries: ['tokenAuth'],
last_instruction: ['tokenAuth'],
ws: ['tokenAuth'], ws: ['tokenAuth'],
actions_batch: ['tokenAuth'], update: ['tokenAuth'],
sqlquery: ['tokenAuth'] update_picto: ['tokenAuth', 'isSupervisorOfStudent'],
}, login: true,
StuSupController:{
find: ['tokenAuth'],
findOne: ['tokenAuth'],
create: ['tokenAuth'],
destroy: ['tokenAuth']
},
PictoController:{
create: ['tokenAuth'], create: ['tokenAuth'],
destroy: ['tokenAuth'], upload: ['tokenAuth'],
categories: ['tokenAuth'], add_picto: ['tokenAuth', 'isSupervisorOfStudent'],
fromcategory: ['tokenAuth'], subscribe: ['tokenAuth'],
find: ['tokenAuth'], unsubscribe: true,
findOne: ['tokenAuth'], vocabulary: true,
add_tag: ['tokenAuth'], action: true,
del_tag: ['tokenAuth'], config: true,
change_exp: ['tokenAuth'], actions_batch: ['tokenAuth'],
upload: ['tokenAuth'] delete: ['tokenAuth'],
unlink_supervisor: ['tokenAuth'],
delete_picto: ['tokenAuth', 'isSupervisorOfStudent']
}, },
MethodController:{
create: ['tokenAuth'], SupervisorController: {
newMethod: ['tokenAuth'], list: ['tokenAuth', 'isAdmin'],
students: ['tokenAuth'],
pictos: ['tokenAuth'],
getByEmail: ['tokenAuth'],
update: ['tokenAuth'], update: ['tokenAuth'],
destroy: ['tokenAuth'], create: true,
find: ['tokenAuth'], login: true,
findOne: ['tokenAuth'], activate: true,
meta_methods: ['tokenAuth'], upload: ['tokenAuth'],
methods: ['tokenAuth'], subscribe: ['tokenAuth'],
save: ['tokenAuth'], unsubscribe: ['tokenAuth']
destroyTemplate: ['tokenAuth'], // Add policie isOwner (supervisor.id == metamethod.id_sup)
}, },
InstructionController:{
create: ['tokenAuth'], TryController: {
update: ['tokenAuth'], update: ['tokenAuth'],
destroy: ['tokenAuth'], create: ['tokenAuth']
find: ['tokenAuth'],
findOne: ['tokenAuth'],
ws: ['tokenAuth'],
}, },
WorkingSessionController:{
close: ['tokenAuth'], WorkingSessionController: {
create: ['tokenAuth'],
update: ['tokenAuth'],
destroy: ['tokenAuth'],
find: ['tokenAuth'],
findOne: ['tokenAuth'],
tries: ['tokenAuth'],
per_year: ['tokenAuth'], per_year: ['tokenAuth'],
per_month: ['tokenAuth'], per_month: ['tokenAuth'],
tries: ['tokenAuth'], tries: ['tokenAuth'],
}, close: ['tokenAuth']
TryController:{ }
create: ['tokenAuth'],
update: ['tokenAuth'],
},
ActionController:{
create: ['tokenAuth'],
createlist: ['tokenAuth'],
},
}; };
/***************************************************************************
* *
* Here's an example of mapping some policies to run before a controller *
* and its actions *
* *
***************************************************************************/
// RabbitController: {
// Apply the `false` policy as the default for all of RabbitController's actions
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
// '*': false,
// For the action `nurture`, apply the 'isRabbitMother' policy
// (this overrides `false` above)
// nurture : 'isRabbitMother',
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
// before letting any users feed our rabbits
// feed : ['isNiceToAnimals', 'hasRabbitFood']
// }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment