Reputation: 57
Whenever I login to my app this is what it says, and my user profile does not get my details. I rechecked everything but cant seem to find the problem. I am still learning MERN and I am stuck here for a few days.
This is my User Model:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
passwordHash: {
type: String,
required: true,
},
phone: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
default: false,
},
street: {
type: String,
default: ''
},
apartment: {
type: String,
default: ''
},
zip :{
type: String,
default: ''
},
city: {
type: String,
default: ''
},
country: {
type: String,
default: ''
}
});
userSchema.virtual('id').get(function () {
return this._id.toHexString();
});
userSchema.set('toJSON', {
virtuals: true,
});
exports.User = mongoose.model('User', userSchema);
exports.userSchema = userSchema;
This is my api for the user:
const {User} = require('../models/user');
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
router.get(`/`, async (req, res) =>{
const userList = await User.find().select('-passwordHash');
if(!userList) {
res.status(500).json({success: false})
}
res.send(userList);
})
router.get('/:id', async(req,res)=>{
const user = await User.findById(req.params.id).select('-passwordHash');
if(!user) {
res.status(500).json({message: 'The user with the given ID was not found.'})
}
res.status(200).send(user);
})
router.post('/', async (req,res)=>{
let user = new User({
name: req.body.name,
email: req.body.email,
passwordHash: bcrypt.hashSync(req.body.password, 10),
phone: req.body.phone,
isAdmin: req.body.isAdmin,
street: req.body.street,
apartment: req.body.apartment,
zip: req.body.zip,
city: req.body.city,
country: req.body.country,
})
user = await user.save();
if(!user)
return res.status(400).send('the user cannot be created!')
res.send(user);
})
router.put('/:id',async (req, res)=> {
const userExist = await User.findById(req.params.id);
let newPassword
if(req.body.password) {
newPassword = bcrypt.hashSync(req.body.password, 10)
} else {
newPassword = userExist.passwordHash;
}
const user = await User.findByIdAndUpdate(
req.params.id,
{
name: req.body.name,
email: req.body.email,
passwordHash: newPassword,
phone: req.body.phone,
isAdmin: req.body.isAdmin,
street: req.body.street,
apartment: req.body.apartment,
zip: req.body.zip,
city: req.body.city,
country: req.body.country,
},
{ new: true}
)
if(!user)
return res.status(400).send('the user cannot be created!')
res.send(user);
})
router.post('/login', async (req,res) => {
const user = await User.findOne({email: req.body.email})
const secret = process.env.secret;
if(!user) {
return res.status(400).send('The user not found');
}
if(user && bcrypt.compareSync(req.body.password, user.passwordHash)) {
const token = jwt.sign(
{
userId: user.id,
isAdmin: user.isAdmin
},
secret,
{expiresIn : '1d'}
)
res.status(200).send({user: user.email , token: token})
} else {
res.status(400).send('password is wrong!');
}
})
router.post('/register', async (req,res)=>{
let user = new User({
name: req.body.name,
email: req.body.email,
passwordHash: bcrypt.hashSync(req.body.password, 10),
phone: req.body.phone,
isAdmin: req.body.isAdmin,
street: req.body.street,
apartment: req.body.apartment,
zip: req.body.zip,
city: req.body.city,
country: req.body.country,
})
user = await user.save();
if(!user)
return res.status(400).send('the user cannot be created!')
res.send(user);
})
router.delete('/:id', (req, res)=>{
User.findByIdAndRemove(req.params.id).then(user =>{
if(user) {
return res.status(200).json({success: true, message: 'the user is deleted!'})
} else {
return res.status(404).json({success: false , message: "user not found!"})
}
}).catch(err=>{
return res.status(500).json({success: false, error: err})
})
})
router.get(`/get/count`, async (req, res) =>{
const userCount = await User.countDocuments((count) => count)
if(!userCount) {
res.status(500).json({success: false})
}
res.send({
userCount: userCount
});
})
module.exports =router;
This is my login.js
import React, { useEffect, useContext, useState } from "react";
import { View, Text, StyleSheet, Button } from "react-native";
import FormContainer from "../../Shared/Form/FormContainer";
import Input from "../../Shared/Form/Input";
import Error from "../../Shared/Error";
import EasyButton from "../../Shared/StyledComponents/EasyButton";
// Context
import AuthGlobal from "../../Context/store/AuthGlobal";
import { loginUser } from "../../Context/actions/Auth.actions";
const Login = (props) => {
const context = useContext(AuthGlobal);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
useEffect(() => {
if (context.stateUser.isAuthenticated === true) {
props.navigation.navigate("User Profile");
}
}, [context.stateUser.isAuthenticated]);
const handleSubmit = () => {
const user = {
email,
password,
};
if (email === "" || password === "") {
setError("Please fill in your credentials");
} else {
loginUser(user, context.dispatch);
}
};
return (
<FormContainer title={"Login"}>
<Input
placeholder={"Enter Email"}
name={"email"}
id={"email"}
value={email}
onChangeText={(text) => setEmail(text.toLowerCase())}
/>
<Input
placeholder={"Enter Password"}
name={"password"}
id={"password"}
secureTextEntry={true}
value={password}
onChangeText={(text) => setPassword(text)}
/>
<View style={styles.buttonGroup}>
{error ? <Error message={error} /> : null}
<EasyButton large primary onPress={() => handleSubmit()}>
<Text style={{ color: "white" }}>Login</Text>
</EasyButton>
</View>
<View style={[{ marginTop: 40 }, styles.buttonGroup]}>
<Text style={styles.middleText}>Don't have an account yet?</Text>
<EasyButton
large
secondary
onPress={() => props.navigation.navigate("Register")}>
<Text style={{ color: "white" }}>Register</Text>
</EasyButton>
</View>
</FormContainer>
);
};
const styles = StyleSheet.create({
buttonGroup: {
width: "80%",
alignItems: "center",
},
middleText: {
marginBottom: 20,
alignSelf: "center",
},
});
export default Login;
This is my user profile where user email, phone and orders is supposed to show.
import React, { useContext, useState, useCallback } from 'react';
import { View, Text, ScrollView, Button, StyleSheet } from 'react-native';
import { Container } from "native-base"
import { useFocusEffect } from "@react-navigation/native"
import AsyncStorage from "@react-native-community/async-storage"
import OrderCard from "../../Shared/OrderCard"
import axios from "axios"
import baseURL from "../../assets/common/baseUrl"
import AuthGlobal from "../../Context/store/AuthGlobal"
import { logoutUser } from "../../Context/actions/Auth.actions"
import { useEffect } from 'react/cjs/react.development';
const UserProfile = (props) => {
const context = useContext(AuthGlobal)
const [userProfile, setUserProfile] = useState()
const [orders, setOrders] = useState()
useFocusEffect(
useCallback(() => {
if (
context.stateUser.isAuthenticated === false ||
context.stateUser.isAuthenticated === null
) {
props.navigation.navigate("Login")
}
AsyncStorage.getItem("jwt")
.then((res) => {
axios
.get(`${baseURL}users/${context.stateUser.user.sub}`, {
headers: { Authorization: `Bearer ${res}` },
})
.then((user) => setUserProfile(user.data))
})
.catch((error) => console.log(error))
axios
.get(`${baseURL}orders`)
.then((x) => {
const data = x.data;
console.log(data)
const userOrders = data.filter(
(order) => order.user._id === context.stateUser.user.sub
);
setOrders(userOrders);
})
.catch((error) => console.log(error))
return () => {
setUserProfile();
setOrders();
}
}, [context.stateUser.isAuthenticated]))
return (
<Container style={styles.container}>
<ScrollView contentContainerStyle={styles.subContainer}>
<Text style={{ fontSize: 30 }}>
{userProfile ? userProfile.name : "" }
</Text>
<View style={{ marginTop: 20 }}>
<Text style={{ margin: 10 }}>
Email: {userProfile ? userProfile.email : ""}
</Text>
<Text style={{ margin: 10 }}>
Phone: {userProfile ? userProfile.phone : ""}
</Text>
</View>
<View style={{ marginTop: 80 }}>
<Button title={"Sign Out"} onPress={() => [
AsyncStorage.removeItem("jwt"),
logoutUser(context.dispatch)
]}/>
</View>
<View style={styles.order}>
<Text style={{ fontSize: 20 }}>My Orders</Text>
<View>
{orders ? (
orders.map((x) => {
return <OrderCard key={x.id} {...x} />;
})
) : (
<View style={styles.order}>
<Text>You have no orders</Text>
</View>
)}
</View>
</View>
</ScrollView>
</Container>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center"
},
subContainer: {
alignItems: "center",
marginTop: 60
},
order: {
marginTop: 20,
alignItems: "center",
marginBottom: 60
}
})
export default UserProfile;
This is my auth.js
import React, { useEffect, useReducer, userEffect, useState } from "react";
import jwt_decode from "jwt-decode";
import AsyncStorage from "@react-native-community/async-storage"
import authReducer from "../reducers/Auth.reducer";
import { setCurrentUser } from "../actions/Auth.actions";
import AuthGlobal from './AuthGlobal'
const Auth = props => {
const [stateUser, dispatch] = useReducer(authReducer, {
isAuthenticated: null,
user: {}
});
const [showChild, setShowChild] = useState(false);
useEffect(() => {
setShowChild(true);
if (AsyncStorage.jwt) {
const decoded = AsyncStorage.jwt ? AsyncStorage.jwt : "";
if (setShowChild) {
dispatch(setCurrentUserUser(jwt_decode(decoded)))
}
}
return () => setShowChild(false);
}, [])
if (!showChild) {
return null;
} else {
return (
<AuthGlobal.Provider
value={{
stateUser,
dispatch
}}
>
{props.children}
</AuthGlobal.Provider>
)
}
};
export default Auth;
Let me know if you need any more codes. Thank-you for your valuable time.
Upvotes: 1
Views: 881
Reputation: 513
Import ObjectID from mongodb package
const { ObjectID } = require('mongodb');
And change findById like below :
const user = await User.findById({id:req.params.id}).select('-passwordHash');
or may be like this :
const user = await User.findById({id:ObjectID(req.params.id)}).select('-passwordHash');
Upvotes: 1