i'm working on a web app in which a user can create an address when logged in, how can i get the current logged in user address which was created by the user
these my address route
const router = require("express").Router();
const Address = require("../models/address");
const User = require("../models/user");
const jwt = require("jsonwebtoken");
router.get('/addresses', (req, res, next) => {
let token = req.headers.token; //token
jwt.verify(token, 'secretkey', (err, decoded) => {
if (err) return res.status(401).json({
title: 'unauthorized'
})
//token is valid
Address.findOne({ _id: decoded.addressId }, (err, user) => {
if (err) return console.log(err)
return res.status(200).json({
title: 'adress grabbed',
address: {
streetAddress: user.streetAddress,
fullName: user.fullName
}
})
})
})
})
i get unauthorised any time i want to get the address of the current user
my db schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const AddressSchema = new Schema({
user: { type: Schema.Types.ObjectId, ref: "User" },
country: String,
fullName: String,
streetAddress: String,
city: String,
state: String,
zipCode: Number,
phoneNumber: String,
deliverInstructions: String,
securityCode: String
});
module.exports = mongoose.model("Address", AddressSchema);
my auth route to get details of current user
//grabbing user info
router.get('/auth/user', (req, res, next) => {
let token = req.headers.token; //token
jwt.verify(token, 'secretkey', (err, decoded) => {
if (err) return res.status(401).json({
title: 'unauthorized'
})
//token is valid
User.findOne({ _id: decoded.userId }, (err, user) => {
if (err) return console.log(err)
return res.status(200).json({
title: 'user grabbed',
user: {
email: user.email,
name: user.name
}
})
})
})
})```
please how can i go about it
Related
This is a rest API that fetches movie data, similar to Netflix. I've created a login route for new users and registered users, however, when I test the API on postman and attempt to log in as a user I get an error message:
Errors:
Expect Output:
I want the user to log in successfully
The Problem:
I can't find anything wrong with the code despite reference errors
Question:
What kind of data and hash arguments do I require? What is causing the problem?
Code:
source code
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
},
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'
}]
});
// HASH THE PASSWORD BEFORE SAVING THE USER MODEL TO THE DATABASE
userSchema.statics.hashPassword = (password) => {
return bcrypt.hashSync(password, 10);
};
// COMPARE THE HASHED PASSWORD IN THE DATABASE WITH THE ONE PROVIDED BY THE USER WHEN THEY LOG IN
userSchema.methods.validatePassword = function(password) {
return bcrypt.compareSync(password, this.Password);
};
// SCHEMA FOR DIRECTORS
let directorSchema = mongoose.Schema({
Name: {
type: String,
required: true
},
Bio: {
type: String,
required: true
},
Birth: {
type: String,
required: true
}
})
/// SCHEMA FOR GENRES
let genreSchema = mongoose.Schema({
Name: {
type: String,
required: true
},
Description: {
type: String,
required: true
}
})
// CREATE MODELS FROM SCHEMAS
let Movie = mongoose.model('Movie', movieSchema);
let User = mongoose.model('User', userSchema);
let Director = mongoose.model('Director', directorSchema);
let Genre = mongoose.model('Genre', genreSchema);
// EXPORT MODELS
module.exports.Movie = Movie;
module.exports.User = User;
module.exports.Director = Director;
module.exports.Genre = Genre;
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.'
});
}
if (!user.validatePassword(password)) {
console.log('incorrect password');
return callback(null, false, {
message: 'Incorrect password.'
});
}
console.log('finished');
return callback(null, user);
});
}));
passport.use(new JWTStrategy({
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(),
secretOrKey: 'your_jwt_secret'
}, async(jwtPayload, callback) => {
try {
const user = await Users.findById(jwtPayload._id);
return callback(null, user);
} catch (error) {
return callback(error);
}
}));
index.js
const express = require('express'),
morgan = require('morgan'),
bodyParser = require('body-parser'),
uuid = require('uuid'),
mongoose = require('mongoose'),
Models = require('./models/models'),
{
check,
validationResult
} = require('express-validator');
const app = express();
// SCHEMAS
const Movies = Models.Movie;
const Users = Models.User;
const Genres = Models.Genre;
const Directors = Models.Director;
mongoose.connect('mongodb://localhost:27017/myMovies', {
useNewUrlParser: true,
useUnifiedTopology: true
}); // DATABASE Option 1: Local DB
// mongoose.connect(process.env.CONNECTION_URI, { useNewUrlParser: true, dbName: "myMoviesDB", useUnifiedTopology: true }); // REMOTE DATABASE Option 2: Remote DB
// MIDDLEWARE
app.use(bodyParser.json());
// LOGGING MIDDLEWARE
const cors = require('cors');
// ALL ORIGINS ARE ALLOWED TO ACCESS THE API ENDPOINTS
app.use(cors());
// CETAIN ORIGINS ARE ALLOWED TO ACCESS THE API ENDPOINTS:
// let allowedOrigins = ['http://localhost:8080', 'http://testsite.com']
// app.use(cors({
// origin: (origin, callback) => {
// if (!origin) return callback(null, true); // i don't understand this line
// if (allowedOrigins.indexOf(origin) === -1){ // specific origin not in allowedOrigins list
// let message = 'The CORS policy for this application doesn’t allow access from origin ' + origin;
// return callback(new Error(message), false);
// }
// return callback(null, true);
// }
// }));
// ERROR HANDLING MIDDLEWARE
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// INPUT VALIDATION
const userValidation = [
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').isEmail()
];
// INPUT VALIDATION FOR MOVIES
const movieValidation = [
check('Title', 'Title is required').not().isEmpty(),
check('Description', 'Description is required').not().isEmpty(),
check('Genre', 'Genre is required').not().isEmpty(),
check('Director', 'Director is required').not().isEmpty(),
check('Actors', 'Actors is required').not().isEmpty(),
check('ImageURL', 'ImageURL is required').not().isEmpty(),
check('Featured', 'Featured is required').not().isEmpty()
];
//AUTHENTICATION
require('./auth')(app);
const passport = require('passport');
const {
Passport
} = require('passport');
require('./passport');
// LOGS REQUESTS TO THE CONSOLE
app.use(morgan('common'));
app.use(express.static('public'));
//ROUTING / HOME
app.get("/", (req, res) => {
res.send('Hello there! Welcome to myMovies');
})
// LIST OF ALL MOVIES
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}`);
});
});
// ADD User
app.post('/users', userValidation, (req, res) => {
//check for validation errors
let errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({
errors: errors.array()
});
}
let hashedPassword = Users.hashPassword(req.body.Password);
Users.findOne({
Username: req.body.Username
})
.then((user) => {
if (user) {
return res.status(400).send(`Username ${req.body.Username} already taken.`);
} else {
Users
.create({
Username: req.body.Username,
Password: hashedPassword,
Email: req.body.Email,
Birthday: req.body.Birthday
})
.then((new_user) => {
res.status(201).json(new_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) => {
// ONLY ALLOWS USERS TO DELETE THEIR OWN ACCOUNT
if (req.user.Username !== req.params.Username) {
res.status(403).json('You are not authorized to delete this user.');
} else {
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 USER INFO BY 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 USER INFO
app.put('/users/:Username', passport.authenticate('jwt', {
session: false
}), userValidation, (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', (req, res) => {
// Movies.find()
// .then((movies) => {
// res.status(201).json(movies);
// })
// .catch((error) => {
// console.error(error);
// res.status(500).send(`Error: ${error}`);
// });
// });
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);
});
});
// ADD MOVIE TO FAVORITES LIST OF USER
app.post('/users/:Username/movies/:MovieID',
passport.authenticate({
session: false
}),
(req, res) => {
if (req.user.Username !== req.params.Username) {
res.status(403).json('Not allowed to add movie to another user\'s favorites list');
} else {
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, updated_User) => {
if (err) {
console.error(err);
res.status(500).send(`Error:${err}`)
} else {
res.json(updated_User)
}
});
}
});
// REMOVE MOVIE FROM FAVORITES
app.delete('/users/:Username/movies/:MovieID', passport.authenticate('jwt', {
session: false
}), (req, res) => {
// ONLY ALLOQWS USERS TO REMOVE MOVIES FROM THEIR OWN FAVORITES
if (req.user.Username != req.params.Username) {
res.status(403).json('Not allowed to remove movie from another user\'s favorites list');
} else {
Users.findOneAndUpdate({
Username: req.params.Username
}, {
pull: {
FavoriteMovies: req.params.MovieID
}
}, {
new: true
}) // THIS LINE ENSURES THAT THE UPDATED DOCUMENT IS RETURNED
.then((updatedUser) => {
res.status(200).send(`Favorite movie removed from ${updatedUser.Username}`);
})
.catch((err) => {
console.error(err);
res.status(500).send(`Error: ${err}`);
});
}
});
// DIRECTORS
// RETURN A LIST OF ALL DIRECTORS BY NAME (BIO, BIRTHYEAR)
app.get('/directors/:Name', passport.authenticate('jwt', {
session: false
}), (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: INTERNAL 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);
})
})
// RETURNS GENRE BY 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);
})
})
// DOCUMENTATION ROUTE
app.get('/documentation', (req, res) => {
res.sendFile('public/documentation.html');
});
// SERVER & HEROKU
const port = process.env.PORT || 8081;
app.listen(port, '0.0.0.0', () => {
console.log(`Listening on Port ${port}`);
});
Research:
I've searched and read through most of the common questions related to the issue, but none helped.
Question #1
Question #2
Thank you in advance for taking the time to answer my question.
I have three models: user, teacher, student. The users, teachers, students collections appear in the database. But everything is saved in the users collection. How to set up in the code below that student is saved in the students collection, not in users.
model
const mongoose = require('mongoose');
extend = require('mongoose-extend-schema');
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {
type: String,
trim: true,
required: true,
maxLength: 32
},
surname: {
type: String,
trim: true,
required: true,
maxLength: 32
},
email: {
type: String,
unique: true,
trim: true,
required: true,
lowercase: true
},
initials: String
});
const studentSchema = extend(userSchema, {
teachers: []
});
const teacherSchema = extend(userSchema, {
isActiveTutor: {
type: Boolean,
default: false
}
})
const User = mongoose.model('User', userSchema);
const Student = mongoose.model('Student', studentSchema);
const Teacher = mongoose.model('Teacher', teacherSchema);
module.exports = {
User,
Student,
Teacher
}
controllers
const User = require('../models/user');
const Student = require('../models/user');
const Teacher = require('../models/user');
const jwt = require('jsonwebtoken');
const nodemailer = require('nodemailer');
const expressJwt = require('express-jwt');
module.exports.signup = (req, res) => {
const {name, surname, email, password, initials, role} = req.body;
Student.User.findOne({email}).exec((err, student) => {
if (student) {
return res.status(400).json({
error: "Email is taken"
})
}
}
}
module.exports.accountActivationStudent = (req, res) => {
const {token} = req.body;
if(token) {
jwt.verify(token, process.env.JWT_ACCOUNT_ACTIVATION, function(err, decoded) {
if(err) {
console.log('JWT VERIFY IN ACCOUNT ACTIVATION ERROR', err);
return res.status(401).json({
error: 'Expired link. Signup again'
})
}
const {name, surname, email, password} = jwt.decode(token);
const student = new Student.User ({name, surname, email, password});
student.save((err, student) => {
if(err) {
console.log('SAVE Student IN ACCOUNT ACTIVATION ERROR', err);
return res.status(401).json({
error: 'Error saving student in database. Try signup again'
});
}
return res.json({
message: 'Signup success. Please signin'
});
});
});
} else {
return res.json({
message: 'Something went wrong. Try again'
})
}
};
new Student is your schema
try to like this
router.post('/', async (req, res) => {
const _studentSave = await new Student({ name, surname, email, password, initials, role });
const saveProcess = await _studentSave.save();
try{
res.json(saveProcess)
}catch(error){
throw error
}
})
According to the error-trace the error occurs in the "validate" method, but as far as i see it my compare call is correct. I hope someone can explain to me why it happens anyways.
POST /user/register 500 23.312 ms - 2235
Error: data and hash arguments required
at Object.compare
at model.user_schema.methods.validate
The mongoose model:
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const salty = 10;
const user_schema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: false,
minlength: 3,
maxlength: 32
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
});
user_schema.pre('save', (next) => {
// if the password is not changed, there is no need to hash it again
if (!this.isModified('password')) return next();
// hash the user password
bcrypt.hash(this.password, salty, (err, hash) => {
if (err) return next(err);
this.password = hash;
return next();
});
});
user_schema.methods.validate = (claim, callback) => {
// compare the password to the existing hash from the database
bcrypt.compare(claim, this.password, (err, is_match) => {
if (err) return callback(err);
return callback(null, is_match);
});
}
module.exports = mongoose.model('user', user_schema);
The router with the create call:
router.post('/register', (req, res, next) => {
let new_user = {
name: req.body.name,
email: req.body.email,
password: req.body.password
};
user_model.create(new_user, (err, user) => {
if (err) return next(err);
res.send(user);
});
});
i am creating a REST API for my users, and i used express-validator for the validation before creating the user in the database.. but when i chain my middleware together in the router.py file it gives the error Error: Route.post() requires a callback function but got a [object Undefined]
i imported my middleware and controller from thier respective files.
here is the code in my router.py
const express = require('express');
const authMiddleware = require('../middlewares/authMiddleware');
const authController = require('../controllers/authController');
const router = express.Router();
router.post(
'/signup',
authMiddleware.verifySignUpInit(),
authMiddleware.verifySignUp,
authController.signup
);
module.exports = router;
in my middleware file i added this..
const jwt = require('jsonwebtoken');
const { authentication } = require('../config');
const { User } = require('../models');
const { body } = require('express-validator');
const verifySignUpInit = () => {
return [
body('email', 'email is required').exists().normalizeEmail().isEmail(),
body('phone', 'phone is required').exists().isInt(),
body('first_name', 'first_name is required').exists().isString(),
body('last_name', 'last_name is required').exists().isString(),
body('password', 'password is required').exists(),
];
};
const verifySignUp = (req, res, next) => {
const { email, phone, password } = req.body;
User.findOne({
email,
}).exec((err, user) => {
if (err) {
res.status(500).json({
status: 'error',
message: err,
});
}
if (user) {
return res.status(400).json({
status: 'failed',
message: 'Email Provided Already Exists',
});
}
});
User.findOne({
phone,
}).exec((err, user) => {
if (err) {
res.status(500).json({
status: 'error',
message: err,
});
}
if (user) {
return res.status(400).json({
status: 'failed',
message: 'Phone Provided Already Exists',
});
}
});
const password_is_valid = authentication.passwordSchema.validate(password);
if (!password_is_valid) {
return res.status(400).json({
status: 'failed',
message: 'password requirements not met',
});
}
next();
};
module.exports = {
verifySignUpInit,
verifySignUp,
};
and finally in my controller i have this..
const config = require('../config');
const db = require('../models');
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
const { validationResult } = require('express-validator');
const { User, Role } = db;
const { token_expiry_time, refresh_token_expiry_time } = config.authentication;
const signUp = (req, res) => {
const { email, phone, first_name, last_name, password } = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
status: 'failed',
message: errors.array(),
});
}
bcrypt.hash(password, 8, (err, hash) => {
if (err) {
return res.status(500).json({
status: 'error',
message: err,
});
}
const user = new User({
first_name: first_name,
last_name: last_name,
email: email,
phone: phone,
password: hash,
});
Role.findOne({ name: 'is_user' }, (err, role) => {
if (err) {
res.status(500).json({
status: 'error',
message: err,
});
return;
}
user.roles = [role._id];
user.save((err) => {
if (err) {
return res.status(500).json({
status: 'error',
message: err,
});
}
return res.status(201).json({
status: 'success',
data: {
user,
},
});
});
});
});
};
module.exports = {
signUp,
};
i cant tell what i am doing wrong :(
authController.signup
should be:
authController.signUp
You have to use the same capitalization for the property name you exported.
I am new to MERN stack development and trying the JWT authentication. During this I am facing that my server is not working they crashed every time.
Yesterday It was working but today It's not working. Now they are showing this error.
This is error showing on console
MissingSchemaError: Schema hasn't been registered for model "users".
Here is my Schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
avatar: {
type: String
},
date: {
type: Date,
default: Date.now
}
});
const User = mongoose.model('users', UserSchema);
module.exports = User;
This code is in the routes folder - user.js file
// user.js
const express = require('express');
const router = express.Router();
const gravatar = require('gravatar');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const passport = require ('passport');
const validateRegisterInput = require('../validation/register');
const validateLoginInput = require('../validation/login');
const User = require('../models/User');
//Register Post Router
router.post('/register', function(req, res){
const {errors, isValid} = validateRegisterInput(req.body);
if(!isValid){
return res.status(400).json(errors);
}
User.findOne({
email: req.body.email
}).then(user => {
if(user){
return res.status(400).json({
email: 'Email already exists'
});
}
else {
const avatar = gravatar.url(req.body.email, {
s: '200',
r: 'pg',
d: 'mm'
});
const newUser = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password,
avatar
});
bcrypt.genSalt(10, (err, salt) => {
if(err)
console.error('There was an error', err);
else{
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err)
console.error('There was an error', err);
else{
newUser.password = hash;
newUser
.save()
.then(user => {
res.json(user)
});
}
});
}
});
}
});
});
//Login Post Router
router.post('/login', (req, ress) => {
const {errors, isValid} = validateLoginInput(req.body);
if(isValid){
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
User.findOne({email})
.then(user => {
if(!user) {
errors.email = 'User not found'
return res.status(404).json(errors);
}
bcrypt.compare(password, user.password)
.then(isMatch => {
if(isMatch){
const payload = {
id: user.id,
name: user.name,
avatar: user.avatar
}
jwt.sign(payload, 'secret', {
expiresIn: 3600
}, (err, token) => {
if(err)
console.error('There is some error in token', err);
else{
res.json({
success: true,
token: `Bearer ${token}`
});
}
});
}
else{
errors.password = 'Incorrect Password';
return
res.status(400).json(errors);
}
});
});
});
router.get('/me', passport.authenticate('jwt', {session: false}), (req, res) => {
return res.json({
id: req.user.id,
name: req.user.name,
email: req.user.email
});
});
module.exports = router;