/**
* This controller is in charge of all of the actions relating to a user/users
* @module UserController
* @category Backend
* @subcategory Controllers
*/
const passport = require("passport");
const bcrypt = require("bcryptjs");
const { User, FriendsData, FollowData, Notification } = require("../models/user");
var notificationController = require("./notificationController");
const e = require("express");
const NodeCache = require("node-cache");
const myCache = new NodeCache({ stdTTL: 60 * 60, checkperiod: 120 });
const {isUserOnlineRoom} = require("../sockets/sockets")
/**
* Tries to sign in a user with a given username and password
* Redirects the user to the same page he previously was on
*
* @param {*} req.body.username userName to login with
* @param {*} req.body.password password tor login with
* @return if failed, a string describing the failure, otherwise the data of the user that signed in
*/
exports.user_login = function (req, res, next) {
passport.authenticate("local", (err, user, info) => {
if (err) {
throw err;
}
if (!user) {
res.send("auth/login_failed");
} else {
req.logIn(user, (err) => {
if (err) throw err;
res.send("auth/login_success");
});
}
})(req, res, next);
};
/**
* Logs the current user on the session out
*/
exports.logout = function (req, res) {
req.logout();
res.send(req.user);
};
/**
* Tries to register a custom user with given username , email and password
* if succesful password is encrypted with bcrypt and user data is written to database
*
* @param {*} req.body.username userName to register with
* @param {*} req.body.email email to registerwith
* @param {*} req.body.password password tor register with
*
* @sends "auth/user_created" if succesful, otherwise the relevant error (username exists, etc..)
*/
exports.user_signup = function (req, res) {
// If either the email or the username exists we do not allow registration
User.findOne(
{ $or: [{ username: req.body.username }, { email: req.body.email }] },
async function (err, doc) {
if (err) {
throw err;
}
if (doc) {
if (doc.email === req.body.email) {
res.send("auth/email_exists");
} else {
res.send("auth/username_exists");
}
}
if (!doc) {
const hashedPassword = await bcrypt.hash(req.body.password, 10); // encrypt the password
const friendsData = new FriendsData({
friendsList: [],
receivedRequests: [],
sentRequests: [],
});
const followData = new FollowData({
followersList: [],
followingList: [],
});
const newUser = new User({
username: req.body.username,
email: req.body.email,
password: hashedPassword,
friendsData: friendsData,
followData: followData,
});
await newUser.save();
const notificationData = new Notification({
type: "welcomeNotification",
clearable: true,
});
notificationController.addNotificationToUser(newUser._id,notificationData ,null);
res.send("auth/user_created");
}
}
);
};
/**
* Returns the up-to-date data of the currently signed in user (or null if no user exist)
*/
exports.get_user = function (req, res) {
res.send(req.user); // The req.user stores the entire user that has been authenticated inside of it.
};
/**
* Returns data regarding a specific requested user by username
* @param {*} req.body.userId username of the user to search for
* @param {*} req
*/
exports.get_user_data = function (req, res) {
User.findOne({ _id: req.body.userId }, async function (err, doc) {
if (err) {
res.send([]);
}
if (doc) {
res.send(doc);
} else {
res.send([]);
}
});
};
/**
* Checks if a username exists in the databaase
* @param {*} req.body.username username to check for
* @sends true if username exists false otherwise
*/
exports.check_username_exists = function (req, res) {
const username = req.body.username;
let exists = myCache.get(username);
if (exists === undefined) {
User.findOne({ username: username }, async function (err, doc) {
if (err) {
}
// user exists
if (doc) {
const success = myCache.set(username, true);
res.send(true);
} else res.send(false);
});
} else {
res.send(true);
}
};
/**
* Searches user by a search string (looks at their username and various data) and what page to look in
* Results are paginated to pages with 20 entries each
*
* @param {*} req.body.searchString string to search in
* @param {*} req.body.page what page of the results we are looking for
*/
exports.searchUsers = function (req, res) {
const page = req.body.page;
const searchString = req.body.searchString;
const PAGE_SIZE = 5; // Similar to 'limit'
const skip = (page - 1) * PAGE_SIZE; // For page 1, the skip is: (1 - 1) * 20 => 0 * 20 = 0
User.find(
{ $and: [{ $text: { $search: searchString } }] },
{ score: { $meta: "textScore" } }
)
.skip(skip)
.limit(PAGE_SIZE)
.exec(async function (err, result) {
if (err) {
res.send("user/no_results");
}
// id exists
if (result) res.send(result);
else res.send("user/no_results");
});
};
/**
* Sets the redirect URI for authentication calls to be the recieved uri
* Take the data from the header (the referrer)
*/
exports.setRedirectURL = function (req, res, next) {
req.session.UrlToRedirect = req.headers.referer;
next();
};
/**
* This function redirect the caller to the redirect URI on the session
*/
exports.successRedirect = function (req, res) {
destination = req.session.UrlToRedirect || "/";
res.redirect(destination);
};
/**
* Uses passport for authentication
*/
exports.twitch_auth = function (req, res, next) {
passport.authenticate("twitch.js")(req, res, next);
};
/**
* Callback after authentication, redirects user to previously set URI
*/
exports.twitch_auth_callback = function (req, res, next) {
passport.authenticate("twitch.js", {
failureRedirect: req.session.UrlToRedirect,
})(req, res, next);
};
/**
* Uses passport for authentication
*/
exports.google_auth = function (req, res, next) {
passport.authenticate("google")(req, res, next);
};
/**
* Callback after authentication, redirects user to previously set URI
*/
exports.google_auth_callback = function (req, res, next) {
passport.authenticate("google", {
failureRedirect: req.session.UrlToRedirect,
})(req, res, next);
};
/**
* Uses passport for authentication
*/
exports.facebook_auth = function (req, res, next) {
passport.authenticate("facebook")(req, res, next);
};
/**
* Callback after authentication, redirects user to previously set URI
*/
exports.facebook_auth_callback = function (req, res, next) {
passport.authenticate("facebook", {
failureRedirect: req.session.UrlToRedirect,
})(req, res, next);
};
/**
* Update user's profile description
* @param {*} req.body.userId - id of user
* @param {*} req.body.shortDescription - new description text
* @param {*} res
*/
exports.updateUserShortDescription = function (req, res, next) {
const data = req.body;
User.updateOne(
{ _id: data.userId },
{ $set: { shortDescription: data.text } }
)
.then((obj) => {
res.send([]);
})
.catch((error) => {
console.log("error updating short desc")
});
};
/**
* Update user's points of interest
* @param {*} req.body.userId - id of user
* @param {*} req.body.interests - list of interests
* @param {*} res
*/
exports.updateUserInterests = function (req, res, next) {
const data = req.body;
User.updateOne(
{ _id: data.userId },
{ $set: { interests: data.interests } }
)
.then((obj) => {
res.send([]);
})
.catch((error) => {
console.log("error updating interests")
});
};
/**
* Check if user is online
* @param {*} req.body._id users id
* @param {*} res contains true or false
*/
exports.isUserOnline = function (req, res, next) {
const data = req.body;
const isOnline = isUserOnlineRoom(data._id);
res.send(isOnline);
}
Source