rachel
rachel

Reputation: 59

findOne is undefined mongodb

After creating validators in a separate file to check if an email exists in mongodb users.findOne no longer works. How do I fix this issue? it was originally in auth.js and working correctly now it's in validators.js. The project is so big I'm having trouble figuring out why it's not working. I noticed that I am still able to save users info to DB on sign-up because the save function is still in auth.js but not able to find users.

index.js file

require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const authRouter = require('./routes/admin/auth')

const app = express();
//route handler request, response
// req receives info
// res sends info back
app.use(bodyParser.urlencoded({ extended: true }));

mongoose.connect('mongodb://localhost:27017/userDB', { useNewUrlParser: true });

app.use(authRouter);

app.listen(3000, () => {
  console.log('Listening');
});

auth.js file

const express = require('express');
const { check, validationResult } = require('express-validator');
const bcrypt = require('bcrypt');
const saltRounds = 10;
const mongoose = require('mongoose');
const signupTemplate = require('../../views/admin/auth/signup');
const signinTemplate = require('../../views/admin/auth/signin');
const {
  requireEmail,
  requirePassword,
  requirePasswordConfirmation,
} = require('./validators');

const router = express.Router();

const userSchema = new mongoose.Schema({
  email: String,
  password: String,
  passwordConfirmation: String,
});

const User = new mongoose.model('User', userSchema);

router.get('/signup', (req, res) => {
  res.send(signupTemplate({ req }));
});

router.post(
  '/signup',
  [requireEmail, requirePassword, requirePasswordConfirmation],
  async (req, res) => {
    bcrypt.hash(req.body.password, saltRounds, async (err, hash) => {
      const newUser = new User({
        email: req.body.email,
        password: hash,
      });
      const errors = validationResult(req);
      console.log(errors);
      const { email, password, passwordConfirmation } = req.body;
      //saves users to db
      newUser.save((err) => {
        if (err) {
          console.log(err);
        } else {
          console.log('success');
          res.send('Account created!!!');
        }
      });
    });
  }
);
module.exports = router;

validators.js

(The file from which the code that's having errors was moved from file auth.js to validators.js.)

const { check } = require('express-validator');

const User = require('./auth');

module.exports = {
  requireEmail: check('email')
    .trim()
    .normalizeEmail()
    .isEmail()
    .withMessage('Must be a valid email')
    //code below is what is having the issue
    .custom(async (email) => {
      const existingUser = User.findOne({ email: email });
      if (existingUser) {
        throw new Error('Email in use');
      }
    }),
  requirePassword: check('password')
    .trim()
    .isLength({ min: 4, max: 20 })
    .withMessage('Must be between 4 and 20 characters'),
  requirePasswordConfirmation: check('passwordConfirmation')
    .trim()
    .isLength({ min: 4, max: 20 })
    .withMessage('Must be between 4 and 20 characters')
    .custom(async (passwordConfirmation, { req }) => {
      if (passwordConfirmation !== req.body.password) {
        throw new Error('Passwords must match');
      }
    }),
};

signup.js

Used to render HTML on screen.

const layout = require('../layout');
const { getError } = require('../../utils')


    module.exports = ({ errors }) => {
        return layout({
          content: `
          <div>
              <form method="POST">
                <input name="email" placeholder="email" />
                ${getError(errors, 'email')}
                <input name="password" placeholder="password" />
                ${getError(errors, 'password')}
                <input name="passwordConfirmation" placeholder="confirm password" />
                ${getError(errors, 'passwordConfirmation')}
                <button>Sign Up</button>
              </form>
          </div>
        `
      });
    };

Upvotes: 1

Views: 123

Answers (1)

acdcjunior
acdcjunior

Reputation: 135742

You are not exporting User in auth.js. You could just do it like:

router.User = User; // added this line
module.exports = router;

Which you would use like: const { User } = require('./auth');

A better way

But the likely cleanest approach is just to move the User declaration to get rid of the cycle you now have between the auth.js and validation.js files. E.g.,

// user.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  email: String,
  password: String,
  passwordConfirmation: String,
});

const User = new mongoose.model('User', userSchema);

module.exports = User;

And use it like in both auth.js and validators.js:

const User = require('./user');

Upvotes: 1

Related Questions