diff --git a/src/controllers/auth.controller.js b/src/controllers/auth.controller.js index b9c605e..103ef1d 100644 --- a/src/controllers/auth.controller.js +++ b/src/controllers/auth.controller.js @@ -13,7 +13,7 @@ const AppError = require('../utils/appErrorsClass'); const catchAsyncError = require('../utils/catchAsyncErrors'); async function sendTokens(user, userType, statusCode, res) { - user.password = undefined; + user.pass = undefined; let session; try { session = await Session.createSession(user._id); @@ -21,6 +21,8 @@ async function sendTokens(user, userType, statusCode, res) { return next(new AppError('Error creating session', 500)); } + // console.log(user.role); + if (userType.toLowerCase() === 'user') { userType = user.role; } @@ -43,38 +45,15 @@ async function sendTokens(user, userType, statusCode, res) { res.cookie('refreshJWT', refreshToken, cookieOptions); res.cookie('accessJWT', accessToken, cookieOptions); - let responseObject = - userType.toLowerCase() === 'mentor' - ? { - name: user.name, - email: user.email, - about: user.about, - experience: user.experience, - identityCard: user.identityCard, - courses: user.courses, - onboarding_completed: user.onboarding_completed - } - : { - name: user.name, - email: user.email, - photo: user.photo, - about: user.about, - isEmployed: user.isEmployed, - skillsToLearn: user.skillsToLearn, - onboarding_completed: user.onboarding_completed, - skillsLearned: user.skillsLearned - }; - res.status(statusCode).json({ status: 'success', accessJWT: accessToken, refreshJWT: refreshToken, - data: { responseObject } + data: user }); } exports.signup = catchAsyncError(async (req, res, next) => { - const { type } = req.body; const signUpData = filterObj( req.body, 'name', @@ -83,57 +62,36 @@ exports.signup = catchAsyncError(async (req, res, next) => { 'passConfirm' ); - // Create a new user based on the 'type' (Mentor or User) - const newUser = await (type.toLowerCase() === 'mentor' + //TODO:only the new users and the users with non active accounts can signup + //TODO:what if the 10m are gone and the user didn't confirm his email -> if login without confirming email -> send email again + + const newUser = await (req.body.type.toLowerCase() === 'mentor' ? Mentor : User ).create(signUpData); - // Create email confirmation token and confirmation URL + //send Activation Mail to User + + //1-create email confirmation token const emailConfirmationToken = signEmailConfirmationToken( newUser._id, - type + req.body.type ); + //2-send email const emailConfirmationURL = `${req.protocol}://${req.get( 'host' )}/api/v1/auth/confirmEmail/${emailConfirmationToken}`; - // Send email with the confirmation link sendEmail( newUser.email, 'Confirm your Email (valid for 10 min)', - { - name: newUser.name, - link: emailConfirmationURL - }, + { name: newUser.name, link: emailConfirmationURL }, './templates/mailConfirmation.handlebars' ); - let responseObject = - type.toLowerCase() === 'mentor' - ? { - name: newUser.name, - email: newUser.email, - about: newUser.about, - experience: newUser.experience, - identityCard: newUser.identityCard, - courses: newUser.courses, - onboarding_completed: newUser.onboarding_completed - } - : { - name: newUser.name, - email: newUser.email, - photo: newUser.photo, - about: newUser.about, - isEmployed: newUser.isEmployed, - skillsToLearn: newUser.skillsToLearn, - onboarding_completed: newUser.onboarding_completed, - skillsLearned: newUser.skillsLearned - }; - res.status(200).json({ status: 'success', - data: responseObject + data: { newUser } }); }); @@ -148,13 +106,11 @@ exports.confirmEmail = catchAsyncError(async (req, res, next) => { const user = await (authenticationToken.userType.toLowerCase() === 'mentor' ? Mentor : User - ).findByIdAndUpdate(authenticationToken.id, { - active: true - }); + ).findById(authenticationToken.id); //update user status - // user.active = true; - // await user.save({ validateBeforeSave: false }); + user.active = true; + await user.save({ validateBeforeSave: false }); //send welcome email sendEmail( @@ -173,6 +129,7 @@ exports.confirmEmail = catchAsyncError(async (req, res, next) => { exports.login = catchAsyncError(async (req, res, next) => { const { email, pass, type } = req.body; + if (!email || !pass) return next(new AppError('Please provide email and password', 400)); @@ -192,10 +149,13 @@ exports.login = catchAsyncError(async (req, res, next) => { }); exports.logout = catchAsyncError(async (req, res, next) => { + //1- from the token get the user id const { refreshSession } = await verifyToken( req.headers.authorization?.split(' ')[2], process.env.JWT_REFRESH_SECRET ); + // console.log(refreshSession); + //2- delete the session from the database await Session.invalidateSession(refreshSession); //3- delete the cookie res.status(res.locals.statusCode || 200).json({ @@ -205,13 +165,17 @@ exports.logout = catchAsyncError(async (req, res, next) => { }); exports.forgotPassword = catchAsyncError(async (req, res, next) => { + //1- get user based on email const user = await (req.body.type.toLowerCase() === 'mentor' ? Mentor : User ).findOne({ email: req.body.email }); + //2- generate random token const resetToken = user.createPasswordResetToken(); + //3- send it to user's email const resetURL = `${process.env.CLIENT_URL}/resetPass/${resetToken}`; + sendEmail( user.email, 'Reset your password (valid for 5 min)', @@ -223,6 +187,7 @@ exports.forgotPassword = catchAsyncError(async (req, res, next) => { exports.resetPassword = catchAsyncError(async (req, res, next) => { const { token, type } = req.params; + //1- get user based on token const user = await (type.toLowerCase() === 'mentor' ? Mentor : User @@ -234,12 +199,14 @@ exports.resetPassword = catchAsyncError(async (req, res, next) => { if (!user) { return next(new AppError('The token is invalid or has expired', 404)); } + //2- if token has not expired and there is user, set new password user.pass = req.body.pass; user.passConfirm = req.body.passConfirm; //3- update changedPassAt property for the user // user.chancgedPassAt = Date.now() - 1000; await user.save({ validateBeforeSave: false }); + //4-Invalidate all user sessions await Session.InvalidateAllUserSessions(user_id); //TODO:Redirect to login page diff --git a/src/controllers/mentor.controller.js b/src/controllers/mentor.controller.js index a05cde5..8f9e9d9 100644 --- a/src/controllers/mentor.controller.js +++ b/src/controllers/mentor.controller.js @@ -31,8 +31,6 @@ exports.UpdateMe = catchAsyncError(async (req, res, next) => { 'about', 'experience', 'identityCard', - 'skillsToLearn', - 'skillsLearned', 'courses' ); @@ -42,7 +40,7 @@ exports.UpdateMe = catchAsyncError(async (req, res, next) => { }); await updatedUser.save({ runValidators: true }); - res.status(res.locals.statusCode || 200).json({ + res.status(res.locals.statusCode || 200).json({ status: 'success', data: { user: updatedUser @@ -86,7 +84,7 @@ exports.getMentorsReq = catchAsyncError(async (req, res, next) => { onboarding_completed: true }); - res.status(res.locals.statusCode || 200).json({ + res.status(res.locals.statusCode || 200).json({ status: 'success', results: mentors.length, data: { diff --git a/src/models/user.model.js b/src/models/user.model.js index 355fa7b..1f701d2 100644 --- a/src/models/user.model.js +++ b/src/models/user.model.js @@ -118,6 +118,16 @@ usersSchema.pre(/^find/, function(next) { this.select( 'photo name email isEmployed skillsToLearn skillsLearned about onboarding_completed active role' ); + this.populate({ + path: 'skillsToLearn', + select: 'name' + }).populate({ + path: 'skillsLearned', + populate: { + path: 'skill', + select: 'name' + } + }); // this.find({ active: { $ne: false } }); next(); }); diff --git a/src/server.js b/src/server.js index e5cce5a..16db8ba 100644 --- a/src/server.js +++ b/src/server.js @@ -12,41 +12,41 @@ dotenv.config({ path: path.join(__dirname, '..', 'config.env') }); const port = process.env.PORT || 3000; const server = http.createServer(app); const socketServer = new Server(server, { - cors: { - origin: '*', - methods: ['GET', 'POST'] - } + cors: { + origin: '*', + methods: ['GET', 'POST'] + } }); (async function startServer() { - await mongoConnect(); - // Start the server - server.listen(port, () => - console.log( - `Server listening on port ${port} in the ${process.env.NODE_ENV} mode` - ) - ); - // Start Socket Listener - sockets.listen(socketServer); + await mongoConnect(); + // Start the server + server.listen(port, () => + console.log( + `Server listening on port ${port} in the ${process.env.NODE_ENV} mode` + ) + ); + // Start Socket Listener + sockets.listen(socketServer); })(); //----------Exception Handling-------------// process.on('uncaughtException', err => { - console.log('UNCAUGHT EXCEPTION! 💥 Shutting down...'); - console.log(err.name, err.message); - process.exit(1); + console.log('UNCAUGHT EXCEPTION! 💥 Shutting down...'); + console.log(err.name, err.message); + process.exit(1); }); //--------------Rejection Handling------------// process.on('unhandledRejection', err => { - console.log('UNHANDLED REJECTION! 💥 Shutting down...'); - console.log(err.name, err.message); - server.close(() => { - process.exit(1); - }); -}); -process.on('SIGTERM', () => { - console.log('👋 SIGTERM RECEIVED. Shutting down gracefully'); - server.close(() => { - console.log('💥 Process terminated!'); - }); + console.log('UNHANDLED REJECTION! 💥 Shutting down...'); + console.log(err.name, err.message); + server.close(() => { + process.exit(1); + }); }); +// process.on('SIGTERM', () => { +// console.log('👋 SIGTERM RECEIVED. Shutting down gracefully'); +// server.close(() => { +// console.log('💥 Process terminated!'); +// }); +// });