import UserModel from "../model/User.model.js"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import ENV from "../config.js"; // Middleware export async function verifyUser(req, res, next) { try { const { username } = req.method == "GET" ? req.query : req.body; // Check if user exists let exist = await UserModel.findOne({ username }); if (!exist) return res.status(404).send({ error: "Can't find User" }); next(); } catch (error) { return res.status(404).send({ error: "Authentication Error" }); } } /** POST: http://localhost:8080/api/register * @param : { "username" : "example123", "password" : "admin123", "email": "example@gmail.com", "profile": "" } */ export async function register(req, res) { try { const { username, password, profile, email } = req.body; // Checking existing Username const existUsername = new Promise((resolve, reject) => { UserModel.findOne({ username }, function (err, user) { if (err) reject(new Error(err)); if (user) reject({ error: "Username already exists!" }); resolve(); }); }); // Checking existing Email const existEmail = new Promise((resolve, reject) => { UserModel.findOne({ email }, function (err, email) { if (err) reject(new Error(err)); if (email) reject({ error: "An account with that email address already exists!" }); resolve(); }); }); Promise.all([existUsername, existEmail]) .then(() => { if (password) { bcrypt .hash(password, 10) .then((hashedPassword) => { const user = new UserModel({ username, password: hashedPassword, profile: profile || "", email, }); // return save result as a response user .save() .then(async (result) => { const user = await UserModel.findOne({ username: username }); // create jwt token const token = jwt.sign( { userId: user._id, username: user.username, admin: false, }, ENV.JWT_SECRET, { expiresIn: "24h" } ); res.status(201).send({ msg: "User Registered Successfully", username: user.username, token, }); }) .catch((error) => res.status(500).send({ error })); }) .catch((error) => { return res.status(500).send({ error: "Enable to hash password", }); }); } }) .catch((error) => { return res.status(500).send({ error }); }); } catch (error) { return res.status(500).send(error); } } /** POST: http://localhost:8080/api/login * @param: { "username" : "example123", "password" : "admin123" } */ export async function login(req, res) { const { username, password } = req.body; try { UserModel.findOne({ username }) .then((user) => { bcrypt .compare(password, user.password) .then((passwordCheck) => { if (!passwordCheck) return res.status(400).send({ error: "Incorrect username or password!" }); // create jwt token const token = jwt.sign( { userId: user._id, username: user.username, admin: user.admin, }, ENV.JWT_SECRET, { expiresIn: "24h" } ); return res.status(200).send({ msg: "Login Successful...!", username: user.username, token, }); }) .catch((error) => { return res.status(400).send({ error: "Password does not Match" }); }); }) .catch((error) => { return res.status(404).send({ error: "Username not Found" }); }); } catch (error) { return res.status(500).send({ error }); } } export async function getUser(req, res) { const { username } = req.params; try { if (!username) return res.status(401).send({ error: "Invalid Username" }); UserModel.findOne({ username }, function (err, user) { if (err) return res.status(500).send({ err }); if (!user) return res.status(501).send({ error: "Couldn't find the User" }); const { password, ...rest } = Object.assign({}, user.toJSON()); return res.status(201).send(rest); }); } catch (err) { return res.status(404).send({ error: "Cannot find User Data" }); } } /** PUT: http://localhost:8080/api/updateuser * . * @param: { "header" : "<token>" } body: { firstName: '', address : '', profile : '' } */ export async function updateUser(req, res) { try { const { userId } = req.user; if (userId) { const body = req.body; // update the data UserModel.updateOne({ _id: userId }, body, function (err, data) { try { if (err) throw err; return res.status(201).send({ msg: "Record Updated...!" }); } catch (error) { return res.status(401).send({ error }); } }); } else { return res.status(401).send({ error: "User Not Found...!" }); } } catch (error) { return res.status(401).send({ error }); } } /** * POST /userlist * This DOES NOT return emails and passwords * @param {*} req * @param {*} res * @returns * * body: {userIdList: []} */ export const GetUserList = async (req, res) => { try { const { userIdList } = req.body; const users = await UserModel.find( { _id: { $in: userIdList } }, { password: 0, email: 0 } ); const userHash = users.map((obj) => [obj._id.toString(), obj]); return res.status(201).send({ userList: Array.from(userHash.entries()) }); } catch (error) { return res.status(401).send({ error }); } }; /** * GET /search * This endpoint OMITS the password and email fields * @param {*} req * @param {*} res * @returns * * query: {query: string} */ export const Search = async (req, res) => { try { const { searchQuery } = req.query; if (searchQuery === undefined || searchQuery.length === 0) { throw new Error("Please provide a valid query!"); } const usersWithMatchingUsername = await UserModel.find( { username: { $regex: `^${searchQuery}` } }, { password: 0, email: 0 } ); const usersWithMatchingName = await UserModel.find( { $or: [ { firstName: { $regex: `^${searchQuery}`, $options: "i" } }, { lastName: { $regex: `^${searchQuery}`, $options: "i" } }, ], }, { password: 0, email: 0 } ); const resultHash = new Map( [...usersWithMatchingUsername, ...usersWithMatchingName].map((obj) => [ obj._id.toString(), obj, ]) ); return res.status(201).send({ result: Array.from(resultHash.entries()) }); } catch (error) { return res.status(401).send({ error: error.message }); } };