Error: data and salt argument required - unable to successfully add users

Viewed 16

Fellow Devs. I know this is a common issue and trust me I've searched and tried to find a solution but to no avail. At least yet.

I'm currently building a rest API that retrieves movie data, basically Netflix and through this API you can register an account. Now, this is where the problem arises for me.

The Problem: When I test my API on Postman and try to add/POST a user I get an error message: " Error: data and salt arguments required" followed by more error messages which I post an image down below

Expected Output: I want to be able to add a user and successfully test it on Postman

Question: What exactly is the problem and how can I go about fixing this?

I've looked at the reference errors and everything seems to look ok but clearly not.

Any help would be appreciated.

Index.js

const express = require('express'),
  bodyParser = require('body-parser'),
  uuid = require('uuid');
const morgan = require('morgan');
const app = express();
const mongoose = require('mongoose');
const Models = require('./models/models');
const passport = require('passport');
const cors = require('cors');
const {
  check,
  validationResult
} = require('express-validator');

app.use(cors());

// SCHEMAS 
const Movies = Models.Movie;
const Users = Models.User;
const Genres = Models.Genre;
const Directors = Models.Director;

// const URI = 'mongodb://localhost:27017/movie-api'; // Database Option 1: Local DB
mongoose.connect(process.env.CONNECTION_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});
app.use(bodyParser.json());

//LOGS REQUESTS
app.use(morgan('common'))

app.use(express.static(__dirname + '/public'));
app.use(bodyParser.urlencoded({
  extended: true
}));

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});


//AUTHENTICATION
const auth = require('./auth')(app);
require('./passport');


//ROUTING
//HOME
app.get("/", (req, res) => {
  res.send('Hello there! Welcome to myMovies');
})

// USERS DATA
app.get('/users', passport.authenticate('jwt', {
  session: false
}), (req, res) => {
  Users.find()
    .then((allUsers) => {
      res.status(201).json(allUsers);
    })
    .catch((err) => {
      console.error(err);
      res.status(500).send(`Error: ${err}`);
    });
});

// Create User
app.post('/users', [
    check('Username', 'Username is required').isLength({
      min: 5
    }), // sets minimum value of 5 characters
    check('Username', 'Username contains non alphanumeric characters - not allowed.').isAlphanumeric(), // specifies tnat a field can only contain letters and numbers
    check('Password', ' Password is required').not().isEmpty(),
    check('Email', 'Email does not appear to be valid').isEmail(),
  ],
  (req, res) => {

    // check the validation object for errors
    const validationErrors = validationResult(req);
    if (!validationErrors.isEmpty()) {

      return res.status(422).json({
        errors: validationErrors.array()
      });
    }
    const hashedPassword = Users.hashPassword(req.body.Passsword);
    Users.findOne({
      Username: req.body.Username
    }).then((user) => { // Searches to see if user with the requested username alreadt exists
      if (user) {
        return res.status(400).send(`${req.body.Username} already exists!`); // if the user is found, send a response that it already exists
      } else {
        Users.create({
            Username: req.body.Username,
            Password: hashedPassword,
            Email: req.body.Email,
            Birthday: req.body.Birthday
          })
          .then((user) => {
            res.status(201).json(user)
          }).catch((error) => {
            console.error(error);
            res.status(500).send(`Error: ${error}`);
          })
      }
    }).catch((error) => {
      console.error(error);
      res.status(500).send(`Error: ${error}`)
    });
  });


// REMOVE USER

app.delete('/users/:Username', passport.authenticate('jwt', {
  session: false
}), (req, res) => {
  Users.findOneAndRemove({
      Username: req.params.Username
    })
    .then((user) => {
      if (!user) {
        res.status(400).send(`${req.params.Username} was not found!`);
      } else {
        res.status(200).send(`${req.params.Username} was deleted`);
      }
    }).catch((err) => {
      console.error(err);
      res.status(500).send(`Error: ${err}`);
    });
});


// GET based on username
app.get('/users/:Username', passport.authenticate('jwt', {
  session: false
}), (req, res) => {
  Users.findOne({
    Username: req.params.Username
  }).then((user) => {
    res.json(user);
  }).catch((err) => {
    console.error(err);
    res.status(500).send('Error: ' + err);
  });
});

