2

I am making a social networking site with MERN Stack. Firstly, the users could simply sign up with email and password but that meant anyone can use any random email and possibly spam the DB. So I turned to this video https://www.youtube.com/watch?v=76tKpVbjhu8 and implemented it to ask for email verification.

Now the problem is even if a user registers and didn't verify his account another user can't create an account with the same email as it says user already exists. This means if some prankster registered an account with: name: John Doe email: johndoe@gmail.com password: 123456

And couldn't verify his account, if someday the real johndoe comes and tries to register an account, he won't be able to register it as it already exists.

Is there anyway for the user to be automatically deleted if it failed to verify his account during the set time.

Here's my User Schema

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
    name: {
        type: String,
        required: true
    },
    posts: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Post'
        }
    ],
    profile: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Profile'
    },
    email: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        type: String,
        required: true
    },
    isVerified: {
        type: Boolean,
        default: false
    },
    date: {
        type: Date,
        default: Date.now
    }
});

const User = mongoose.model('User', UserSchema);
module.exports = User;

Register route

//  @route    POST api/users
// @desc       REgister a user
// @access    Public
router.post(
    '/',
    [
        check('name', 'Please add name')
            .not()
            .isEmpty(),
        check('email', 'Please include a valid email').isEmail(),
        check(
            'password',
            'Please enter a password with 6 or more characters'
        ).isLength({ min: 6 })
    ],
    async (req, res) => {
        const errors = validationResult(req);
        if (!errors.isEmpty()) {
            return res.status(400).json({ errors: errors.array() });
        }
        const { name, email, password } = req.body;

        try {
            let user = await User.findOne({ email });
            if (user) {
                return res.status(400).json({ msg: 'User already exists' });
            }
            user = new User({
                name,
                email,
                password
            });

            const salt = await bcrypt.genSalt(10);
            user.password = await bcrypt.hash(password, salt);
            await user.save();

            const payload = {
                user: {
                    id: user.id
                }
            };
            let profile = new Profile({
                user: user.id
            });
            await profile.save();
            user.profile = profile.id;
            await user.save();
            jwt.sign(
                payload,
                config.get('jwtSecret'),
                {
                    expiresIn: 36000
                },
                (err, token) => {
                    if (err) throw err;
                    const url = `http://localhost:3000/confirmation/${token}`;

                    transporter.sendMail({
                        to: user.email,
                        subject: 'Confirm Email',
                        html: `Please click this link to confirm your email for signing up for MERN Blog <a href="${url}">${url}</a>`
                    });

                    res.json({
                        msg:
                            'Thanks for signing up! An email has been sent to your email for verification. Go ahead and verify your account'
                    });
                }
            );
        } catch (err) {
            console.log(err.message);
            res.status(500).send('Server Error');
        }
    }
);

module.exports = router;

Confirmation route


router.post('/confirmation', async (req, res) => {
    const token = req.body.token;

    //Check if not token
    if (!token) {
        return res.status(401).json({ msg: 'No token, authorization denied' });
    }

    try {
        const decoded = jwt.verify(token, config.get('jwtSecret'));
        const user = await User.findByIdAndUpdate(decoded.user.id, {
            isVerified: true
        });
        const payload = {
            user: {
                id: user.id
            }
        };
        jwt.sign(
            payload,
            config.get('jwtSecret'),
            {
                expiresIn: 36000
            },
            (err, token) => {
                if (err) throw err;
                res.json({ token });
            }
        );
    } catch (err) {
        res.status(401).json({ msg: 'Token is not valid' });
    }
});

  • You need to automate this. First you need to create an api to remove unverified users within a period, and schedule a job to call this api. – SuleymanSah Nov 20 '19 at 13:32
  • I have provided a cursory answer, are you looking for a code example or just a general strategy? – Lewis Clarke Nov 21 '19 at 10:13

1 Answers1

0

I think the best way of doing this would be to check the accounts creation date/time, if it has been over X amount of days/weeks && the email is not verified, then dispatch a delete action.

Lewis Clarke
  • 69
  • 2
  • 12
  • that's pretty straight forward. So there isn't really any mongoose way for this. Of course a code sample will be much helpful! Thanks – Ashtuosh Agrawal Nov 21 '19 at 15:41
  • did you solve the problem? I am having a similar problem. If you have a script in charge that, for example, every 24 hours check the links that have expired but some links expire minutes after that check is made and a user wants to register with the same email, as would be done in that case ? – JulianProg Jun 23 '20 at 22:31