You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

791 lines
33 KiB

var express = require('express');
var app = express();
var router = express.Router();
var jwt = require('jsonwebtoken');
var config = require('../config/config');
var crypto = require('crypto');
var formidable = require('formidable');
var fs = require('fs');
var https = require('https');
app.set('superSecret', config.secret);
/*******MODELS*********/
var publicationModel = require('../models/publicationModel');
var userModel = require('../models/userModel');
var dietModel = require('../models/dietModel');
var routineModel = require('../models/routineModel');
/** POST '/users/register' **/
exports.register = function (req, res) {
console.log(req.body);
var user = new userModel({
name: req.body.name,
role: req.body.role,
password: crypto.createHash('sha256').update(req.body.password).digest('base64'),
email: req.body.email,
description: "Hi, i'm here to train.",
avatar: 'img/user.png',
background: 'img/background.png',
attributes: {
height: req.body.height,
weight: req.body.weight,
gender: req.body.gender,
age: req.body.age
},
points: {
total: 0
}
});
/* gamification */
var reward = {
concept: "account created",
date: Date(),
value: +1
};
user.points.history.push(reward);
user.points.total = user.points.total + 1;
/* end of gamification */
/*notification*/
var notification = {
state: "pendent",
message: "Wellcome! this is your profile, update the Profile picture to let other members recognize you",
link: "editUser/" + user._id,
icon: "newpetition.png",
date: Date()
};
user.notifications.push(notification);
/* end of notification*/
user.save(function (err, user) {
if (err) {
console.log(err.message);
return res.status(500).send(err.message);
}
//res.status(200).jsonp(user); en comptes de retoranr la data del signup, fem el login directament
console.log("signup fet correctament, redirigint al login internament automàtic");
exports.login(req, res);
});
};
var SECRET = "6LcyxhIUAAAAAPkCdz5HoBPN5--RhP7mpIE-V2CL";
function verifyRecaptcha(key, callback) {
https.get("https://www.google.com/recaptcha/api/siteverify?secret=" + SECRET + "&response=" + key, function(res) {
var data = "";
res.on('data', function (chunk) {
data += chunk.toString();
});
res.on('end', function() {
try {
var parsedData = JSON.parse(data);
callback(parsedData.success);
} catch (e) {
callback(false);
}
});
});
}
/** POST '/users/login' **/
exports.login = function (req, res) {
verifyRecaptcha(req.body["g-recaptcha-response"], function() {
userModel.findOne({
email: req.body.email
})
.select('+password')
.exec(function (err, user) {
if (err) throw err;
if (!user) {
res.json({success: false, message: 'Authentication failed. User not found.'});
} else if (user) {
req.body.password = crypto.createHash('sha256').update(req.body.password).digest('base64');
if (user.password != req.body.password) {
res.json({success: false, message: 'Authentication failed. Wrong password.'});
} else {
var indexToken = -1;
for (var i = 0; i < user.tokens.length; i++) {
if (user.tokens[i].userAgent == req.body.userAgent) {
indexToken = JSON.parse(JSON.stringify(i));//stringify i parse pq es faci una còpia de la variable i, enlloc de una referència
}
}
console.log(indexToken);
if (indexToken == -1) {//userAgent no exist
var tokenGenerated = jwt.sign({foo: 'bar'}, app.get('superSecret'), {
// expiresIn: 86400 // expires in 24 hours
});
var newToken = {
userAgent: req.body.userAgent,
token: tokenGenerated,
os: req.body.os,
browser: req.body.browser,
device: req.body.device,
os_version: req.body.os_version,
browser_version: req.body.browser_version,
ip: req.body.ip,
lastLogin: Date()
};
user.tokens.push(newToken);
} else {//userAgent already exist
user.tokens[indexToken].token = "";
var tokenGenerated = jwt.sign({foo: 'bar'}, app.get('superSecret'), {
// expiresIn: 86400 // expires in 24 hours
});
user.tokens[indexToken].token = tokenGenerated;
user.tokens[indexToken].ip = req.body.ip;
user.tokens[indexToken].lastLogin = Date();
}
user.save(function (err, user) {
if (err) return res.send(500, err.message);
// return the information including token as JSON
user.password = "";
res.json({
user: user,
success: true,
message: 'Enjoy your token!',
token: tokenGenerated
});
});
}
}
});
})};
/** POST '/logout' **/
exports.logout = function (req, res, callback) {
var token = req.headers.authorization;
var decoded = verify(token);
if (decoded) {
db.get(decoded.auth, function (err, record) {
if (err) throw err;
var updated = JSON.parse(record);
updated.valid = false;
db.put(decoded.auth, updated, function (err) {
if (err) throw err;
res.writeHead(200, {'content-type': 'text/plain'});
res.end('Logged Out!');
return callback(res);
});
});
} else {
authFail(res, done);
return callback(res);
}
};
/*** Building a File Uploader with NodeJs
* https://coligo.io/building-ajax-file-uploader-with-node/
*/
/** POST '/users/upload' **/
exports.avatarUpload = function (req, res) {/* no sé si s'ha provat si funciona, per ara almenys no està linkat ni es fa servir */
// create an incoming form object
var form = new formidable.IncomingForm();
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = path.join(__dirname, '/uploads');
// every time a file has been uploaded successfully,
// rename it to it's orignal name
form.on('file', function (field, file) {
fs.rename(file.path, path.join(form.uploadDir, file.name));
});
// log any errors that occur
form.on('error', function (err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
form.on('end', function () {
res.end('success');
});
// parse the incoming request containing the form data
form.parse(req);
};
/** PUT '/users/:userid' **/
exports.updateUser = function (req, res) {//funciona
var id = req.params.userid;
var user = req.body;
userModel.update({'tokens.token': req.headers['x-access-token']}, user,
function (err) {
if (err) return console.log(err);
console.log(user);
res.status(200).jsonp(user);
});
};
/** DELETE '/users/:userid' **/
exports.deleteUserById = function (req, res) {
userModel.findByIdAndRemove({_id: req.params.userid}, function (err) {
if (err) return res.send(500, err.message);
res.status(200).send("Deleted");
});
};
/** GET '/users/' **/
exports.getUsers = function (req, res) {
userModel.find({role: 'user'})
.limit(Number(req.query.pageSize))
.skip(Number(req.query.pageSize) * Number(req.query.page))
.exec(function (err, users) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(users);
});
};
/** GET '/users/:userid' **/
exports.getUserById = function (req, res) {
userModel.findOne({_id: req.params.userid})
.lean()
.populate('diets', 'title description')
.populate('routines', 'title description')
.populate('trainers', 'name avatar description disciplines')
.populate('clients.client', 'name avatar')
.populate('publications')
.exec(function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'User not found.'});
} else if (user) {
/* aquí va el carro de bucle per acabar retornant només les peticions pendents */
var pendentNumber=0;
for (var i = 0; i < user.notifications.length; i++) {
if (user.notifications[i].state == "pendent") {
pendentNumber++;
}
}
user.pendentNotificationsNumber=pendentNumber;
/* fi del carro de bucle de peticions pendents */
res.status(200).jsonp(user);
}
});
};
exports.getUserByToken = function (req, res) {
console.log(req.params.tok);
userModel.findOne({'tokens.token': req.params.tok})
.lean()
.populate('diets', 'title description')
.populate('routines', 'title description')
.populate('trainers', 'name avatar description disciplines')
.populate('clients.client', 'name avatar')
.populate('publications')
.exec(function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'User not found.'});
} else if (user) {
/* aquí va el carro de bucle per acabar retornant només les peticions pendents */
var pendentNumber=0;
for (var i = 0; i < user.notifications.length; i++) {
if (user.notifications[i].state == "pendent") {
pendentNumber++;
}
}
user.pendentNotificationsNumber=pendentNumber;
/* fi del carro de bucle de peticions pendents */
res.status(200).jsonp(user);
}
});
};
/** GET '/users/:userid/network' **/
exports.getUserNetworkById = function (req, res) {
userModel.findOne({_id: req.params.userid})
.lean()
.populate('followers', 'name avatar description')
.populate('following', 'name avatar description')
.exec(function (err, user) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(user);
});
};
/** GET '/users/:userid/suggestions' **/
exports.getUserSuggestionsById = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']})
.exec(function (err, user) {
if (err) return res.send(500, err.message);
userModel.find({
$and: [
{_id: { $nin: user._id}},
{_id: { $nin: user.following}}
],
city: user.city})
.limit(Number(req.query.pageSize))
.skip(Number(req.query.pageSize) * Number(req.query.page))
.select('name role email description avatar')
.exec(function (err, users) {
if (err) return res.send(500, err.message);
console.log(users);
if (users.length>0) {
res.status(200).jsonp(users);
} else {
//si no té users a la ciutat, li tornem users igualment (tot i no ser de la mateixa ciutat)
userModel.find({
$and: [
{_id: { $nin: user._id}},
{_id: { $nin: user.following}}
]})
.limit(Number(req.query.pageSize))
.skip(Number(req.query.pageSize) * Number(req.query.page))
.select('name role email description avatar')
.exec(function (err, users) {
res.status(200).jsonp(users);
});
}
});
});
};
/** GET '/users/:userid/diets' **/
exports.getDietsFromUserId = function (req, res) {
userModel.findOne({_id: req.params.userid})
.populate('diets')
.exec(function (err, user) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(user.diets);
});
};
/** GET '/users/:userid/routines' **/
exports.getRoutinesFromUserId = function (req, res) {
userModel.findOne({_id: req.params.userid})
.populate('routines')
.exec(function (err, user) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(user.routines);
});
};
/** POST '/users/sendPetitionToTrainer/:trainerid' **/
exports.sendPetitionToTrainer = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']}, function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'sending petition failed. user not found.'});
} else if (user) {
console.log(user.name);//aquí potser caldria comprovar que la routine és la que han creat per l'user
//ara busquem el trainer
userModel.findOne({_id: req.params.trainerid}, function (err, trainer) {
if (err) return res.send(500, err.message);
if (!trainer) {
res.json({success: false, message: 'sending petition failed. trainer not found.'});
} else if (trainer) {
var newPetition = {
clientid: user._id,
message: req.body.message,
state: "pendent"
};
trainer.clientsPetitions.push(newPetition);
/*notification*/
var notification = {
state: "pendent",
message: "client has sent a petition to you",
link: "dashboard",
icon: "newpetition.png",
date: Date()
};
trainer.notifications.push(notification);
/* end of notification*/
trainer.save(function (err) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(trainer);
});
}//end else if
});
}//end else if
});
};
exports.getNumberOfNotifications = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']})
.exec(function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'User not found.'});
} else if (user) {
/* aquí va el carro de bucle per acabar retornant només les peticions pendents */
var pendentNumber=0;
for (var i = 0; i < user.notifications.length; i++) {
if (user.notifications[i].state == "pendent") {
pendentNumber++;
}
}
/* fi del carro de bucle de peticions pendents */
res.status(200).jsonp(pendentNumber);
}
});
};
/** GET '/users/:userid/getNotifications' **/
exports.getNotifications = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']})
.exec(function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'User not found.'});
} else if (user) {
var viewed=[];
var pendent=[];
for (var i = 0; i < user.notifications.length; i++) {
if (user.notifications[i].state == "pendent") {
pendent.push(user.notifications[i]);
user.notifications[i].state = "viewed";
user.notifications[i].dateviewed = Date();
}else{
viewed.push(user.notifications[i]);
}
}
user.save(function (err) {
if (err) return res.send(500, err.message);
res.status(200).jsonp({
pendent: pendent,
viewed: viewed
});
});
}
});
};
/** POST '/users/:userid/deleteSelectedTokens' **/
exports.deleteSelectedTokens = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']}, function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'user not found.'});
} else if (user) {
console.log(user);
for (var i = 0; i < req.body.devicesToDelete.length; i++) {
for (var j = 0; j < user.tokens.length; j++) {
if (user.tokens[j].userAgent == req.body.devicesToDelete[i].userAgent) {
user.tokens.splice(j, 1);
}
}
}
user.save(function (err) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(user);
});
}//end else if
});
};
/**
userA: el que fa l'acció de seguir --> se li posa userB a following
userB: el que reb el seguiment --> se li posa el userA al followers
**/
/** POST '/users/follow' **/
exports.follow = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']}, function (err, userA) {
if (err) return res.send(500, err.message);
if (!userA) {
res.json({success: false, message: 'userA not found.'});
} else if (userA) {
//ara busquem el userB
userModel.findOne({_id: req.body.userid}, function (err, userB) {
if (err) return res.send(500, err.message);
if (!userB) {
res.json({success: false, message: 'userB not found.'});
} else if (userB) {
userB.followers.push(userA._id);
/*notification*/
var notification = {
state: "pendent",
message: userA.name + " followed you",
link: "dashboard",
icon: "follower.png",
date: Date()
};
userB.notifications.push(notification);
/* end of notification*/
/* gamification */
var reward = {
concept: userA.name + " followed you",
date: Date(),
value: +1
};
userB.points.history.push(reward);
userB.points.total = userB.points.total + 1;
/* end of gamification */
userB.save(function (err) {
if (err) return res.send(500, err.message);
userA.following.push(userB._id);
/* gamification */
var reward = {
concept: "followed " + userB.name,
date: Date(),
value: +1
};
userA.points.history.push(reward);
userA.points.total = userA.points.total + 1;
/* end of gamification */
userA.save(function (err) {
if (err) return res.send(500, err.message);
userModel.findOne({_id: userA._id}).lean().populate('following', 'name avatar')
.exec(function (err, userA) {
if (err) return res.send(500, err.message);
console.log("user followed" + userB.name);
res.status(200).jsonp(userB);
});
});
});
}//end else if
});
}//end else if
});
};
/**
userA: el que fa l'acció de deixar de seguir --> se li treu userB de following
userB: el que deixa de tenir el seguiment --> se li treu l'userA del followers
**/
/** POST '/users/unfollow' **/
exports.unfollow = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']}, function (err, userA) {
if (err) return res.send(500, err.message);
if (!userA) {
res.json({success: false, message: 'userA not found.'});
} else if (userA) {
//ara busquem el userB
userModel.findOne({_id: req.body.userid}, function (err, userB) {
if (err) return res.send(500, err.message);
if (!userB) {
res.json({success: false, message: 'userB not found.'});
} else if (userB) {
var indexFollower = -1;
for (var i = 0; i < userB.followers.length; i++) {
if (userB.followers[i].equals(userA._id)) {
indexFollower = JSON.parse(JSON.stringify(i));
}
}
if (indexFollower > -1) {
userB.followers.splice(indexFollower, 1);
/*notification*/
var notification = {
state: "pendent",
message: userA.name + " unfollowed you",
link: "dashboard",
icon: "unfollower.png",
date: Date()
};
userB.notifications.push(notification);
/* end of notification*/
/* gamification */
var reward = {
concept: userA.name + " unfollowed you",
date: Date(),
value: -1
};
userB.points.history.push(reward);
userB.points.total = userB.points.total - 1;
/* end of gamification */
userB.save(function (err) {
if (err) return res.send(500, err.message);
var indexFollower = -1;
for (var i = 0; i < userA.following.length; i++) {
if (userA.following[i].equals(userB._id)) {
indexFollower = JSON.parse(JSON.stringify(i));
}
}
if (indexFollower > -1) {
userA.following.splice(indexFollower, 1);
/* gamification */
var reward = {
concept: "unfollowed " + userB.name,
date: Date(),
value: -1
};
userA.points.history.push(reward);
userA.points.total = userA.points.total - 1;
/* end of gamification */
userA.save(function (err) {
if (err) return res.send(500, err.message);
userModel.findOne(userA).lean().populate('following', 'name avatar')
.exec(function (err, userA) {
if (err) return res.send(500, err.message);
console.log("user followed" + userB.name);
res.status(200).jsonp(userB);
});
});
} else {//else de indexFollower>-1
res.status(200).jsonp({message: 'not found'});
}
});
} else {//else de indexFollower>-1
res.status(200).jsonp({message: 'not found'});
}
}//end else if
});
}//end else if
});
};
/**GET '/search/:searchstring' **/
exports.search = function (req, res) {
userModel.find({
name: new RegExp(req.params.searchstring, "i"),
role: 'user'
})//perquè retorni tots els objectes que continguin l'string sense necessitat de que sigui exactament la mateixa string
.limit(Number(req.query.pageSize))
.skip(Number(req.query.pageSize) * Number(req.query.page))
.exec(function (err, users) {
if (err) return res.send(500, err.message);
userModel.find({
name: new RegExp(req.params.searchstring, "i"),
role: 'trainer'
})//perquè retorni tots els objectes que continguin l'string sense necessitat de que sigui exactament la mateixa string
.limit(Number(req.query.pageSize))
.skip(Number(req.query.pageSize) * Number(req.query.page))
.exec(function (err, trainers) {
if (err) return res.send(500, err.message);
routineModel.find({title: new RegExp(req.params.searchstring, "i")})//perquè retorni tots els objectes que continguin l'string sense necessitat de que sigui exactament la mateixa string
.limit(Number(req.query.pageSize))
.skip(Number(req.query.pageSize) * Number(req.query.page))
.exec(function (err, routines) {
if (err) return res.send(500, err.message);
dietModel.find({title: new RegExp(req.params.searchstring, "i")})//perquè retorni tots els objectes que continguin l'string sense necessitat de que sigui exactament la mateixa string
.limit(Number(req.query.pageSize))
.skip(Number(req.query.pageSize) * Number(req.query.page))
.exec(function (err, diets) {
if (err) return res.send(500, err.message);
res.json({
users: users,
trainers: trainers,
routines: routines,
diets: diets
});
});//diets
});//routines
});//trainers
});//users
};
/** POST '/users/newMark' **/
exports.newMark = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']}, function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'user not found.'});
} else if (user) {
var newmark = {
title: req.body.title,
unit: req.body.unit
};
user.marks.push(newmark);
/* gamification */
var reward = {
concept: "new mark created: " + newmark.title,
date: Date(),
value: +3
};
user.points.history.push(reward);
user.points.total = user.points.total + 3;
/* end of gamification */
user.save(function (err) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(user.marks);
});
}//end else if user
});
};
/** DELETE /users/markid'**/
exports.deleteUserMark = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']}, function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'user not found.'});
} else if (user) {
var indexMark=-1;
for (var i = 0; i < user.marks.length; i++) {
if (user.marks[i]._id == req.params.markid) {
indexMark = JSON.parse(JSON.stringify(i));
}
}
if(indexMark>-1)
{
user.marks.splice(indexMark, 1);
/* gamification */
var reward = {
concept: "mark deleted",
date: Date(),
value: -3
};
user.points.history.push(reward);
user.points.total = user.points.total - 3;
/* end of gamification */
user.save(function (err, user) {//guardem el trainer amb la rutina treta
if (err) return res.send(500, err.message);
userModel.findOne({_id: user._id})
.lean()
.populate('diets', 'title description')
.populate('routines', 'title description')
.populate('trainers', 'name avatar description disciplines')
.populate('clients.client', 'name avatar')
.populate('publications')
.exec(function (err, user) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(user);
});
});
}else{
res.status(200).jsonp({message: 'mark not found'});
}
}
});
}
/**
cal rebre:
_id
value: 10
**/
/** POST '/users/:markid/addDayToMark' **/
exports.addDayToMark = function (req, res) {
userModel.findOne({'tokens.token': req.headers['x-access-token']}, function (err, user) {
if (err) return res.send(500, err.message);
if (!user) {
res.json({success: false, message: 'user not found.'});
} else if (user) {
var indexMark = -1;
var indexDay = -1;
for (var i = 0; i < user.marks.length; i++) {
if (user.marks[i]._id == req.params.markid) {
indexMark = JSON.parse(JSON.stringify(i));
for (var j = 0; j < user.marks[i].days.length; j++) {
if (user.marks[i].days[j].date == Date()) {
indexDay = JSON.parse(JSON.stringify(j));
}
}
}
}
if (indexMark > -1)//si la mark existeix
{
if (indexDay == -1)//però el dia no existeix encara
{
var newday = {
date: Date(),
value: req.body.value
};
user.marks[indexMark].days.push(newday);
/* gamification */
var reward = {
concept: "day value added to mark: " + user.marks[indexMark].title,
date: Date(),
value: +1
};
user.points.history.push(reward);
user.points.total = user.points.total + 1;
/* end of gamification */
user.save(function (err) {
if (err) return res.send(500, err.message);
res.status(200).jsonp(user.marks);
});
} else {
res.status(200).jsonp({message: 'mark of day already registered'});
}
} else {
res.status(200).jsonp({message: 'mark not registered'});
}
}//end else if user
});
};