Can someone help me to understand and give me code review of my small todos APP, why my code in backend is bad? Also give me a answers for some of my questions, please:
- Where my code is bad?
- Where do I use bad combinations with callback and
async
/await
?
And show me how it should look in a best code practices, please.
I Attached link for my app on github: https://github.com/datagramm/ThinkMobiles
I was learning a lot of techniques and approaches but I don't know what I do wrong :(
dashboard controller
const User = require("../../models/User");
const Helpers = require('../dashboard/helpers')
const getAllUsers = async (req,res) => {
await User
.find()
.skip(5 * (req.query.page - 1))
.sort({[req.query.sortValue] : req.query.sortDirection})
.limit(5)
.exec(async (err, users) => {
if (err) return res.status(500).json(err)
const completeUsers = await Helpers.getCurrentEventForAllUsers(users)
User.count().exec( (err,count) => {
if (err) return res.status(500).json(err)
res.status(200).json({
users:completeUsers,
accessDenied: req.body.accessDenied,
currentUser: req.body.currentUserName,
page: +req.query.page,
pages: Math.ceil(count / 5)
});
})
})
}
const getCurrentUser = (req, res) => {
User.findOne({id: req.params.id})
.exec((err, user) => {
if (err) return res.status(404).json(err)
res.status(200).json(user)
})
}
const getCurrentUserEvents = (req,res) => {
const skip = 5 * (req.query.page - 1);
const limit = 5;
const sort = `events.${req.query.sortValue}`
const id = req.query.currentUser.id
User.aggregate([
{ $match: {id: parseInt(id)}},
{ $project: {
id: 1,
firstName: 1,
lastName: 1,
phoneNumber: 1,
mail: 1,
eventCount: 1,
firstEventDate: 1,
events: {$slice: ['$events', skip, limit]}
}},
{ $unwind: '$events' },
{ $sort: {
[sort]: parseInt(req.query.sortDirection)
}}
],function (err, user){
if (err) return res.status(500).json(err)
console.log(user)
User.findOne({id: id})
.exec((err, userCount) => {
if (err) return res.status(500).json(err)
res.status(200).json({
user: user,
page: +req.query.page,
pages: Math.ceil(userCount.events.length / 5)
})
})
} )
}
const pushUser = (req,res) => {
User.find().exec(async (err, users) => {
if (err) return res.status(500).json(err)
let id;
id = users.length
if (!users) id = 1
const newUser = await new User({id: id, firstName: req.body.firstName, lastName: req.body.lastName, phoneNumber: req.body.phoneNumber, mail: req.body.mail, eventCount: 0, firstEventDate: 0}).save()
res.status(201).json(newUser);
})
}
const pushEventDate = async (req, res) => {
let {
startEventYear,
startEventMonth,
startEventDay,
endEventYear,
endEventMonth,
endEventDay
} = req.body.event;
let {id, firstName, lastName, phone, mail} = req.body.currentUser;
if (!isNaN(+startEventMonth) && !isNaN(+startEventYear) && !isNaN(+startEventDay)
&& !isNaN(+endEventMonth) && !isNaN(+endEventYear) && !isNaN(+endEventDay)
) {
if (startEventMonth.length === 1) startEventMonth = '0' + startEventMonth;
if (startEventYear.length === 1) startEventYear = '0' + startEventYear;
if (startEventDay.length === 1) startEventDay = '0' + startEventDay;
if (endEventMonth.length === 1) endEventMonth = '0' + endEventMonth;
if (endEventYear.length === 1) endEventYear = '0' + endEventYear;
if (endEventDay.length === 1) endEventDay = '0' + endEventDay;
if (startEventMonth.length === 2 && startEventYear.length === 4 && startEventDay.length === 2 &&
endEventMonth.length === 2 && endEventYear.length === 4 && endEventDay.length === 2
) {
const currentStarEventDate = startEventYear.toString() + '/' + startEventMonth.toString() + '/' + startEventDay.toString();
const currentEndEventDate = endEventYear.toString() + '/' + endEventMonth.toString() + '/' + endEventDay.toString();
const user = await User.findOne({
id: id,
firstName: firstName,
lastName: lastName,
phoneNumber: phone,
mail: mail
})
if (user) {
const checkIs = user.events.some(event => {
if (Helpers.intercept(new Date(`${event.startEventDate}`), new Date(`${event.endEventDate}`),
new Date(`${currentStarEventDate}`),
new Date(`${currentEndEventDate}`))) {
return true;
}
})
if (checkIs) res.send({error: true});
else {
let id;
id = user.events.length
if (!user.events) id = 1
const event = {
id: id,
tittle: req.body.event.tittle,
description: req.body.event.description,
startEventDate: currentStarEventDate,
endEventDate: currentEndEventDate,
}
await User.findOneAndUpdate({
firstName: req.body.currentUser.firstName,
lastName: req.body.currentUser.lastName,
phoneNumber: req.body.currentUser.phone,
mail: req.body.currentUser.mail,
}, {$inc: {eventCount: 1}, $push: {events: event}}, {new: true}).then( (user) => {
if (user) {
const now = new Date().setHours(0,0,0,0);
let closest = {
date: Infinity,
closest: null,
}
user.events.forEach( (event) => {
const date = new Date(event.startEventDate);
if (date >= now && (date < new Date(closest.date) || date < closest.date)) {
closest = {
date: date,
closest: event.startEventDate
}
}
});
User.findOneAndUpdate({
firstName: req.body.currentUser.firstName,
lastName: req.body.currentUser.lastName,
phoneNumber: req.body.currentUser.phone,
mail: req.body.currentUser.mail,
},{firstEventDate:closest.closest}, {new: true}).then(async(user) =>{
if (user) res.send(event);
})
}
})
}
}
}
}
}
module.exports = {getAllUsers, getCurrentUserEvents, pushUser, pushEventDate, getCurrentUser}
dashboard helpers functions
const getCurrentEventDate = (user) => {
const currentDate = new Date().setHours(0,0,0,0);
let closest = {
date: Infinity,
closest: null,
}
user.events.forEach((event) => {
const date = new Date(event.startEventDate);
if (date >= currentDate && (date < new Date(closest.date) || date < closest.date)) {
closest = {
date: date,
closest: event.startEventDate
}
}
});
user.firstEventDate = closest.closest;
return user
}
const getCurrentEventForAllUsers = async (users) => {
let completeUsers = []
await users.forEach(user => {
completeUsers.push(getCurrentEventDate(user))
})
return completeUsers;
}
const intercept = (start1, end1, start2, end2) => {
return (Math.max(0, Math.min(end2, end1) - Math.max(start1, start2) + 1)) > 0
}
module.exports = {getCurrentEventForAllUsers, intercept}
user authorization controller
const bcrypt = require('bcrypt');
const Client = require("../models/Client");
const Session = require("../models/Session");
const registerUser = (req, res) => {
const {username, password, mail} = req.body;
bcrypt.hash(password, 10).then((hash) => {
new Client({
login: username,
mail: mail,
password: hash,
}).save().then( () => {
res.status(200).json({success: true, err: false});
}).catch( err => {
if (err) res.status(500).json({success: false, err: err});
});
});
};
const login = async (req, res, next) => {
const {username, password} = req.body;
const user = await Client.findOne({login: username});
if (!user) {
res.status(401).json({err: true, message: 'User not found'})
return
}
const dbPassword = user.password;
bcrypt.compare(password, dbPassword).then( async (match) => {
if (!match) res.status(401).json({err: true, message: 'Wrong password'});
else {
req.body.userName = await user.login
next()
}
});
}
const logout = (req,res) => {
const refreshTokenId = req.cookies["refreshTokenId"];
Session.findOneAndDelete({"refreshToken.id": refreshTokenId});
res.clearCookie('refreshTokenId');
res.clearCookie('accessTokenId');
res.status(200).json({logout: true})
}
module.exports = {registerUser, login, logout}
user session controller
const Session = require('../models/Session')
const {sign} = require('jsonwebtoken')
const uuid = require("uuid");
const createSession = (req, res) => {
const accessTokenId = sign({login: req.body.userName}, process.env.SECRET_JWT, {expiresIn: '10s'})
const refreshTokenId = uuid.v4();
new Session({
userName: req.body.userName,
refreshToken: {
id: refreshTokenId,
timeExp: '60d',
}
}).save();
res.cookie('accessTokenId', accessTokenId,{ httpOnly: true, sameSite: 'none', secure: true },);
res.cookie('refreshTokenId', refreshTokenId,{ maxAge: 5184000000, httpOnly: true, sameSite: 'none',secure: true},);
res.status(200).json({err: false})
}
module.exports = {createSession}
session validation middleware
const {sign, verify} = require('jsonwebtoken')
const uuid = require('uuid')
const Session = require('../models/Session');
const validateSession = async (req,res,next) =>{
const accessTokenId = req.cookies["accessTokenId"];
const refreshTokenId = req.cookies["refreshTokenId"]
try {
const access = verify(accessTokenId, process.env.SECRET_JWT)
if(access) {
const session = await Session.findOne({"refreshToken.id": refreshTokenId})
req.body.accessDenied = true;
const userName = session.userName
req.body.currentUserName = userName
next()
}
}
catch (err){
if (err){
const session = await Session.findOne({"refreshToken.id": refreshTokenId})
if (!session) res.status(401).json({users:false, accessDenied: false})
else {
const userName = session.userName
req.body.currentUserName = userName
const newRefreshTokenId = uuid.v4();
await Session.findOneAndUpdate({"refreshToken.id": refreshTokenId},
{
refreshToken: {id: newRefreshTokenId, timeExp: '60d'},
}, {new: true}).then(() =>{
const newAccessTokenId = sign({login: session.userName },process.env.SECRET_JWT, {expiresIn: '900s'} )
res.cookie('accessTokenId', newAccessTokenId, { httpOnly: true, sameSite: 'none', secure: true},);
res.cookie('refreshTokenId', newRefreshTokenId, {maxAge: 5184000000, httpOnly: true, sameSite: 'none', secure: true},);
req.body.accessDenied = true;
next()
})
}
}
}
}
module.exports = {validateSession};
login
function reviewed then please expand the code here. Please embed the code to be reviewed directly in the question. Links to code hosted on third-party sites are permissible, but the most relevant excerpts must be embedded in the question itself. \$\endgroup\$