// UPDATE: change user's username
app.put('/users/:Username', [
    check('Username', 'Username is required').isLength({
      min: 5
    }),
    check('Username', 'Username contains non alphanumeric characters - not allowed.').isAlphanumeric(),
    check('Password', 'Password is required').not().isEmpty(),
    check('Email', 'Email does not appear to be valid').isEmpty(),
  ],
  passport.authenticate('jwt', {
    session: false
  }),

  (req, res) => {

    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(422).json({
        errors: errors.array()
      });
    }
    Users.findOneAndUpdate({
        Username: req.params.Username
      }, {
        $set: {
          Username: req.body.Username,
          Password: req.body.Password,
          Email: req.body.Email,
          Birthday: req.body.Birthday

        }
      }, {
        new: true
      }, // This line ensures that the updated document is returned
      (err, updateUser) => {
        if (err) {
          console.error(err);
          res.status(500).send(`Error: ${err}`);
        } else {
          res.json(updateUser); // Return the updated document

        }
      })
  });


// MOVIES

// GET: fetches a list of all movies
app.get('/movies', passport.authenticate('jwt', {
  session: false
}), (req, res) => {
  Movies.find()
    .then((movies) => {
      res.status(201).json(movies);
    })
    .catch((error) => {
      console.error(error);
      res.status(500).send(`Error: ${error}`);
    });
});

// GET: fetches movies by title
app.get('/movies/:Title', passport.authenticate('jwt', {
  sesson: false
}), (req, res) => {
  Movies.findOne({
      Title: req.params.Title
    })
    .then((movie) => {
      res.json(movie);
    }).catch((err) => {
      console.error(err);
      res.status(500).send('Error: ' + err);
    });
});

// UPDATE: add favorite movies to users
app.post('/users/:Username/movies/:MovieID', [
    check('Username', 'Username is required').isLength({
      min: 5
    }),
    check('Username', 'Username contains non alphanumeric characters - not allowed').isAlphanumeric(),
    check('MovieID', 'MovieID is required').not().isEmpty(),
    check('MovieID', 'MovieID does not appear to be valid').isMongoId(),
  ],
  passport.authenticate({
    session: false
  }),
  (req, res) => {
    Users.findOneAndUpdate({
        Username: req.params.Username
      }, {
        $addToSet: {
          FavoriteMovies: req.params.MovieID
        }
      }, {
        $push: {
          FavoriteMovies: req.params.MovieID
        }
      }, {
        new: true
      }, // This line ensures that the updated document is returned
      (err, updatedUser) => {
        if (err) {
          console.error(err);
          res.status(500).send(`Error:${err}`)
        } else {
          res.json(updatedUser)
        }
      });
  });

// DELETE: remove favorite movie from users
app.delete('/users/:Username/movies/:MovieID', passport.authenticate('jwt', {
    session: false
  }),
  (req, res) => {
    Users.findOneAndDelete({
      FavoriteMovies: req.params.MovieID
    }).then((movie) => {
      if (!movie) {
        res.status(400).send(req.params.MovieID + ' movie was not found!');
      } else {
        res.status(201).send(req.params.MovieID + ' movie was successfully deleted!');
      }
    }).catch((err) => {
      console.error(err);
      res.status(500).send('Error:' + err)
    });
  });


// DIRECTORS

// GET: returns all directors
app.get('/directors', (req, res) => {
  Directors.find().then((director) => {
    res.status(201).json(director);
  }).catch((err) => {
    console.error(err);
    res.status(500).send('Error', +err);
  })
})


// GET: return director by name
app.get('/directors/:Name', (req, res) => {
  Directors.findOne({
    Name: req.params.Name
  }).then((director) => {
    res.json(director);
  }).catch((err) => {
    console.error(err);
    res.status(500).send('Error: ' + err); // 500 is server error
  })
})

// GENRES

// GET: returns all genres
app.get('/genres', (req, res) => {
  Genres.find().then((genre) => {
    res.status(201).json(genre);
  }).catch((err) => {
    console.error(err);
    res.status(400).send('Error: ' + err);
  })
})

// GET: returns Genre based on name
app.get('/genres/:Name', (req, res) => {
  Genres.findOne({
    Name: req.params.Name
  }).then((genreName) => {
    res.status(201).json(genreName)
  }).catch((err) => {
    console.error(err);
    res.status(500).send('Error: ' + err);
  })
})


app.get('/documentation', (req, res) => {
  res.sendFile('public/documentation.html', {
    root: __dirname
  });
});


// Server & Heroku 
const port = process.env.PORT || 8081;
app.listen(port, '0.0.0.0', () => {
  console.log(`Listening on Port ${port}`);
});

