Commit 9675647e by Pablo Molina

Merge branch 'issue/386' into develop

Conflicts:
	sails/src/assets/app/modules/supervisor/controllers/students.js
parents d0f6aea1 e39c1c30
/* global Student, PictoCoreCat, VStuLastInstruction, StuPicto, StuSup, sailsTokenAuth, sails */
/**
/* StudentController
*
......@@ -7,932 +9,967 @@
module.exports = {
//
// login action
// expected params in post body: username, password
//
login: function (req, res) {
var bcrypt = require('bcrypt-nodejs');
var username = req.body.username;
var password = req.body.password;
// no credentials
if (!username || !password)
return res.json(401, {error: 'No credentials sent'});
// search user by username
Student.findOneByUsername(username).exec(function (err, stu) {
if (err)
return res.json(500, { error: 'DB error' });
if (!stu)
return res.json(401, {error: 'User not found'});
// if found, check password in encrypted form
bcrypt.compare(password, stu.password, function (err, match) {
if (err)
return res.json(500, { error: 'Server error' });
if (match) { // password match
// all supervisor information is passed as payload to the token
stu.isStudent = true;
return res.json({
user: stu,
token: sailsTokenAuth.issueToken(stu, sails.config.jwt.expiresInMinutes),
server_time: (new Date()).getTime()
});
} else {
return res.json(401, { error: 'Invalid password' });
}
});
});
},
//
// Get a student with the given id, population also the office and the last method/instruction
//
getInfo: function(req, res) {
if (!req.params.id_stu)
return res.json(500, {err: 'no id_stu'});
Student.findOne(req.params.id_stu).populate('office').populate('stuSup').exec(function(err, student){
if (err) {
sails.log.debug(err);
console.log(JSON.stringify(err));
return res.json(500, err);
}
if (!student)
return res(500, {err: JSON.stringify(err)});
// get student last method/instruction
VStuLastInstruction.findOne({ student : student.id }).exec(function(err, row) {
if (err) {
sails.log.debug(err);
console.log(JSON.stringify(err));
return res.json(500, err);
}
if (!row || row.length == 0) {
student.current_method = 'no_method';
student.current_instruction = 'no_instruction';
} else {
student.current_method = row.met_name;
student.current_instruction = row.ins_name;
}
return res.json(student);
});
});
},
//
// create action
// adds a new student into the database
//
create: function(req, res) {
var params = req.params.all();
Student.create(params).exec(function (err, created) {
if (err) {
sails.log.debug(err);
console.log(JSON.stringify(err));
return res.json(500, err);
}
if (created) {
sails.log.debug("Student "+ created.id +" created: " + JSON.stringify(created));
// Assign the initial collection of pictos to the student
PictoCoreCat.find().exec(function(err, pictoCoreCat) {
if (err || !pictoCoreCat || pictoCoreCat.length == 0){
sails.log.debug("PictoCoreCat: " + err);
return;
}
sails.log.debug("PictoCoreCat Length: " + pictoCoreCat.length);
sails.log.debug(pictoCoreCat);
// Every picto from 'picto_core_cat' is going to be created
// in 'stu_picto'
for (var i = 0; i < pictoCoreCat.length; i++) {
sails.log.debug("Loop: " + i);
sails.log.debug("Picto Category: " + pictoCoreCat[i].category);
sails.log.debug("User id: " + created.id);
StuPicto.create({
student: created.id,
picto: pictoCoreCat[i].picto,
attributes: {
id_cat: pictoCoreCat[i].category,
coord_x: pictoCoreCat[i].coord_x,
coord_y: pictoCoreCat[i].coord_y,
status: 'invisible', // Default, the pictos don't appear to the user
color: pictoCoreCat[i].color
}
}).exec(function(err, added){
if(err) sails.log.debug("StuPicto.create: " + err);
if(added) sails.log.debug("Picto " + added.picto + " added to student " + created.id + " with attributes: " + JSON.stringify(added.attributes));
});
}
});
return res.json({student: created});
}
});
},
//
// Deletes logically a student by removing id_off and linked supervisors
//
delete: function(req, res) {
if (!req.params.id_stu)
return res.json(500, {error: "No student defined"});
Student.logical_delete(req.params.id_stu, function(err) {
if (err)
return res.json(500, {error: err});
return res.json({result: 'Deleted'});
});
},
//
// Updates student information
//
update: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.findOne(req.params.id_stu).exec(function(err, stu){
if (err || !stu)
return res.json(500, {error: "No student found"});
// copy attributes
for (k in req.body) stu[k] = req.body[k];
stu.save(function(err, saved) {
if (err)
return res.json(500, {error: "Error when saving student"});
return res.json({result: 'Deleted'});
});
});
},
//
// Returns all supervisors (therapists + tutors) for the given student
//
supervisors: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.supervisors(req.params.id_stu, function(err, sups) {
if (err) throw err;
return res.json(sups);
});
},
//
// Returns all therapists for the given student
//
therapists: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.therapists(req.params.id_stu, function(err, sups) {
if (err) throw err;
return res.json(sups);
});
},
//
// Returns all tutors for the given student
//
tutors: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.tutors(req.params.id_stu, function(err, sups) {
if (err) throw err;
return res.json(sups);
});
},
// Add action
// Create a relation between supervisor and student (stu_sup)
//
link_supervisor: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuSup.create({student: params.id_stu, supervisor: params.id_sup}).exec(function (err, created) {
if (err) {
console.log(err);
return res.json(500, {error: 'Relation student/supervisor NO created'});
}
if (created) {
console.log("Relation student/supervisor created" );
return res.json(created);
}
});
},
// destroy action
// remove the relation between supervisor and student (stu_sup)
//
unlink_supervisor: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuSup.destroy({student: params.id_stu, supervisor: params.id_sup}).exec(function (err, destroyed) {
if (err) {
console.log(err);
return res.json(500, {error: 'Relation student/supervisor not removed'});
}
if (destroyed) {
console.log("Relation student/supervisor removed" );
return res.json({stusup: destroyed});
}
});
},
//
// Returns all the devices associated to the student
//
devices: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.devices(req.params.id_stu, function(err, devs) {
if (err) throw err;
return res.json(devs);
});
},
//
// Link a device to a student
//
link_device: function(req, res) {
var params = req.params.all();
console.log(params);
if (!params.id_stu)
return res.json(500, {error: "No student defined"});
if (!params.id_dev_firm)
return res.json(500, {error: "No device defined"});
Student.link_device(params.id_stu, params.id_dev_firm, function(err, created) {
if (err || !created)
return res.json(500, {error: 'The device could not be linked with the student'});
return res.json(created);
});
},
// destroy action
// remove the relation between student and device (stu_dev)
//
unlink_device: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuDev.destroy({id_stu: params.id_stu, id_dev: params.id_dev}).exec(function (err, destroyed) {
if (err) {
console.log(err);
return res.json(500, {error: 'Relation student/device not removed'});
}
if (destroyed) {
console.log("Relation student/device removed");
return res.json(destroyed[0]);
}
});
},
// read action
// get methods of a student
//
methods: function(req, res) {
var params = req.allParams();
Method.find({ student: params.id_stu }).populate('instructions').exec(function (err, methods) {
if (err)
return res.json(500, {error: err});
if(!methods || methods.length == 0)
return res.json([]); // Return an empty array
if (methods) {
var l_met = [];
async.eachSeries(methods, function(m, callback1) {
sails.log.debug("Loop methods: " + m.name);
var l_ins = [];
var last_ins;
var last_time = 0;
async.eachSeries(m.instructions, function(ins, callback2) {
sails.log.debug("Loop instructions: " + ins.name);
Instruction.findOne({ id: ins.id }).populate('workingSessions', { sort: 'begin DESC' }).exec(function (err, instruction) {
if (err) {
sails.log.debug("Error in method " + m.name);
}
if(!instruction || !instruction.workingSessions || instruction.workingSessions.length == 0) {
sails.log.debug("No working sessions found for instruction " + instruction.id);
}else{
console.log("Total working sessions: " + instruction.workingSessions.length);
var last = instruction.workingSessions.length-1;
instruction.begin = instruction.workingSessions[last].end;
instruction.end = instruction.workingSessions[0].end;
if(instruction.end > last_time){
last_ins = instruction.id;
last_time = instruction.end;
}
}
// Add instruction to list (with or without tries)
l_ins.push(instruction);
callback2();
});
// Finish function when each callback is done
// Optionaly it can be passed and err parameter
}, function(err){
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('An error ocurred with a try');
return res.json(500, { error: "Error looping in tries: " + err });
}
m.instructions = l_ins;
m.last_ins = last_ins;
l_met.push(m);
callback1();
});
// Finish function when each callback is done
// Optionaly it can be passed and err parameter
}, function(err){
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('An error ocurred with an instruction');
return res.json(500, { error: "Error looping in method instructions: " + err });
} else {
// All end ok
console.log('All instructions have been processed successfully');
//Assing the built list
return res.json(l_met);
}
});
}
});
},
// read action
// get tries of the last working session
//
lasttries: function(req, res) {
var params = req.allParams();
//Student.findOne({ id: params.id_stu }).populate('workingSessions')
VStuLastInstruction.findOne({ where: {student: params.id_stu }}).exec(function (err, ws) {
if (err){
sails.log.debug("Finding student working sessions: " + err);
return res.json(500, {error: 'No student last working session found'});
}
if(!ws || ws.length == 0){
sails.log.debug("The user has not any working session");
return res.json([]); // Return an empty array of last tries
}
if (ws) {
// Find the tries of this working session populating actions
sails.log.debug("Find WS "+ JSON.stringify(ws));
Try.find({
workingSession: ws.workingSession
}).populate('actions',{supervisor:null}).exec(function (err, tries) {
if (err){
sails.log.debug("Finding student last tries: " + err);
return res.json(500, {error: 'No student last tries found'});
}
if(!tries || tries.length == 0){
sails.log.debug("The user has not any tries for working session id. "+ws.workingSession);
return res.json([]); // Return an empty array of tries
}
if(tries){
console.log("Found student tries for last working session: " + ws.workingSession);
console.log("Last tries: " + JSON.stringify(tries));
// A list for one element: The last working session
var l_ws = [];
l_ws.push({
"id": ws.workingSession,
"student": ws.student,
"begin": ws.ws_begin,
"end": ws.ws_end,
"description":ws.ws_description,
"tries": tries
});
return res.json(l_ws);
}
});
}
});
},
//
// Returns all the tries of the student
//
tries: function(req, res) {
if (!req.params.id_stu)
return res.json(500, {error: "No student defined"});
Student.tries(req.params.id_stu, function(err, l_met) {
if (err) throw err;
return res.json(l_met);
});
},
//
// Returns all pictos for the given student
//
pictos: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
sails.log.debug("Pictos requested for student " + req.params.id_stu);
Student.pictos(req.params.id_stu, function(err, pictos) {
if (err) throw err;
return res.json(pictos);
});
},
//
// Returns all working sessions for the given student
//
ws: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
sails.log.debug("Working Sessions requested for student " + req.params.id_stu);
Student.findOne(req.params.id_stu).populate('workingSessions').exec(function (err, stu) {
if (err)
return res.json(500, {error: err});
if(!stu || !stu.workingSessions || stu.workingSessions.length == 0)
return res.json([]); // Return an empty array
else
return res.json(stu.workingSessions);
});
},
// add action
// add picto to studentPicto
//
add_picto: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuPicto.create({
student: params.id_stu,
picto: params.id_picto,
attributes: params.attributes
}).exec(function (err, added) {
if (err) {
console.log(err);
return res.json(500, {error: 'Not added picto to student'});
}
if (added) {
console.log("Added picto to student: " + JSON.stringify(added));
return res.json({
id: added.id,
picto: { id: added.picto, uri: params.uri },
attributes: added.attributes
});
}
});
},
// destroy action
// remove a picto for a student
//
delete_picto: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuPicto.destroy({id: params.id_stuPicto}).exec(function (err, destroyed) {
if (err) {
console.log(err);
return res.json(500, {error: 'Not removed picto for student'});
}
if (destroyed) {
console.log("Removed picto "+destroyed[0].id_pic+ "for the student ");
return res.json({
id: destroyed[0].id,
attributes: JSON.parse(destroyed[0].attributes),
picto: { id: destroyed[0].id_pic }
});
}
});
},
// update action
// update picto atributes for a studentPicto
//
update_picto: function(req, res) {
var params = req.allParams();
console.log("Updating attributes for picto student "+ JSON.stringify(params));
console.log(JSON.stringify(params));
query=params.id_stuPicto ? {id: params.id_stuPicto}
: {id_stu:params.id_stu, id_pic:params.id_pic}
StuPicto.update(query, {attributes: params.attributes}).exec(function (err, updated) {
if (err) {
console.log(err);
return res.json(500, {error: 'Not updated picto for student'});
}
if (updated) {
console.log("Updated attributes for picto student:"+JSON.stringify(updated[0]));
// return res.json(updated[0]);
return res.json({
id: updated[0].id,
attributes: updated[0].attributes,
picto: { id:updated[0].picto }
});
}
});
},
//
// Upload pic file
//
upload: function (req, res) {
if(req.method === 'GET')
return res.json({'status':'GET not allowed'});
// Call to /upload via GET is error
var uploadFile = req.file('file');
console.log("Nombre de archivo: " + req.body.filename);
console.log("Nombre de carpeta: " + req.body.folder);
console.log("Id del usuario: " + req.body.id);
var fs = require('fs'), path = require('path');
var dirUpload = path.join(process.cwd(), '../upload/' + req.body.folder);
req.body.filename = sailsHash.hashCode(req.body.filename + Date().toString()) + '.' + req.body.extension;
uploadFile.upload({
dirname: dirUpload,
saveAs: req.body.filename
},
function onUploadComplete (err, files) {
// Files will be uploaded to .tmp/uploads
if (err) return res.serverError(err);
// IF ERROR Return and send 500 error with error
// Delete old pic (if it isn't the default pic)
Student.findOne({id: req.body.id}).exec(function(err, found){
if(found && found.pic != "/app/img/default.jpg"){
console.log("Found: " + found.pic);
// Path: ../upload/students/xxxx.jpg
fs.unlink('..' + found.pic, function (err) {
if (err) throw err;
console.log('Old pic destroyed');
});
}
});
// Store in DB new URL pic
Student.update({id: req.body.id}, {pic: '/upload/' + req.body.folder + '/' + req.body.filename}).exec(function(err, updated){
if(updated)
console.log("Student picture updated");
});
files[0].name = req.body.filename;
delete files[0].fd;
console.log(files);
var file = dirUpload + '/' + req.body.filename;
//
// login action
// expected params in post body: username, password
//
login: function (req, res) {
var bcrypt = require('bcrypt-nodejs');
var username = req.body.username;
var password = req.body.password;
// no credentials
if (!username || !password) {
return res.json(401, { error: 'No credentials sent' });
}
// search user by username
Student.findOneByUsername(username).exec(function (err, stu) {
if (err) {
return res.json(500, { error: 'DB error' });
}
if (!stu) {
return res.json(401, { error: 'User not found' });
}
// if found, check password in encrypted form
bcrypt.compare(password, stu.password, function (err, match) {
if (err) {
return res.json(500, { error: 'Server error' });
}
if (match) { // password match
// all supervisor information is passed as payload to the token
stu.isStudent = true;
return res.json({
user: stu,
token: sailsTokenAuth.issueToken(stu, sails.config.jwt.expiresInMinutes),
server_time: (new Date()).getTime()
});
} else {
return res.json(401, { error: 'Invalid password' });
}
});
});
},
//
// Get a student with the given id, population also the office and the last method/instruction
//
getInfo: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, { err: 'no id_stu' });
}
Student.findOne(req.params.id_stu).populate('office').populate('stuSup')
.exec(function(err, student){
if (err) {
sails.log.debug(err);
console.log(JSON.stringify(err));
return res.json(500, err);
}
if (!student) {
return res(500, {err: JSON.stringify(err)});
}
// get student last method/instruction
VStuLastInstruction.findOne({ student : student.id })
.exec(function(err, row) {
if (err) {
sails.log.debug(err);
console.log(JSON.stringify(err));
return res.json(500, err);
}
if (!row || row.length === 0) {
student.current_method = 'no_method';
student.current_instruction = 'no_instruction';
} else {
student.current_method = row.met_name;
student.current_instruction = row.ins_name;
}
return res.json(student);
});
});
},
//
// create action
// adds a new student into the database
//
create: function(req, res) {
var params = req.params.all();
Student.create(params).exec(function (err, created) {
if (err) {
sails.log.debug(err);
console.log(JSON.stringify(err));
return res.json(500, err);
}
if (created) {
sails.log.debug("Student "+ created.id +" created: " + JSON.stringify(created));
// Assign the initial collection of pictos to the student
PictoCoreCat.find().exec(function(err, pictoCoreCat) {
if (err || !pictoCoreCat || pictoCoreCat.length == 0){
sails.log.debug("PictoCoreCat: " + err);
return;
}
sails.log.debug("PictoCoreCat Length: " + pictoCoreCat.length);
sails.log.debug(pictoCoreCat);
// Every picto from 'picto_core_cat' is going to be created
// in 'stu_picto'
for (var i = 0; i < pictoCoreCat.length; i++) {
sails.log.debug("Loop: " + i);
sails.log.debug("Picto Category: " + pictoCoreCat[i].category);
sails.log.debug("User id: " + created.id);
StuPicto.create({
student: created.id,
picto: pictoCoreCat[i].picto,
attributes: {
id_cat: pictoCoreCat[i].category,
coord_x: pictoCoreCat[i].coord_x,
coord_y: pictoCoreCat[i].coord_y,
status: 'invisible', // Default, the pictos don't appear to the user
color: pictoCoreCat[i].color
}
}).exec(function(err, added){
if(err) sails.log.debug('StuPicto.create: ' + err);
if(added) {
sails.log.debug(
'Picto ' + added.picto +
' added to student ' + created.id +
' with attributes: ' + JSON.stringify(added.attributes));
}
});
}
});
return res.json({ student: created });
}
});
},
//
// Deletes logically a student by removing id_off and linked supervisors
//
delete: function(req, res) {
if (!req.params.id_stu)
return res.json(500, {error: "No student defined"});
Student.logical_delete(req.params.id_stu, function(err) {
if (err)
return res.json(500, {error: err});
return res.json({result: 'Deleted'});
});
},
//
// Updates student information
//
update: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.findOne(req.params.id_stu).exec(function(err, stu){
if (err || !stu)
return res.json(500, {error: "No student found"});
// copy attributes
for (k in req.body) stu[k] = req.body[k];
stu.save(function(err, saved) {
if (err)
return res.json(500, {error: "Error when saving student"});
return res.json({result: 'Deleted'});
});
});
},
//
// Returns all supervisors (therapists + tutors) for the given student
//
supervisors: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.supervisors(req.params.id_stu, function(err, sups) {
if (err) throw err;
return res.json(sups);
});
},
//
// Returns all therapists for the given student
//
therapists: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.therapists(req.params.id_stu, function(err, sups) {
if (err) throw err;
return res.json(sups);
});
},
//
// Returns all tutors for the given student
//
tutors: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.tutors(req.params.id_stu, function(err, sups) {
if (err) throw err;
return res.json(sups);
});
},
/**
* Creates a relation between the student and a given supervisor.
* It broadcasts the even linkSupervisorToStudent to both the student room
* and the supervisor room.
*/
link_supervisor: function(req, res) {
var params = req.allParams();
StuSup.create({
student: params.id_stu,
supervisor: params.id_sup
}).exec(function (err, created) {
var response;
var socketToOmit;
var linkSupervisorToStudentEvent;
if (err) {
response = res.serverError(
'Relation student/supervisor not created: ' + err
);
}
if (created) {
socketToOmit = (req.isSocket) ? req.socket : undefined;
linkSupervisorToStudentEvent = sails.hooks.events.linkSupervisorToStudent(
params.id_sup,
params.id_stu
);
sails.hooks.events.broadcastEvent(
sails.hooks.rooms.supervisor(params.id_sup),
linkSupervisorToStudentEvent,
socketToOmit
);
sails.hooks.events.broadcastEvent(
sails.hooks.rooms.student(params.id_stu),
linkSupervisorToStudentEvent,
socketToOmit
);
response = res.ok(created);
} else {
response = res.serverError(
'Relation student/supervisor not created, ' +
'but no error was received'
);
}
return response;
});
},
// destroy action
// remove the relation between supervisor and student (stu_sup)
//
unlink_supervisor: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuSup.destroy({student: params.id_stu, supervisor: params.id_sup}).exec(function (err, destroyed) {
if (err) {
console.log(err);
return res.json(500, {error: 'Relation student/supervisor not removed'});
}
if (destroyed) {
console.log("Relation student/supervisor removed" );
return res.json({stusup: destroyed});
}
});
},
//
// Returns all the devices associated to the student
//
devices: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
Student.devices(req.params.id_stu, function(err, devs) {
if (err) throw err;
return res.json(devs);
});
},
//
// Link a device to a student
//
link_device: function(req, res) {
var params = req.params.all();
console.log(params);
if (!params.id_stu)
return res.json(500, {error: "No student defined"});
if (!params.id_dev_firm)
return res.json(500, {error: "No device defined"});
Student.link_device(params.id_stu, params.id_dev_firm, function(err, created) {
if (err || !created)
return res.json(500, {error: 'The device could not be linked with the student'});
return res.json(created);
});
},
// destroy action
// remove the relation between student and device (stu_dev)
//
unlink_device: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuDev.destroy({id_stu: params.id_stu, id_dev: params.id_dev}).exec(function (err, destroyed) {
if (err) {
console.log(err);
return res.json(500, {error: 'Relation student/device not removed'});
}
if (destroyed) {
console.log("Relation student/device removed");
return res.json(destroyed[0]);
}
});
},
// read action
// get methods of a student
//
methods: function(req, res) {
var params = req.allParams();
Method.find({ student: params.id_stu }).populate('instructions').exec(function (err, methods) {
if (err)
return res.json(500, {error: err});
if(!methods || methods.length == 0)
return res.json([]); // Return an empty array
if (methods) {
var l_met = [];
async.eachSeries(methods, function(m, callback1) {
sails.log.debug("Loop methods: " + m.name);
var l_ins = [];
var last_ins;
var last_time = 0;
async.eachSeries(m.instructions, function(ins, callback2) {
sails.log.debug("Loop instructions: " + ins.name);
Instruction.findOne({ id: ins.id }).populate('workingSessions', { sort: 'begin DESC' }).exec(function (err, instruction) {
if (err) {
sails.log.debug("Error in method " + m.name);
}
if(!instruction || !instruction.workingSessions || instruction.workingSessions.length == 0) {
sails.log.debug("No working sessions found for instruction " + instruction.id);
}else{
console.log("Total working sessions: " + instruction.workingSessions.length);
var last = instruction.workingSessions.length-1;
instruction.begin = instruction.workingSessions[last].end;
instruction.end = instruction.workingSessions[0].end;
if(instruction.end > last_time){
last_ins = instruction.id;
last_time = instruction.end;
}
}
// Add instruction to list (with or without tries)
l_ins.push(instruction);
callback2();
});
// Finish function when each callback is done
// Optionaly it can be passed and err parameter
}, function(err){
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('An error ocurred with a try');
return res.json(500, { error: "Error looping in tries: " + err });
}
m.instructions = l_ins;
m.last_ins = last_ins;
l_met.push(m);
callback1();
});
// Finish function when each callback is done
// Optionaly it can be passed and err parameter
}, function(err){
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('An error ocurred with an instruction');
return res.json(500, { error: "Error looping in method instructions: " + err });
} else {
// All end ok
console.log('All instructions have been processed successfully');
//Assing the built list
return res.json(l_met);
}
});
}
});
},
// read action
// get tries of the last working session
//
lasttries: function(req, res) {
var params = req.allParams();
//Student.findOne({ id: params.id_stu }).populate('workingSessions')
VStuLastInstruction.findOne({ where: {student: params.id_stu }}).exec(function (err, ws) {
if (err){
sails.log.debug("Finding student working sessions: " + err);
return res.json(500, {error: 'No student last working session found'});
}
if(!ws || ws.length == 0){
sails.log.debug("The user has not any working session");
return res.json([]); // Return an empty array of last tries
}
if (ws) {
// Find the tries of this working session populating actions
sails.log.debug("Find WS "+ JSON.stringify(ws));
Try.find({
workingSession: ws.workingSession
}).populate('actions',{supervisor:null}).exec(function (err, tries) {
if (err){
sails.log.debug("Finding student last tries: " + err);
return res.json(500, {error: 'No student last tries found'});
}
if(!tries || tries.length == 0){
sails.log.debug("The user has not any tries for working session id. "+ws.workingSession);
return res.json([]); // Return an empty array of tries
}
if(tries){
console.log("Found student tries for last working session: " + ws.workingSession);
console.log("Last tries: " + JSON.stringify(tries));
// A list for one element: The last working session
var l_ws = [];
l_ws.push({
"id": ws.workingSession,
"student": ws.student,
"begin": ws.ws_begin,
"end": ws.ws_end,
"description":ws.ws_description,
"tries": tries
});
return res.json(l_ws);
}
});
}
});
},
//
// Returns all the tries of the student
//
tries: function(req, res) {
if (!req.params.id_stu)
return res.json(500, {error: "No student defined"});
Student.tries(req.params.id_stu, function(err, l_met) {
if (err) throw err;
return res.json(l_met);
});
},
//
// Returns all pictos for the given student
//
pictos: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
sails.log.debug("Pictos requested for student " + req.params.id_stu);
Student.pictos(req.params.id_stu, function(err, pictos) {
if (err) throw err;
return res.json(pictos);
});
},
//
// Returns all working sessions for the given student
//
ws: function(req, res) {
if (!req.params.id_stu) {
return res.json(500, {error: "No student defined"});
}
sails.log.debug("Working Sessions requested for student " + req.params.id_stu);
Student.findOne(req.params.id_stu).populate('workingSessions').exec(function (err, stu) {
if (err)
return res.json(500, {error: err});
if(!stu || !stu.workingSessions || stu.workingSessions.length == 0)
return res.json([]); // Return an empty array
else
return res.json(stu.workingSessions);
});
},
// add action
// add picto to studentPicto
//
add_picto: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuPicto.create({
student: params.id_stu,
picto: params.id_picto,
attributes: params.attributes
}).exec(function (err, added) {
if (err) {
console.log(err);
return res.json(500, {error: 'Not added picto to student'});
}
if (added) {
console.log("Added picto to student: " + JSON.stringify(added));
return res.json({
id: added.id,
picto: { id: added.picto, uri: params.uri },
attributes: added.attributes
});
}
});
},
// destroy action
// remove a picto for a student
//
delete_picto: function(req, res) {
var params = req.allParams();
console.log(JSON.stringify(params));
StuPicto.destroy({id: params.id_stuPicto}).exec(function (err, destroyed) {
if (err) {
console.log(err);
return res.json(500, {error: 'Not removed picto for student'});
}
if (destroyed) {
console.log("Removed picto "+destroyed[0].id_pic+ "for the student ");
return res.json({
id: destroyed[0].id,
attributes: JSON.parse(destroyed[0].attributes),
picto: { id: destroyed[0].id_pic }
});
}
});
},
// update action
// update picto atributes for a studentPicto
//
update_picto: function(req, res) {
var params = req.allParams();
console.log("Updating attributes for picto student "+ JSON.stringify(params));
console.log(JSON.stringify(params));
query=params.id_stuPicto ? {id: params.id_stuPicto}
: {id_stu:params.id_stu, id_pic:params.id_pic}
StuPicto.update(query, {attributes: params.attributes}).exec(function (err, updated) {
if (err) {
console.log(err);
return res.json(500, {error: 'Not updated picto for student'});
}
if (updated) {
console.log("Updated attributes for picto student:"+JSON.stringify(updated[0]));
// return res.json(updated[0]);
return res.json({
id: updated[0].id,
attributes: updated[0].attributes,
picto: { id:updated[0].picto }
});
}
});
},
//
// Upload pic file
//
upload: function (req, res) {
if(req.method === 'GET')
return res.json({'status':'GET not allowed'});
// Call to /upload via GET is error
var uploadFile = req.file('file');
console.log("Nombre de archivo: " + req.body.filename);
console.log("Nombre de carpeta: " + req.body.folder);
console.log("Id del usuario: " + req.body.id);
var fs = require('fs'), path = require('path');
var dirUpload = path.join(process.cwd(), '../upload/' + req.body.folder);
req.body.filename = sailsHash.hashCode(req.body.filename + Date().toString()) + '.' + req.body.extension;
uploadFile.upload({
dirname: dirUpload,
saveAs: req.body.filename
},
function onUploadComplete (err, files) {
// Files will be uploaded to .tmp/uploads
if (err) return res.serverError(err);
// IF ERROR Return and send 500 error with error
// Delete old pic (if it isn't the default pic)
Student.findOne({id: req.body.id}).exec(function(err, found){
if(found && found.pic != "/app/img/default.jpg"){
console.log("Found: " + found.pic);
// Path: ../upload/students/xxxx.jpg
fs.unlink('..' + found.pic, function (err) {
if (err) throw err;
console.log('Old pic destroyed');
});
}
});
// Store in DB new URL pic
Student.update({id: req.body.id}, {pic: '/upload/' + req.body.folder + '/' + req.body.filename}).exec(function(err, updated){
if(updated)
console.log("Student picture updated");
});
files[0].name = req.body.filename;
delete files[0].fd;
console.log(files);
var file = dirUpload + '/' + req.body.filename;
//setTimeout(function(){ alert("Hello"); }, 3000);
var interval = setInterval(
function(){
fs.exists(file, function(exists) {
if (exists) {
console.log("Existe el archivo");
clearInterval(interval);
res.json({status:200,file:files[0]});
} else {
console.log("No Existe el archivo");
}
});
} , 5);
}
);
},
// ***************************************************************
// WEBSOCKETS
// ***************************************************************
//
// Subscribe to websockets events
//
subscribe: function(req, res) {
var action = req.param('action');
var attributes = req.param('attributes');
var roomName = 'studentRoom' + attributes.id_stu;
sails.log.debug("Inside /stu/subscribe. Action: " + action);
if (req.isSocket) {
sails.log.debug("Inside /stu/subscribe - isSocket");
sails.sockets.join(req.socket, roomName);
sails.io.sockets.in(roomName).clients(function(err, ids) {
sails.log.debug("number of clients in room: " + ids.length);
if (!err)
sails.io.to(roomName).emit('update_peers', {count: ids.length});
});
res.json({
msg: "Subscribed to student " + roomName
});
}
},
//
// Unsubscribe to websockets events
//
unsubscribe: function(req, res) {
var action = req.param('action');
//var attributes = req.param('attributes');
sails.log.debug("Inside /stu/unsubscribe. Action: " + action);
if (req.isSocket) {
sails.log.debug("Inside /stu/unsubscribe - isSocket");
var rooms = sails.sockets.socketRooms(req.socket);
console.log("Subscribed rooms in socket: " + JSON.stringify(rooms));
// Leave all rooms
for(var i=0; i<rooms.length; i++){
sails.sockets.leave(req.socket, rooms[i]);
sails.log.debug("Unsusbscribe from room " + rooms[i]);
}
res.json({
msg: "Unsubscribed from all rooms"
});
}
},
//
// Logs a vocabulary action and broadcast to anyone subscribed to this student
vocabulary: function(req, res) {
var action = req.param('action');
var attributes = req.param('attributes');
var roomName = 'studentRoom' + attributes.id_stu;
sails.log.debug("Inside vocabulary");
if (req.isSocket) {
sails.log.debug("Inside vocabulary - isSocket");
// Send to all sockets subscribed to this room except the own socket that sends the message
// Parameters: room, action, data to send, socket to avoid sending (the socket that send this)
sails.sockets.broadcast(roomName, 'vocabulary', { "action": action, "attributes": attributes }, req.socket);
res.json({
msg: "Vocabulary "+ action +" action from student " + attributes.id_stu
});
}
},
//
// Logs a TRY action and broadcast to anyone subscribed to this student
action: function(req, res) {
var action = req.param('action');
var attributes = req.param('attributes');
var roomName = 'studentRoom' + attributes.id_stu;
sails.log.debug("Inside action. Student:"+attributes.id_stu);
if (req.isSocket) {
sails.log.debug("websockets - room "+roomName);
// BROADCAST to everyone subscribed to this student
sails.sockets.broadcast(roomName, 'action', { "action": action, "attributes": attributes });
// PROBAR DESDE AQUÍ
// NEW DB STORAGE in table action
var dev = null;
if(attributes.device) dev = attributes.device;
var sup = null;
if(attributes.supervisor) sup = attributes.supervisor;
var desc = null;
if(attributes.picto) desc = attributes.picto; // select, add and delete actions data
if(attributes.pictos) desc = attributes.pictos; // show action data
Action.create({
type: action,
timestamp: attributes.timestamp,
supervisor: sup,
student: attributes.id_stu,
device: dev,
description: desc
}).exec(function (err, created) {
if (err)
res.serverError(err.details);
else if (created)
res.json({action: created});
});
/*
res.json({
msg: "Action "+ action +" action from student " + attributes.id_stu
});
*/
}
},
//
// Logs a config action and broadcast to anyone subscribed to this student
config: function(req, res) {
var action = req.param('action');
var attributes = req.param('attributes');
var roomName = 'studentRoom' + attributes.id_stu;
sails.log.debug("Inside config");
if (req.isSocket) {
sails.log.debug("Inside config - isSocket");
sails.sockets.broadcast(roomName, 'config', { "action": action, "attributes": attributes });
res.json({
msg: "Config "+ action +" action from student " + attributes.id_stu
});
}
},
//
// Stores in the action table a bulk of actions loaded from of the
// recorded action log
//
actions_batch: function(req, res) {
var params = req.allParams();
var count = 0;
sails.log.debug("Actions_batch request");
if (!params.actions)
return res.json(400, {'error': "no actions"});
// We loop through the actions and store them in the database
async.forEach(params.actions, function(action, cb){
sails.log.debug("Actions batch is recording action: "+JSON.stringify(action));
var id_dev = null;
if (action.attributes.id_dev)
id_dev = action.attributes.id_dev;
var id_sup = null;
if(action.attributes.id_sup)
id_sup = action.attributes.sup;
var id_stu = null;
if (action.attributes.id_stu)
id_stu = action.attributes.id_stu;
var desc = null;
if(action.attributes.picto)
desc = action.attributes.picto; // select, add and delete actions data
if(action.attributes.pictos)
desc = action.attributes.pictos; // show action data
Action.create({
type: action.action,
timestamp: action.attributes.timestamp,
supervisor: id_sup,
student: id_stu,
device: id_dev,
description: desc
}).exec(function (err, created) {
if (err) {
console.log(err.details);
sails.log.error(err.details);
return cb(err);
}
else if (created)
count++;
cb();
});
},
var interval = setInterval(
function(){
fs.exists(file, function(exists) {
if (exists) {
console.log("Existe el archivo");
clearInterval(interval);
res.json({status:200,file:files[0]});
} else {
console.log("No Existe el archivo");
}
});
} , 5);
}
);
},
// ***************************************************************
// WEBSOCKETS
// ***************************************************************
//
// Subscribe to websockets events
//
subscribe: function(req, res) {
var action = req.param('action');
var attributes = req.param('attributes');
var roomName = 'studentRoom' + attributes.id_stu;
sails.log.debug("Inside /stu/subscribe. Action: " + action);
if (req.isSocket) {
sails.log.debug("Inside /stu/subscribe - isSocket");
sails.sockets.join(req.socket, roomName);
sails.io.sockets.in(roomName).clients(function(err, ids) {
sails.log.debug("number of clients in room: " + ids.length);
if (!err)
sails.io.to(roomName).emit('update_peers', {count: ids.length});
});
res.json({
msg: "Subscribed to student " + roomName
});
}
},
//
// Unsubscribe to websockets events
//
unsubscribe: function(req, res) {
var action = req.param('action');
//var attributes = req.param('attributes');
sails.log.debug("Inside /stu/unsubscribe. Action: " + action);
if (req.isSocket) {
sails.log.debug("Inside /stu/unsubscribe - isSocket");
var rooms = sails.sockets.socketRooms(req.socket);
console.log("Subscribed rooms in socket: " + JSON.stringify(rooms));
// Leave all rooms
for(var i=0; i<rooms.length; i++){
sails.sockets.leave(req.socket, rooms[i]);
sails.log.debug("Unsusbscribe from room " + rooms[i]);
}
res.json({
msg: "Unsubscribed from all rooms"
});
}
},
//
// Logs a vocabulary action and broadcast to anyone subscribed to this student
vocabulary: function(req, res) {
var action = req.param('action');
var attributes = req.param('attributes');
var roomName = 'studentRoom' + attributes.id_stu;
sails.log.debug("Inside vocabulary");
if (req.isSocket) {
sails.log.debug("Inside vocabulary - isSocket");
// Send to all sockets subscribed to this room except the own socket that sends the message
// Parameters: room, action, data to send, socket to avoid sending (the socket that send this)
sails.sockets.broadcast(roomName, 'vocabulary', { "action": action, "attributes": attributes }, req.socket);
res.json({
msg: "Vocabulary "+ action +" action from student " + attributes.id_stu
});
}
},
//
// Logs a TRY action and broadcast to anyone subscribed to this student
action: function(req, res) {
var action = req.param('action');
var attributes = req.param('attributes');
var roomName = 'studentRoom' + attributes.id_stu;
sails.log.debug("Inside action. Student:"+attributes.id_stu);
if (req.isSocket) {
sails.log.debug("websockets - room "+roomName);
// BROADCAST to everyone subscribed to this student
sails.sockets.broadcast(roomName, 'action', { "action": action, "attributes": attributes });
// PROBAR DESDE AQUÍ
// NEW DB STORAGE in table action
var dev = null;
if(attributes.device) dev = attributes.device;
var sup = null;
if(attributes.supervisor) sup = attributes.supervisor;
var desc = null;
if(attributes.picto) desc = attributes.picto; // select, add and delete actions data
if(attributes.pictos) desc = attributes.pictos; // show action data
Action.create({
type: action,
timestamp: attributes.timestamp,
supervisor: sup,
student: attributes.id_stu,
device: dev,
description: desc
}).exec(function (err, created) {
if (err)
res.serverError(err.details);
else if (created)
res.json({action: created});
});
/*
res.json({
msg: "Action "+ action +" action from student " + attributes.id_stu
});
*/
}
},
//
// Logs a config action and broadcast to anyone subscribed to this student
config: function(req, res) {
var action = req.param('action');
var attributes = req.param('attributes');
var roomName = 'studentRoom' + attributes.id_stu;
sails.log.debug("Inside config");
if (req.isSocket) {
sails.log.debug("Inside config - isSocket");
sails.sockets.broadcast(roomName, 'config', { "action": action, "attributes": attributes });
res.json({
msg: "Config "+ action +" action from student " + attributes.id_stu
});
}
},
//
// Stores in the action table a bulk of actions loaded from of the
// recorded action log
//
actions_batch: function(req, res) {
var params = req.allParams();
var count = 0;
sails.log.debug("Actions_batch request");
if (!params.actions)
return res.json(400, {'error': "no actions"});
// We loop through the actions and store them in the database
async.forEach(params.actions, function(action, cb){
sails.log.debug("Actions batch is recording action: "+JSON.stringify(action));
var id_dev = null;
if (action.attributes.id_dev)
id_dev = action.attributes.id_dev;
var id_sup = null;
if(action.attributes.id_sup)
id_sup = action.attributes.sup;
var id_stu = null;
if (action.attributes.id_stu)
id_stu = action.attributes.id_stu;
var desc = null;
if(action.attributes.picto)
desc = action.attributes.picto; // select, add and delete actions data
if(action.attributes.pictos)
desc = action.attributes.pictos; // show action data
Action.create({
type: action.action,
timestamp: action.attributes.timestamp,
supervisor: id_sup,
student: id_stu,
device: id_dev,
description: desc
}).exec(function (err, created) {
if (err) {
console.log(err.details);
sails.log.error(err.details);
return cb(err);
}
else if (created)
count++;
cb();
});
},
function(err) { // function called when loop is done
if (err) {
console.log(err.details);
sails.log.error(err.details);
return res.json({'error': err.details});
} else
return res.json({'result': 'Ok', 'total': count});
});
},
//
// Returns the last instruction for the student
//
last_instruction: function(req, res) {
if (!req.params.id_stu)
return res.json(400, {err: 'id_stu parameter is missing'});
VStuLastInstruction.find({id_stu: req.params.id_stu}).exec(function(err, found) {
if (err)
return res.json(500, err);
if (!found)
return res.json({});
return res.json(found);
});
},
if (err) {
console.log(err.details);
sails.log.error(err.details);
return res.json({'error': err.details});
} else
return res.json({'result': 'Ok', 'total': count});
});
},
//
// Returns the last instruction for the student
//
last_instruction: function(req, res) {
if (!req.params.id_stu)
return res.json(400, {err: 'id_stu parameter is missing'});
VStuLastInstruction.find({id_stu: req.params.id_stu}).exec(function(err, found) {
if (err)
return res.json(500, err);
if (!found)
return res.json({});
return res.json(found);
});
},
//
// Test raw sql on models
sqlquery: function(req, res) {
/* Example of data recieved via POST
{
"id_stu": 80,
"begin": "2015-07-01",
"end": "2015-07-31"
}
*/
var params = req.params.all();
console.log(JSON.stringify(params));
// Data to return
var l_queries = {
"results" : [],
"totals" : 0
};
if (!params.id_stu)
return res.json(500, {error: "No student defined"});
var sql = "SELECT result, COUNT(result) percentage" +
" FROM method m, student s, instruction i, working_session w, try t" +
" WHERE m.id_stu=s.id and i.id_met=m.id and w.id_ins=i.id and t.id_ws=w.id and s.id="+ params.id_stu +
" and t.begin>='"+ params.begin +"' and t.end<='" + params.end + "'" +
" GROUP BY result" +
" ORDER BY result";
// 1st query
Student.sqlquery(sql, function (err,data) {
if (err) sails.log.debug(err);
else l_queries.results = data;
sql = "SELECT COUNT(result)" +
" FROM method m, student s, instruction i, working_session w, try t" +
" WHERE m.id_stu=s.id and i.id_met=m.id and w.id_ins=i.id and t.id_ws=w.id and s.id="+ params.id_stu;
// 2nd query
Student.sqlquery(sql, function (err,data) {
if (err) sails.log.debug(err);
else l_queries.totals = data;
return res.json(l_queries);
});
});
/* Example of data recieved via POST
{
"id_stu": 80,
"begin": "2015-07-01",
"end": "2015-07-31"
}
*/
var params = req.params.all();
console.log(JSON.stringify(params));
// Data to return
var l_queries = {
"results" : [],
"totals" : 0
};
if (!params.id_stu)
return res.json(500, {error: "No student defined"});
var sql = "SELECT result, COUNT(result) percentage" +
" FROM method m, student s, instruction i, working_session w, try t" +
" WHERE m.id_stu=s.id and i.id_met=m.id and w.id_ins=i.id and t.id_ws=w.id and s.id="+ params.id_stu +
" and t.begin>='"+ params.begin +"' and t.end<='" + params.end + "'" +
" GROUP BY result" +
" ORDER BY result";
// 1st query
Student.sqlquery(sql, function (err,data) {
if (err) sails.log.debug(err);
else l_queries.results = data;
sql = "SELECT COUNT(result)" +
" FROM method m, student s, instruction i, working_session w, try t" +
" WHERE m.id_stu=s.id and i.id_met=m.id and w.id_ins=i.id and t.id_ws=w.id and s.id="+ params.id_stu;
// 2nd query
Student.sqlquery(sql, function (err,data) {
if (err) sails.log.debug(err);
else l_queries.totals = data;
return res.json(l_queries);
});
});
}
};
......@@ -10,19 +10,19 @@ module.exports = {
// login action
// expected params in post body: email, password
//
login: function (req, res) {
login: function (req, res) {
var bcrypt = require('bcrypt-nodejs');
var email = req.body.email;
var password = req.body.password;
// no credentials
if (!email || !password)
return res.json(401, {error: 'No credentials sent'});
sails.log.debug("Supervisor Login request:"+email);
// search user by email
Supervisor.findOneByEmail(email).exec(function (err, sup) {
if (err)
if (err)
return res.json(500, { error: 'DB error' });
if (!sup)
......@@ -30,16 +30,16 @@ module.exports = {
// if found, check password in encrypted form
bcrypt.compare(password, sup.password, function (err, match) {
if (err)
if (err)
return res.json(500, { error: 'Server error' });
if (match) { // password match
var user = sup;
// Check if user is an Office administrator
Office.findOne(user.office).exec(function(err, off) {
if (off){
if (off){
if (off.admin == sup.id) {
console.log("This supervisor with id "+ user.id + " is admin of the office " + off.id);
user.isSupAdmin = true;
......@@ -52,10 +52,10 @@ module.exports = {
// all supervisor information is passed as payload to the token
return res.json({
user: user,
user: user,
server_time: (new Date()).getTime(),
token: sailsTokenAuth.issueToken(user, sails.config.jwt.expiresInMinutes)});
});
});
} else {
return res.json(401, { error: 'Invalid password' });
}
......@@ -69,17 +69,17 @@ module.exports = {
//
activate: function(req, res) {
if (!req.body.code)
return res.json(500, {error: "Code must be specified"});
return res.json(500, {error: "Code must be specified"});
if (!req.body.email)
return res.json(500, {error: "Email must be specified"});
return res.json(500, {error: "Email must be specified"});
// Find the supervisor by email and check the code
Supervisor.findOne({email: req.body.email}).exec(function findOneCB(err,sup){
if (err)
return res.json(500, {error: "Error finding the user"});
// PROBAR A DEVOLVER EL SUPERVISOR VACÍO!!
// PROBAR A DEVOLVER EL SUPERVISOR VACÍO!!
if(sup){
var hash_code = sailsHash.hashCode(sup.name + sup.email + sup.phone);
......@@ -94,8 +94,8 @@ module.exports = {
// Model.update(find criteria, updated records).exec(callbacks returns(error, updated records))
Supervisor.update({email: req.body.email},{active:'true', password: req.body.password }).exec(function afterwards(err,updated){
if (err)
return res.json(500, {error: "Error activating account"});
return res.json(500, {error: "Error activating account"});
console.log('User activated: '+updated[0].email);
return res.json(200, {user: updated[0]});
});
......@@ -103,8 +103,8 @@ module.exports = {
// Model.update(find criteria, updated records).exec(callbacks returns(error, updated records))
Supervisor.update({email: req.body.email},{active:'true' }).exec(function afterwards(err,updated){
if (err)
return res.json(500, {error: "Error activating account"});
return res.json(500, {error: "Error activating account"});
console.log('User activated: '+updated[0].email);
return res.json(200, {user: updated[0]});
});
......@@ -124,19 +124,19 @@ module.exports = {
//
deactivate: function(req, res) {
if (!req.body.email)
return res.json(500, {error: "Email must be specified"});
return res.json(500, {error: "Email must be specified"});
// Find the supervisor by email
Supervisor.findOne({email: req.body.email}).exec(function findOneCB(err,sup){
if (err)
return res.json(500, {error: "Error finding the user"});
if(sup){
// Model.update(find criteria, updated records).exec(callbacks returns(error, updated records))
Supervisor.update({email: req.body.email},{active:'false'}).exec(function afterwards(err,updated){
if (err)
return res.json(500, {error: "Error activating account"});
if (err)
return res.json(500, {error: "Error activating account"});
console.log('User deactivated: '+updated[0].email);
return res.json(200, {user: updated[0]});
});
......@@ -158,16 +158,16 @@ module.exports = {
Supervisor.create(params).exec(function (err, created) {
if (err) {
console.log(err);
return res.json(500, {error: 'User not created'});
return res.json(500, {error: 'User not created'});
}
if (created) {
// TODO: Send email confirmation
// created.sendMail();
return res.json({
user: created,
token: sailsTokenAuth.issueToken(created.id)});
user: created,
token: sailsTokenAuth.issueToken(created.id)});
} else {
return res.json(500, {error: 'User not created'});
return res.json(500, {error: 'User not created'});
}
});
},
......@@ -202,7 +202,7 @@ module.exports = {
[
//
// First, let's get the list of students of the supervisor
//
//
function (cb) {
console.log("getting supervisor's students");
StuSup.find({supervisor: idSup}).populate('student').exec(function(err, stusups){
......@@ -217,7 +217,7 @@ module.exports = {
stusup.student.supervision = 1;
l_stu.push(stusup.student);
next();
},
},
function(err) { // when forEach has finished
if (err) return cb(err);
cb();
......@@ -232,7 +232,7 @@ module.exports = {
function (cb) {
console.log("getting office students");
if (req.token.isSupAdmin) {
Student.find({office: req.token.office.id }).exec(function(err, students){
Student.find({office: req.token.office.id }).exec(function(err, students){
if (err) return cb(err);
var _ = require('lodash');
var l_stu_id = _.pluck(l_stu, 'id'); // get a list of supervised student ids
......@@ -264,9 +264,9 @@ module.exports = {
if (err) {
sails.log.debug(err);
console.log(JSON.stringify(err));
return res.json(500, err);
return res.json(500, err);
}
if ( !row || row.length == 0) {
if ( !row || row.length == 0) {
student.current_method = 'no_method';
student.current_instruction = 'no_instruction';
} else {
......@@ -279,7 +279,7 @@ module.exports = {
function(err) {
if (err) return cb(err);
cb();
});
});
}
],
function(err) { // All steps done! return list of students if no error
......@@ -295,7 +295,7 @@ module.exports = {
// returns all the supervisor's pictos
pictos: function(req, res){
var idSup = req.params.id;
Supervisor.findOne(idSup).exec(function(err, sup) {
if(err)
return res.json(500, {error: 'DB error'});
......@@ -317,7 +317,7 @@ module.exports = {
//
upload: function (req, res) {
if(req.method === 'GET')
return res.json({'status':'GET not allowed'});
return res.json({'status':'GET not allowed'});
// Call to /upload via GET is error
var uploadFile = req.file('file');
......@@ -331,16 +331,16 @@ module.exports = {
var dirUpload = path.join(process.cwd(), '../upload/' + req.body.folder);
req.body.filename = sailsHash.hashCode(req.body.filename + Date().toString()) + '.' + req.body.extension;
uploadFile.upload({
dirname: dirUpload,
uploadFile.upload({
dirname: dirUpload,
saveAs: req.body.filename
},
function onUploadComplete (err, files) {
function onUploadComplete (err, files) {
// Files will be uploaded to .tmp/uploads
if (err) return res.serverError(err);
// Files will be uploaded to .tmp/uploads
if (err) return res.serverError(err);
// IF ERROR Return and send 500 error with error
// Delete old pic (if it isn't the default pic)
Supervisor.findOne({id: req.body.id}).exec(function(err, found){
if(found && found.pic != "/app/img/default.jpg"){
......@@ -352,13 +352,13 @@ module.exports = {
console.log('Old pic destroyed');
});
}
});
// Store in DB new URL pic
});
// Store in DB new URL pic
Supervisor.update({id: req.body.id}, {pic: '/upload/' + req.body.folder + '/' + req.body.filename}).exec(function(err, updated){
if(updated)
console.log("Supervisor picture updated");
});
});
files[0].name = req.body.filename;
delete files[0].fd;
......@@ -381,5 +381,59 @@ module.exports = {
} , 5);
}
);
}
},
/**
* Subscribe to supervisor's room
* @param {Object} request must have the following format:
*
* {
* action: subscribe,
* attributes: { id_sup: '' }
* }
*
* @param {Object} response
* @return {Object} response
*/
subscribe: function(request, response) {
var action = request.param('action');
var attributes = request.param('attributes');
if (action === 'subscribe' && request.isSocket && attributes.id_sup) {
sails.hooks.rooms.subscribeToRoom(
sails.hooks.rooms.supervisor(attributes.id_sup),
request.socket
);
return response.ok();
} else {
return response.badRequest();
}
},
/**
* Unsubscribe from supervisor's room
* @param {Object} request must have the following format:
*
* {
* action: unsubscribe,
* attributes: { id_sup: '' }
* }
*
* @param {Object} response
* @return {Object} response
*/
unsubscribe: function(request, response) {
var action = request.param('action');
var attributes = request.param('attributes');
if (action === 'unsubscribe' && request.isSocket && attributes.id_sup) {
sails.hooks.rooms.unsubscribeFromRoom(
sails.hooks.rooms.supervisor(attributes.ip_sup),
request.socket
);
return response.ok();
} else {
return response.badRequest();
}
}
};
/**
* Functions defining the events sent inside the sockets.
* In order to create a new event you have to call the corresponding
* function with the necesary parameters, and you will receive an Object:
*
* {
* name: 'eventName',
* data: 'eventData'
* }
*
* Where 'name' is the name of the event and 'data' is the block of
* information to send.
* @type {Object}
*/
module.exports = function eventsHook (sails) {
return {
/**
* Speacial Function wrapping sails.sockets.broadcast that uses a room
* from sails.hooks.rooms and an event from sails.hooks.events in
* order to broadcast information. This also logs the event as debug
* level information with the message:
*
* "websocketEvent": {
* "room",
* "name",
* "data": { ... }
* }
*
* @param {RoomId} rooms RoomID or IDs where the event will be sent
* @param {Object} event A tuple {name, data} returned by a
* function inside sails.sockets.events
* @param {socket} socketToOmit If specified, this socket will not receive
* the event
*/
broadcastEvent: function (rooms, event, socketToOmit) {
// Ensure rooms is an Array
if (!(rooms instanceof Array)) {
rooms = [rooms];
}
sails.log.debug('"websocketEvent":', JSON.stringify({
rooms: rooms,
name: event.name,
data: event.data,
socketToOmit: socketToOmit ? socketToOmit.id : undefined
}));
sails.sockets.broadcast(
rooms,
event.name,
event.data,
socketToOmit || undefined
);
},
/**
* A supervisor has been linked to a student.
* @param {ID} supId ID of the supervisor
* @param {ID} stu_id ID of the student
* @return {Object} {name, data}
*/
linkSupervisorToStudent: function (supId, stuId) {
return {
name: 'linkSupervisorToStudent',
data: {
sup_id: supId,
stu_id: stuId
}
};
},
/**
* Someone has subscribed/unsubscribed to/from a room. The number
* of subscribes is sent
* @param {number} subscriberCount Number of subscribers
* @return {Object} {name, data}
*/
roomSubscribersChange: function (subscriberCount) {
return {
name: 'update_peers',
data: {
count: subscriberCount
}
};
}
};
};
/**
* This hook is used for managing the rooms IDs.
* Every room created should call one of this functions in order
* to obtain an ID.
* @type {Object}
*/
module.exports = function roomsHook (sails) {
return {
/**
* Special function that subscribes a socket to a given room.
* This creates the connection and logs to debug with this format:
*
* {
* websocketSubscribe: {
* room,
* socket
* }
* }
*
* @param {RoomID} room Room to subscribe
* @param {Socket} socket Socket added to the subscription
*/
subscribeToRoom: function (room, socket) {
sails.log.debug('"websocketSubscribe":', JSON.stringify({
room: room,
socket: socket.id
}));
sails.sockets.join(socket, room, function () {
sails.io.sockets.in(room).clients(function(error, ids) {
if (!error) {
sails.hooks.events.broadcastEvent(
room,
sails.hooks.events.roomSubscribersChange(ids.length)
);
}
});
});
},
/**
* Special function that unsubscribes a socket from a given room.
* This remotes the connection and logs to debug with this format:
*
* {
* websocketUnsubscribe: {
* room,
* socket
* }
* }
*
* @param {RoomID} room Room to unsubscribe from
* @param {Socket} socket Socket removed from the subscription
*/
unsubscribeFromRoom: function (room, socket) {
sails.log.debug('"websocketUnsubscribe":', JSON.stringify({
room: room,
socket: socket.id
}));
sails.sockets.leave(socket, room, function () {
sails.io.sockets.in(room).clients(function(error, ids) {
if (!error) {
sails.hooks.events.broadcastEvent(
room,
sails.hooks.events.roomSubscribersChange(ids.length)
);
}
});
});
},
/**
* Student related rooms
* @param {ID} studentId Student's ID used for creating a room.
* @return {RoomID} RoomID generated
*/
student: function (studentId) {
return 'studentRoom' + studentId;
},
/**
* Supervisor related rooms
* @param {ID} supervisorId Supervisor's ID used for creating a room.
* @return {RoomID} RoomID generated
*/
supervisor: function (supervisorId) {
return 'supervisorRoom' + supervisorId;
}
};
};
'use strict';
/* Services */
/* global io */
//
// This defines an interceptor service in every HTTP request to add session
// token in the header and in every HTTP response to handle non authorized
// connections
//
'use strict';
var module = angular.module('dashboardServices', []);
angular.module('dashboardServices', [])
.service('authInterceptor', function ($rootScope, $q, $window) {
/**
* This defines an interceptor service in every HTTP request to add session
* token in the header and in every HTTP response to handle non authorized
* connections.
*/
module.factory('AuthInterceptorService', function ($rootScope, $q, $window) {
return {
request: function (config) {
config.headers = config.headers || {};
......@@ -30,7 +29,68 @@ angular.module('dashboardServices', [])
return $q.reject(rejection);
}
};
})
.config(function ($httpProvider) {
$httpProvider.interceptors.push('authInterceptor');
});
\ No newline at end of file
});
// Add AuthInterceptorService to $httpProvider.interceptors
module.config(function ($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptorService');
});
/**
* IOService that must be used as communication with the server.
* It allows to subscribe/unsubscribe to/from rooms and listen/stop listening
* to events.
*/
module.factory('IOService', function ($window) {
return {
/**
* Send a get request to the server via websocket
* @param {String} url Url of the request
* @param {Function} callback Function to be called on response
*/
get: function(url, callback) {
io.socket.get(url, { token: $window.sessionStorage.token }, callback);
},
/**
* Send a post request to the server via websocket
* @param {String} url Url of the request
* @param {Object} data If this parameter is not an object, it will
* be wrapped inside an object:
* { data, token }, otherwise the token will be
* appended to the parameters
* @param {Function} callback Function to be called on response
*/
post: function (url, data, callback) {
// Create the request data and convert it to an object if necesary
// Then append the token
var requestData = data;
if (typeof requestData !== 'object') {
requestData = { data: data };
}
requestData.token = $window.sessionStorage.token;
io.socket.post(url, requestData, callback);
},
/**
* Subscribes to an event with the given function using websockets
* @param {String} event Event to subscribe to
* @param {Function} callback Function to be executed when the event occurs
*/
on: function (event, callback) {
io.socket.on(event, callback);
},
/**
* Unsubscribe from an event
* @param {String} event Event to unsubscribe from
* @param {Function} callback If specified, only this funcion will be
* unsuscribed from the event, otherwise all
* functions subscribed to this event will be
* removed
*/
off: function (event, callback) {
io.socket.off(event, callback);
}
};
});
......@@ -12,7 +12,8 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
config,
$window,
$translate,
ngToast) {
ngToast,
IOService) {
$scope.formdatastudent = {
username: '',
password: '',
......@@ -148,6 +149,10 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
$translate('student_deleted').then(function (translation) {
ngToast.success({ content: translation });
});
IOService.post('/stu/unsubscribe', {
action: 'unsubscribe'
});
})
.error(function () {
$translate('student_not_deleted').then(function (translation) {
......@@ -157,7 +162,30 @@ dashboardControllers.controller('StudentsCtrl', function StudentsCtrl(
}
};
io.socket.post('/stu/unsubscribe', { action: 'unsubscribe' });
// When a new student is added to the supervisor, we should update
// the student list if necesary
IOService.on('linkSupervisorToStudent', function (eventData) {
eventData.sup_id = parseInt(eventData.sup_id, 10);
eventData.stu_id = parseInt(eventData.stu_id, 10);
if (eventData.sup_id === $scope.user.id) {
IOService.get('/stu/' + eventData.stu_id, function (studentData) {
var i;
var studentAlreadyAdded = false;
for (i = 0; i < $scope.students.length; i++) {
if ($scope.students[i].id === eventData.stu_id) {
studentAlreadyAdded = true;
break;
}
}
if (!studentAlreadyAdded) {
$scope.students.push(studentData);
$scope.$apply();
}
});
}
});
});
/**
......
/* global io */
'use strict';
//-----------------------
// Supervisor Controller
//-----------------------
dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl($scope, $window, $location) {
dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl($scope, $window, $location, IOService) {
// Restore user data from session
var user = JSON.parse($window.sessionStorage.user);
// Assign values this way (like an object) to ensure it's the parent scope
$scope.user.id = user.id;
$scope.user.name = user.name;
......@@ -22,4 +24,11 @@ dashboardControllers.controller('SupervisorCtrl', function SupervisorCtrl($scope
$location.path('/setup');
};
});
\ No newline at end of file
// Subscribe to the supervisor's room
IOService.post('/sup/subscribe', {
action: 'subscribe',
attributes: {
id_sup: $scope.user.id
}
});
});
......@@ -45,7 +45,9 @@ module.exports.policies = {
destroy: ['tokenAuth', 'isAdmin'],
students: ['tokenAuth'],
pictos: ['tokenAuth'],
upload: ['tokenAuth']
upload: ['tokenAuth'],
subscribe: ['tokenAuth'],
unsubscribe: ['tokenAuth']
},
DeviceController: {
register: true,
......
/**
* Route Mappings
* (sails.config.routes)
*
*
* Your routes map URLs to views and controllers.
*
* If Sails receives a URL that doesn't match any of the routes below,
......@@ -22,16 +22,7 @@
module.exports.routes = {
/***************************************************************************
* *
* Make the view located at `views/homepage.ejs` (or `views/homepage.jade`, *
* etc. depending on your default view engine) your home page. *
* *
* (Alternatively, remove this and add an `index.html` file in your *
* `assets` directory) *
* *
***************************************************************************/
// Supervisor
'post /sup/login': 'SupervisorController.login',
'post /sup': 'SupervisorController.create',
'put /sup': 'SupervisorController.update',
......@@ -40,13 +31,15 @@ module.exports.routes = {
'get /sup/get/:id': 'SupervisorController.findOne',
'post /sup/activate': 'SupervisorController.activate',
'get /sup/:id/students': 'SupervisorController.students',
'post /sup/subscribe': 'SupervisorController.subscribe',
'post /sup/unsubscribe': 'SupervisorController.unsubscribe',
'post /sup/upload': 'SupervisorController.upload', // upload profile img file
// Pictos
'get /sup/:id/pictos': 'SupervisorController.pictos',
'get /sup/:id/pic_categories/:id_cat': 'Picto.categories',
'get /sup/:id/pic_fromcategory/:id_cat': 'Picto.fromcategory',
'post /sup/upload': 'SupervisorController.upload', // upload profile img file
// Pictogram administration
'post /admin/login': 'AdminController.login',
......@@ -65,7 +58,7 @@ module.exports.routes = {
'get /office/get/:id': 'OfficeController.get',
'get /office/get_all': 'OfficeController.getAll',
'get /office/get/:id/supervisors': 'OfficeController.supervisors',
/////////////////////////////////////////////////////////////////////////
// STUDENTS /////////////////////////////////////////////////////////////
// get /student --> List all students
......@@ -127,16 +120,16 @@ module.exports.routes = {
// (check them by inspecting the policies.js file)
// Reports
'get /ws/:id_stu/year/:year': 'WorkingSessionController.per_year',
'get /ws/:id_stu/month/:month': 'WorkingSessionController.per_month',
// Working Sessions > Tries
'get /ws/:id_ws/tries': 'WorkingSession.tries',
'post /workingsession/:id_ws/close': 'WorkingSession.close',
'get /ws/:id_ws/tries': 'WorkingSession.tries',
'post /workingsession/:id_ws/close': 'WorkingSession.close',
'put /try/:id': 'Try.update',
'post /try': 'Try.create',
// Instructions > Working Sessions
'get /instruction/:id_ins/ws': 'Instruction.ws',
//'get /instruction/:id_ins/tries': 'Instruction.tries', // BORRAR aquí y en wiki
......
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