can you help me look at this code to find out where I am making it wrong ?
I have my mongoose schema that am referencing child. What I want is to create a user and embed his payment details as a reference. my current result now, allows me to create anew user and the problems comes from when I want to update the user schema with payment details. If I send a request in postman, the request keep on loading until I cancel it. and what happend is if I try to get the userInfo, I will see that the payment_Id is reference in the schema but I can called .populate method on the parent schema. below is the....
export const expoSignUp = async (req, res) => {
const { firstname, lastname, middlename, username, email, phoneNo , password } = req.body
try {
const userReg = await Expo.findOne({ username })
if (userReg) {
res.status(403).json({ message: "Username already taken"})
} else {
const encryptPass = CryptoJS.AES.encrypt(password, 'secret key 123').toString();
const userData = await Expo.create({
firstname, lastname, middlename, username, email, phoneNo, password: encryptPass
});
const result = jwt.sign({firstname, lastname, middlename, username, email, phoneNo},"secrete", {expiresIn:"24"})
res.status(200).json({ userData, result })
}
} catch (err) {
res.status(500).json({ message: err.message });
}
}
export const expoSignIn = async (req, res) => {
const { password, email, username } = req.body;
try {
const userLogin = await Expo.findOne({ username })
if (!userLogin) {
res.status(401).json({ message: "username is incorrect"})
} else {
const decryptPass = CryptoJS.AES.decrypt(userLogin.password, 'secret key 123');
var originalPass = decryptPass.toString(CryptoJS.enc.Utf8);
if (password !== originalPass) {
res.status(403).json({ message: "Login credentials is incorrect" })
} else {
const result = jwt.sign({ username, email, _id: userLogin._id }, "secrete", { expiresIn: "24" });
const {password, ...others} = userLogin._doc
res.status(200).json({ others, result })
}
}
} catch (error) {
res.status(500).json({message: error.message})
}
}
export const getAllExpoUsers = async (req, res) => {
try {
const getUsers = await Expo.find()
res.status(200).json(getUsers)
} catch (err) {
res.status(err)
}
}
export const paymentInfo = async (req, res) => {
const {
userId,
tx_ref,
amount,
currency,
payment_options,
customer: {
email,
phonenumber,
fullname,
},
customizations: {
title,
description,
logo
}
} = req.body;
try {
const userPaymentInfo = await Payment.create({
tx_ref,
amount,
currency,
payment_options,
customer: {
email,
phonenumber,
fullname,
},
customizations: {
title,
description,
logo
}
})
const newPaymentInfo = await Expo.findById({ _id: userPayment })
res.status(newPaymentInfo)
} catch (error) {
res.status(500).json({message:error.message})
}
}
Related
I'm trying to get all my users from MongoDB, I've readed all documentations, but nothing helps.. What I'm trying to do is set my back-end mainController and create a get request which helps me get all users in front, so I can display them in my page. I'm still learning how to work with MongoDB, so sorry for my awful question.
mainController:
const uid = require('uid-safe')
const bcrypt = require('bcrypt')
const UserSchema = require('../schemas/UserSchema');
const { db } = require('../schemas/UserSchema');
const { default: mongoose } = require('mongoose');
module.exports = {
register: async (req, res) => {
const { username, email, password, image, city, country, firstName, lastName, phone, gender, birth } = req.body;
const userExists = await UserSchema.findOne({ username });
if (userExists) {
return res.send({ error: true, message: 'User with this username exists', data: null });
}
const emailExists = await UserSchema.findOne({ email });
if (emailExists) {
return res.send({ error: true, message: 'User with this email exists', data: null });
}
const id = await uid(7);
const hashedPass = await bcrypt.hash(password, 3);
const user = new UserSchema({
secret: id,
username,
email,
password: hashedPass,
image,
city,
country,
firstName,
lastName,
phone,
gender,
birth
});
await user.save();
return res.send({ error: false, message: 'User successfully registrated!', data: null });
},
login: async (req, res) => {
const { username, password } = req.body;
const loginUser = await UserSchema.findOne({ username });
if (loginUser) {
const passMatch = bcrypt.compare(password, loginUser.password)
if (passMatch) {
return res.send({ error: false, message: `Welcome back ${username}!`, data: loginUser })
}
return res.send({ error: true, message: 'Invalid password', data: null });
};
return res.send({ error: true, message: 'Invalid username', data: null });
},
getSingleUser: async (req, res) => {
const { secret } = req.params;
const findUser = await UserSchema.findOne({ secret });
if (findUser) {
return res.send({ error: false, message: 'User found', data: findUser });
}
return res.send({ error: true, message: 'User not found', data: null });
},
updateUser: async (req, res) => {
try {
const updateduser = await User.updateOne({ secret: req.params.secret }, { $set: req.body });
res.status(200).json(updateduser);
} catch (error) {
res.status(400).json({ message: error.message });
}
}
};
mainRouter:
const express = require('express')
const { login, register, getSingleUser, authSession, usersApi } = require("../controller/mainController")
const { loginValidate, registerValidate } = require("../middleware/authValidator")
const mainRouter = express.Router()
mainRouter.post('/register', registerValidate, register);
mainRouter.post('/login', loginValidate, login);
mainRouter.get('/user/:secret', getSingleUser)
module.exports = mainRouter;
Thank you!
I think you can use the find function.
const uid = require('uid-safe')
const bcrypt = require('bcrypt')
const UserSchema = require('../schemas/UserSchema');
const { db } = require('../schemas/UserSchema');
const { default: mongoose } = require('mongoose');
module.exports = {
register: async (req, res) => {
const { username, email, password, image, city, country, firstName, lastName, phone, gender, birth } = req.body;
const userExists = await UserSchema.findOne({ username });
if (userExists) {
return res.send({ error: true, message: 'User with this username exists', data: null });
}
const emailExists = await UserSchema.findOne({ email });
if (emailExists) {
return res.send({ error: true, message: 'User with this email exists', data: null });
}
const id = await uid(7);
const hashedPass = await bcrypt.hash(password, 3);
const user = new UserSchema({
secret: id,
username,
email,
password: hashedPass,
image,
city,
country,
firstName,
lastName,
phone,
gender,
birth
});
await user.save();
return res.send({ error: false, message: 'User successfully registrated!', data: null });
},
login: async (req, res) => {
const { username, password } = req.body;
const loginUser = await UserSchema.findOne({ username });
if (loginUser) {
const passMatch = bcrypt.compare(password, loginUser.password)
if (passMatch) {
return res.send({ error: false, message: `Welcome back ${username}!`, data: loginUser })
}
return res.send({ error: true, message: 'Invalid password', data: null });
};
return res.send({ error: true, message: 'Invalid username', data: null });
},
getSingleUser: async (req, res) => {
const { secret } = req.params;
const findUser = await UserSchema.findOne({ secret });
if (findUser) {
return res.send({ error: false, message: 'User found', data: findUser });
}
return res.send({ error: true, message: 'User not found', data: null });
},
updateUser: async (req, res) => {
try {
const updateduser = await User.updateOne({ secret: req.params.secret }, { $set: req.body });
res.status(200).json(updateduser);
} catch (error) {
res.status(400).json({ message: error.message });
}
},
getAllUsers: async(req, res) => {
try {
const allUser = await User.find({});
res.status(200).json(allUser);
} catch (error) {
res.status(400).json({ message: error.message });
}
}
};
const express = require('express')
const { login, register, getSingleUser, authSession, usersApi, getAllUsers } = require("../controller/mainController")
const { loginValidate, registerValidate } = require("../middleware/authValidator")
const mainRouter = express.Router()
mainRouter.post('/register', registerValidate, register);
mainRouter.post('/login', loginValidate, login);
mainRouter.get('/user/all', getAllUsers);
mainRouter.get('/user/:secret', getSingleUser);
module.exports = mainRouter;
I am building a Node.js project which has an advanced folder structure for future purposes.
user.register controller:
exports.register = async (req, res) => {
try {
var isValidated = await userService.validateInDatabase(req);
if (!isValidated)
return res
.status(409)
.json({ error: "Phone number or email is already registered" });
var user = await userService.create(req);
return user
} catch (e) {
console.trace(e);
return res.status(400).json({ message: e.message });
}
};
The services file code:
exports.create = async (user) => {
const hashedPassword = passwordHash.generate(user.password);
let new_user = new User({
phoneNumber,
email,
password: hashedPassword,
});
const payload = {
id: new_user._id,
};
let token = jwt.sign(payload, keys.JWToken, { expiresIn: 31556926 });
const userData = await new_user.save();
return userData;
};
exports.validateInDatabase = async (req) => {
let check_user = await User.findOne({
$or: [{ email: req.body.email }, { phoneNumber: req.body.phoneNumber }],
});
if (check_user) return false;
return true;
};
Now, whenever I send the request from the postman it says invalid password Why is that?
Not sure what's going on but every time I try to send an email i'm met with a error message. I've literally tried everything I can think of and Nothing. This is the message i'm receiving from postman when I hit the localhost:4000/api/send-mail route. I've been trying to work through this for hours now, if anyone can help that would be amazing. Thanks in advance!!!
{
"message": "Unauthorized",
"code": 401,
"response": {
"headers": {
"server": "nginx",
"date": "Mon, 21 Mar 2022 01:57:04 GMT",
"content-type": "application/json",
"content-length": "116",
"connection": "close",
"access-control-allow-origin": "https://sendgrid.api-docs.io",
"access-control-allow-methods": "POST",
"access-control-allow-headers": "Authorization, Content-Type, On-behalf-of, x-sg-elas-acl",
"access-control-max-age": "600",
"x-no-cors-reason": "https://sendgrid.com/docs/Classroom/Basics/API/cors.html",
"strict-transport-security": "max-age=600; includeSubDomains"
},
"body": {
"errors": [
{
"message": "The provided authorization grant is invalid, expired, or revoked",
"field": null,
"help": null
}
]
}
}
}
my user controllers code
const expressAsyncHandler = require("express-async-handler");
const sgMail = require("#sendgrid/mail");
const generateToken = require("../../config/token/generateToken");
const User = require("../../model/user/User");
const validateMongodbId = require("../../utils/validateMongodbID");
sgMail.setApiKey(process.env.SEND_GRID_API_KEY);
//-------------------------------------
//Register
//-------------------------------------
const userRegisterCtrl = expressAsyncHandler(async (req, res) => {
//Check if user Exist
const userExists = await User.findOne({ email: req?.body?.email });
if (userExists) throw new Error("User already exists");
try {
//Register user
const user = await User.create({
firstName: req?.body?.firstName,
lastName: req?.body?.lastName,
email: req?.body?.email,
password: req?.body?.password,
});
res.json(user);
} catch (error) {
res.json(error);
}
});
//-------------------------------
//Login user
//-------------------------------
const loginUserCtrl = expressAsyncHandler(async (req, res) => {
const { email, password } = req.body;
//check if user exists
const userFound = await User.findOne({ email });
//Check if password is match
if (userFound && (await userFound.isPasswordMatched(password))) {
res.json({
_id: userFound?._id,
firstName: userFound?.firstName,
lastName: userFound?.lastName,
email: userFound?.email,
profilePhoto: userFound?.profilePhoto,
isAdmin: userFound?.isAdmin,
token: generateToken(userFound?._id),
});
} else {
res.status(401);
throw new Error("Invalid Login Credentials");
}
});
//------------------------------
//Users
//-------------------------------
const fetchUsersCtrl = expressAsyncHandler(async (req, res) => {
console.log(req.headers);
try {
const users = await User.find({});
res.json(users);
} catch (error) {
res.json(error);
}
});
//------------------------------
//Delete user
//------------------------------
const deleteUsersCtrl = expressAsyncHandler(async (req, res) => {
const { id } = req.params;
//check if user id is valid
validateMongodbId(id);
try {
const deletedUser = await User.findByIdAndDelete(id);
res.json(deletedUser);
} catch (error) {
res.json(error);
}
});
//----------------
//user details
//----------------
const fetchUserDetailsCtrl = expressAsyncHandler(async (req, res) => {
const { id } = req.params;
//check if user id is valid
validateMongodbId(id);
try {
const user = await User.findById(id);
res.json(user);
} catch (error) {
res.json(error);
}
});
//------------------------------
//User profile
//------------------------------
const userProfileCtrl = expressAsyncHandler(async (req, res) => {
const { id } = req.params;
validateMongodbId(id);
try {
const myProfile = await User.findById(id);
res.json(myProfile);
} catch (error) {
res.json(error);
}
});
//------------------------------
//Update profile
//------------------------------
const updateUserCtrl = expressAsyncHandler(async (req, res) => {
const { _id } = req?.user;
validateMongodbId(_id);
const user = await User.findByIdAndUpdate(
_id,
{
firstName: req?.body?.firstName,
lastName: req?.body?.lastName,
email: req?.body?.email,
bio: req?.body?.bio,
},
{
new: true,
runValidators: true,
}
);
res.json(user);
});
//------------------------------
//Update password
//------------------------------
const updateUserPasswordCtrl = expressAsyncHandler(async (req, res) => {
//destructure the login user
const { _id } = req.user;
const { password } = req.body;
validateMongodbId(_id);
//Find the user by _id
const user = await User.findById(_id);
if (password) {
user.password = password;
const updatedUser = await user.save();
res.json(updatedUser);
} else {
res.json(user);
}
});
//------------------------------
//following
//------------------------------
const followingUserCtrl = expressAsyncHandler(async (req, res) => {
//1.Find the user you want to follow and update it's followers field
//2. Update the login user following field
const { followId } = req.body;
const loginUserId = req.user.id;
//find the target user and check if the login Id exists
const targetUser = await User.findById(followId);
const alreadyFollowing = targetUser?.followers?.find(
(user) => user?.toString() === loginUserId.toString()
);
if (alreadyFollowing) throw new Error("You are already folliwig this user");
//1. Find the user you want to follow and update it's followers field
await User.findByIdAndUpdate(
followId,
{
$push: { followers: loginUserId },
},
{ new: true }
);
//2. Update the login user following field
await User.findByIdAndUpdate(
loginUserId,
{
$push: { following: followId },
isFollowing: true,
},
{ new: true }
);
res.json("You are now following this user");
});
//------------------------------
//unfollow
//------------------------------
const unfollowUserCtrl = expressAsyncHandler(async (req, res) => {
const { unFollowId } = req.body;
const loginUserId = req.user.id;
await User.findByIdAndUpdate(
unFollowId,
{
$pull: { followers: loginUserId },
isFollowing: false,
},
{ new: true }
);
await User.findByIdAndUpdate(
loginUserId,
{
$pull: { following: unFollowId },
},
{ new: true }
);
res.json("You have successfully unfollowed this user");
});
//------------------------------
//Block Users
//------------------------------
const blockUserCtrl = expressAsyncHandler(async (req, res) => {
const { id } = req.params;
validateMongodbId(id);
const user = await User.findByIdAndUpdate(
id,
{
isBlocked: true,
},
{ new: true }
);
res.json(user);
});
//------------------------------
//Block user
//------------------------------
const unBlockUserCtrl = expressAsyncHandler(async (req, res) => {
const { id } = req.params;
validateMongodbId(id);
const user = await User.findByIdAndUpdate(
id,
{
isBlocked: false,
},
{ new: true }
);
res.json(user);
});
//------------------------------
// Account Verification - Send email
//------------------------------
const generateVerificationTokenCtrl = expressAsyncHandler(async (req, res) => {
try {
//build your message
const msg = {
to: "MizTamaraAndrea#gmail.com",
from: "Tamara18_1985#msn.com",
subject: "My first Node js email sending",
text: "I hope this goes through",
};
await sgMail.send(msg);
res.json("Email sent");
} catch (error) {
res.json(error);
}
});
module.exports = {
generateVerificationTokenCtrl,
userRegisterCtrl,
loginUserCtrl,
fetchUsersCtrl,
deleteUsersCtrl,
fetchUserDetailsCtrl,
userProfileCtrl,
updateUserCtrl,
updateUserPasswordCtrl,
followingUserCtrl,
unfollowUserCtrl,
blockUserCtrl,
unBlockUserCtrl,
};
My user Routes Code
const express = require("express");
const {
userRegisterCtrl,
loginUserCtrl,
fetchUsersCtrl,
deleteUsersCtrl,
fetchUserDetailsCtrl,
userProfileCtrl,
updateUserCtrl,
updateUserPasswordCtrl,
followingUserCtrl,
unfollowUserCtrl,
blockUserCtrl,
unBlockUserCtrl,
generateVerificationTokenCtrl,
} = require("../../controllers/users/usersCtrl");
const authMiddleware = require("../../middleware/auth/authMiddleware");
const userRoutes = express.Router();
userRoutes.post("/register", userRegisterCtrl);
userRoutes.post("/login", loginUserCtrl);
userRoutes.post("/send-mail", generateVerificationTokenCtrl);
userRoutes.get("/", authMiddleware, fetchUsersCtrl);
userRoutes.put("/password", authMiddleware, updateUserPasswordCtrl);
userRoutes.put("/follow", authMiddleware, followingUserCtrl);
userRoutes.put("/unfollow", authMiddleware, unfollowUserCtrl);
userRoutes.put("/block-user/:id", authMiddleware, blockUserCtrl);
userRoutes.put("/unblock-user/:id", authMiddleware, unBlockUserCtrl);
userRoutes.get("/profile/:id", authMiddleware, userProfileCtrl);
userRoutes.put("/:id", authMiddleware, updateUserCtrl);
userRoutes.delete("/:id", deleteUsersCtrl);
userRoutes.get("/:id", fetchUserDetailsCtrl);
module.exports = userRoutes;
You have one of two problems here. Either, your API key does not have the permission to send messages, or has been deleted. Create yourself a new API key that has permission to send emails and try again.
Or, I see you appear to be trying to send from an msn.com email address. In order to send from a third party domain like that, you need to have set up single sender verification. This lets SendGrid know that you do have access to that email address and that you are not trying to spoof someone else's.
(Note that when you ship to production, we recommend you use your own domain and authenticate that domain with SendGrid, which will give you much better deliverability.)
I am having issues posting to send a verification email. I am using ReactJS front end NodeJS backend and MongoDB database. I am running npm run dev to make sure my backend server is running when testing in Postman and gives me an error Cannot Post /api/verify-email I am not getting any other error code so having a hard time trouble shooting. I am using Send Grid API to send the verification email.
verifyEmailRoute.js
import { ObjectId } from 'mongodb';
import jwt from 'jsonwebtoken';
import { getDbConnection } from '../src/db';
export const verifyEmailRoute = {
path: 'http://localhost:8080/api/verify-email',
method: 'put',
handler: async (req, res) => {
const { verificationString } = req.body;
const db = await getDbConnection('react-auth-db');
const result = await db.collection('users').findOne({ verificationString });
if (!result) return res.status(401).json({ message: 'The email verification code is incorrect' });
const { _id: id, email, info } = result;
await db.collection('users').updateOne({ _id: ObjectId(id) }, { $set: { isVerified: true } });
jwt.sign({ id, email, isVerified: true, info }, process.env.JWT_SECRET, { expiresIn: '2d' }, (err, token) => {
if (err) {
return res.status(500).json(err);
}
res.status(200).json({ token });
});
},
};
emailVerificationLandingPage.js
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useToken } from '../src/auth/useToken';
import { EmailVerificationSuccess } from './EmailVerificationSuccess';
import { EmailVerificationFail } from './EmailVerificationFail';
export const EmailVerificationLandingPage = () => {
const [isLoading, setIsLoading] = useState(true);
const [isSuccess, setIsSuccess] = useState(false);
const [user, setUser] = useState(null);
const { verificationString } = useParams();
const [token, setToken] = useToken();
useEffect(() => {
const loadVerification = async () => {
try {
const response = await fetch.put('http://localhost:8080/api/verify-email', { verificationString });
const { token } = response.data;
setToken(token);
console.log(token);
setIsSuccess(true);
setIsLoading(false);
} catch (error) {
setIsSuccess(false);
setIsLoading(false);
}
}
loadVerification();
}, [setToken, verificationString]);
console.log(token);
if (isLoading) return <p>Loading...</p>;
if (!isSuccess) return <EmailVerificationFail />
return <EmailVerificationSuccess />
}
sendEmail.js
import sendgrid from '#sendgrid/mail';
sendgrid.setApiKey(process.env.SENDGRID_API_KEY);
export const sendEmail = ({ to, from, subject, text, html }) => {
const msg = { to, from, subject, text, html };
return sendgrid.send(msg);
}
signUpRoute.js
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { v4 as uuid } from 'uuid';
import { getDbConnection } from '../src/db';
import { sendEmail } from '../src/util/sendEmail';
export const signUpRoute = {
path: '/api/signup',
method: 'post',
handler: async (req, res) => {
const { email, password } = req.body;
// Make sure there's no existing user with that email - no verification yet
const db = getDbConnection('react-auth-db');
const user = await db.collection('users').findOne({ email });
if (user) {
console.log("found user", user)
return res.sendStatus(409).json(user); // 409 is the "conflict" error code
}
// Generate the salt first
const salt = uuid();
const pepper = process.env.PEPPER_STRING;
// Encrypt the password
const passwordHash = await bcrypt.hash(salt + password + pepper, 10);
const verificationString = uuid();
// Store email and password hash in database (i.e. create user) - you'll also want to get the id
const startingInfo = {
firstName: '',
lastName: '',
dob: '',
}
const result = await db.collection('users').insertOne({
email,
isVerified: false,
verificationString,
passwordHash,
salt,
info: startingInfo,
});
const { insertedId } = result;
try {
await sendEmail({
to: email,
from: 'mdolly01#gmail.com',
subject: 'Welcome to Tool Right Please verify your email',
text: `
Thanks for signing up! To verify your email, you just need to click the link below:
http://localhost:3000/verify-email/${verificationString}
`
});
} catch (e) {
console.log(e);
throw new Error(e);
}
jwt.sign({
id: insertedId,
isVerified: false,
email, // Do NOT send the salt back to the user
info: startingInfo,
},
process.env.JWT_SECRET,
{
expiresIn: '2d',
},
(err, token) => {
if (err) {
return res.status(500).send(err);
}
return res.status(200).json({token});
});
},
};
I was trying to separate the logic of my back-end server into route/controller/service,
but one problem is when I try to catch error in service layer, I will return error, but how can I determine if it's error and return 404 status in my controller layer ?
Here's the code
Service layer
const register = async(name, email, password) => {
const newUser = new User({
username: name,
email: email,
password: CryptoJS.AES.encrypt(password, key).toString(),
});
try{
const savedUser = await newUser.save();
return savedUser
} catch (err){
return err
}
};
Controller layer
const register = (req,res) => {
const { name, email, password } = req.body
const user = UserService.register(name,email,password);
if(how to determine here?){
res.status(201).json(user);
}
}
You could return an object in your Service Layer instead of an User or Error object:
const register = async(name, email, password) => {
const newUser = new User({
username: name,
email: email,
password: CryptoJS.AES.encrypt(password, key).toString(),
});
try{
const savedUser = await newUser.save();
return { user: savedUser, error: null }
} catch (error){
return { error, user: null }
}
};
In your Controller Layer you would then do something like this:
const register = (req,res) => {
const { name, email, password } = req.body
const { user, error } = UserService.register(name,email,password);
if(error){
res.status(500).json({ user, error: error.message });
} else {
res.status(200).json({ user, error })
}
}
return the save promise and handle errors in your controller
serivce:
const register = async(name, email, password) => {
const newUser = new User({
username: name,
email: email,
password: CryptoJS.AES.encrypt(password, key).toString(),
});
return newUser.save();
};
controller:
const register = async (req,res) => {
const { name, email, password } = req.body
try {
const user = await UserService.register(name,email,password);
res.status(201).json(user);
} catch(error) {
// handle error here
}
}