Handling login using promises
This is missing the point. It is not about promises. You are right that if done correctly, you'll get a nice flat structure, but not if you inline all your code. This would be true if you weren't using promises as well. What you should do is split your code into smaller building blocks, and the nice structure will follow.

Also, be wary of your variable names:

// check if password matches
if (compareResult) {


Why not rename "compareResult" "passwordIsCorrect" and get rid of the comment?

// find the user
User.findOne({


That comment is useless.

Basically all the comments can be removed. Try to explain yourself with code instead, and only comment what can't be explained with code.

Just a quick example of the type of refactoring I would do:

routes.login = (req, res) =&gt; {
    let inpEmail = req.body.email.toLowerCase();
    let inpPassword = req.body.password;

    User.findOne({email: inpEmail})
        .exec()
        .then((user) =&gt; {
            if(user.isLocked &amp;&amp; Date.now &lt; user.lockExpiry){
                return blabla();
            }else if(!user.emailVerified){
                return requireEmailVerification();
            }else{
                return login(user, inpPassword);
            }
        })
        .then(() =&gt; {
            // Probably res.send() here
        })
        .catch((err) =&gt; {
            //some logic here
        });
};

function login(user, pw){
    return bcrypt.compare(pw, user.passwordHash)
        .then(passwordIsCorrect =&gt; {
            if(passwordIsCorrect){
                return setLastLoginAndDoSomeLogic(user);
            }

            return incrementLoginFailureCountAndDoSomeLogic(user);
        });
}

function setLastLoginAndDoSomeLogic(user){
    return setLastLogin(user)
        .then(() =&gt; {
            //some logic here
        })
        .catch((err) =&gt; {
            //some logic here
        });
}

function incrementLoginFailureCountAndDoSomeLogic(user){
    return setLoginFailureCount(user, user.loginFailureCount + 1)
        .then(() =&gt; {
            //some logic here
        })
        .catch((err) =&gt; {
            //some logic here
        });
}