0
\$\begingroup\$

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:

  1. Where my code is bad?
  2. 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};
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Welcome to Code Review! Please edit your question so that the title describes the purpose of the code, rather than its mechanism. We really need to understand the motivational context to give good reviews. Please see How to get the best value out of Code Review: Asking Questions for guidance on writing good question titles. \$\endgroup\$ Jun 27 at 17:09
  • \$\begingroup\$ Also, if you want more code than that 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\$ Jun 27 at 17:10
  • \$\begingroup\$ Good evening, i need full project code review of my backend part, not only one function showed here :) \$\endgroup\$ Jun 27 at 22:09

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.