passport.js

const passport = require('passport'),
  LocalStrategy = require('passport-local').Strategy,
  Models = require('./models/models'),
  passportJWT = require('passport-jwt');

let Users = Models.User,
  JWTStrategy = passportJWT.Strategy,
  ExtractJWT = passportJWT.ExtractJwt;

passport.use(new LocalStrategy({
  usernameField: 'Username',
  passwordField: 'Password'
}, (username, password, callback) => {
  console.log(`${username}  ${password}`);
  Users.findOne({
    Username: username
  }, (error, user) => {
    if (error) {
      console.log(error);
      return callback(error);
    }

    if (!user) {
      console.log('incorrect username');
      return callback(null, false, {
        message: 'Incorrect username or password.'
      });
    }

    console.log('finished');
    return callback(null, user);
  });
}));

passport.use(new JWTStrategy({
  jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
  secretOrKey: 'your_jwt_secret'
}, (jwtPayload, callback) => {
  return Users.findById(jwtPayload._id)
    .then((user) => {
      return callback(null, user);
    })
    .catch((error) => {
      return callback(error)
    });
}));

auth.js

const jwtSecret = 'your_jwt_secret'; // This has to be the same key used in the JWTStrategy
const {
  check,
  validationResult
} = require('express-validator');
const jwt = require('jsonwebtoken'),
  passport = require('passport');

require('./passport'); // Your local passport file


let generateJWTToken = (user) => {
  return jwt.sign(user, jwtSecret, {
    subject: user.Username, // This is the username you’re encoding in the JWT
    expiresIn: '7d', // This specifies that the token will expire in 7 days
    algorithm: 'HS256' // This is the algorithm used to “sign” or encode the values of the JWT
  });
}


/* POST login. */
module.exports = (router) => {
  router.post('/login', [
      check('Username', 'Username is required').isLength({
        min: 5
      }),
      check('Username', 'Username contains non alphanumeric characters - allowed').isAlphanumeric(),
      check('Password', 'Password is required').not().isEmpty(),
    ],
    (req, res) => {
      const validatonErrors = validationResult(req);

      if (!validatonErrors.isEmpty()) {
        return res.status(422).json({
          errors: validatonErrors.array()
        })
      }
      passport.authenticate('local', {
        session: false
      }, (error, user, info) => {
        if (error || !user) {
          return res.status(400).json({
            message: 'Something is not right',
            user: user
          });
        }
        req.login(user, {
          session: false
        }, (error) => {
          if (error) {
            res.send(error);
          }
          let token = generateJWTToken(user.toJSON());
          return res.json({
            user,
            token
          });
        });
      })(req, res);
    });
}

model.js

const mongoose = require('mongoose');
const bcrypt = require('bcrypt');

let movieSchema = mongoose.Schema({
  Title: {
    type: String,
    required: true
  },
  Description: {
    type: String,
    required: true
  },
  Genre: {
    Name: String,
    Description: String
  },
  Director: {
    Name: String,
    Bio: String,
    Birth: String,
    Death: String
  },
  Actors: [String],
  ImageURL: String,
  Featured: Boolean
});

let userSchema = mongoose.Schema({
  Username: {
    type: String,
    required: true
  },
  Password: {
    type: String,
    required: true
  },
  Email: {
    type: String,
    required: true
  },
  Birthday: Date,
  FavoriteMovies: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Movie'
  }]
});

userSchema.statics.hashPassword = (password) => { // HASHES PASSWORD
  return bcrypt.hashSync(password, 10);
};

userSchema.methods.validatePassword = function validatePassword(password) {
  return bcrypt.compareSync(password, this.Password);
};
let directorSchema = mongoose.Schema({
  Name: {
    type: String,
    required: true
  },
  Bio: {
    type: String,
    required: true
  },
  Birth: {
    type: String,
    required: true
  }
})


let genreSchema = mongoose.Schema({
  Name: {
    type: String,
    required: true
  },
  Description: {
    type: String,
    required: true
  }
})

let Movie = mongoose.model('Movie', movieSchema);
let User = mongoose.model('User', userSchema);
let Director = mongoose.model('Director', directorSchema);
let Genre = mongoose.model('Genre', genreSchema);

module.exports.Movie = Movie;
module.exports.User = User;
module.exports.Director = Director;
module.exports.Genre = Genre;

Package.json

Package.json

Debug Console

Debug Console

0 Answers
Related