mongodb - 登录用户时遇到问题
问题描述
我收到错误 TypeError: Cannot read property 'email' of undefined 尝试登录用户并且不允许我登录。我的代码有问题吗?我的 mongo 管理员/教师模型和控制器示例(我正在使用 jwt 身份验证)
const mongoose = require('mongoose');
const { isEmail, isLength } = require('validator');
const bcrypt = require('bcryptjs');
const { Schema, model } = mongoose;
const TeacherSchema = new Schema({
email: {
type: String,
unique: true,
validate: [isEmail, 'Please enter a valid email address'],
required: [true, 'You must provide an email address'],
},
password: {
type: String,
required: [true, 'You must provide a password'],
validate: [(value) => isLength(value, { min: 6 }), 'Your password must be at least 6 characters long'],
},
dateCreated: {
type: Date,
default: Date.now(),
},
myImages:[{
type:[Schema.Types.ObjectId],
ref:'Image'
}],
myGrade:[{
type:[Schema.Types.ObjectId],
ref:'Grade'
}],
myCourses: [{
type: [Schema.Types.ObjectId],
ref: 'Course',
}],
myStocks: [{
type: [Schema.Types.ObjectId],
ref: 'Stock',
}],
});
TeacherSchema.methods.toJSON = function() {
var obj = this.toObject();
delete obj.password;
return obj;
};
TeacherSchema.methods.comparePassword = async function (candidatePassword) {
const teacher = this;
try {
const isMatch = await bcrypt.compare(candidatePassword, teacher.password);
return Promise.resolve(isMatch);
} catch (e) {
return Promise.reject(e);
}
};
TeacherSchema.pre('save', async function (next) {
// gets access to the user model that is currently being saved
const teacher = this;
if (teacher.isModified('password')) {
try {
const salt = await bcrypt.genSalt();
const hash = await bcrypt.hash(teacher.password, salt);
// overwrite the plain text password with our hash
teacher.password = hash;
// Finally call save
next();
} catch (e) {
// Call save with an error
next(e);
}
}
next();
});
module.exports = model('Teacher', TeacherSchema);
这是控制器和路由的示例
const { isEmail, isLength } = require('validator');
const jwt = require('jwt-simple');
const axios = require('axios');
const { Teacher } = require('../models');
const { secret, GITHUB_CLIENT_SECRET } = require('../config');
function tokenForUser(teacher) {
const timeStamp = new Date().getTime();
return jwt.encode({ sub: teacher._id, iat: timeStamp }, process.env.SECRET || secret);
}
module.exports = {
teacherSignUp: async (req, res) => {
const {
email,
password
} = req.body;
if (!email || !password) {
return res
.status(422)
.json({ error: 'You must provide email and password' });
}
if (!isEmail(email)) {
return res
.status(403)
.json({ error: 'You must provide a valid email address' });
}
if (!isLength(password, { min: 6 })) {
return res
.status(403)
.json({ error: 'Your password must be at least 6 characters long' });
}
try {
// See if a user with the given email exists
const existingTeacher = await Teacher.findOne({ email });
if (existingTeacher) {
return res
.status(403)
.json({ error: 'User already exists' });
}
const teacher = await new Teacher({
email,
password,
}).save();
const currentTeacher = await Teacher.findById(teacher._id).select('-password');
// Eventually we will send a token
return res.json({ token: tokenForUser(teacher), teacher: currentTeacher });
} catch (e) {
return res
.status(403)
.json({ e });
}
},
teacherSignin: async (req, res) => {
const currentUser = await Teacher.findOne({ email: req.teacher.email }).select('-password');
console.log(currentUser,'current teacher email signin auth')
res.json({ token: tokenForUser(req.teacher), teacher: currentUser });
},
};
my route
const router = require('express').Router(); const {teacherSignUp,teacherSignin } = require('../../../controllers/teacherAuth');
const { trequireSignIn } = require('../../../tmiddlewares/tauthMiddlewares');
// /api/tauth/teachersignup // /api/tauth/teachersignin
router.post('/teachersignup', teacherSignUp); router.post('/teachersignin', trequireSignIn, teacherSignin);
module.exports = 路由器;
我在前端的 axios 请求。(我使用 redux 形式)
import React, { Component } from 'react';
import { Field, reduxForm, SubmissionError } from 'redux-form';
import { Form, Segment, Button,Container,Image,Header,Grid,Message,Icon } from 'semantic-ui-react';
import logo from './../../components/Images/Logo.png'
import { email, required } from 'redux-form-validators';
import axios from 'axios';
import { AUTH_TEACHER} from '../../actions/types';
import './../../index.css'
import { Helmet } from 'react-helmet';
import { Link } from 'react-router-dom';
import fanuel from './../../components/Images/fanuel.jpg'
import ganesh from './../../components/Images/ganesh.png'
import vanessa from './../../components/Images/vanessa.jpeg'
import husam from './../../components/Images/husam.jpeg'
import './../../index.css'
class TeacherSignIn extends Component {
onSubmit = async (formValues, dispatch) => {
try {
const { data } = await axios.post('/api/tauth/teachersignin', formValues);
localStorage.setItem('token', data.token);
dispatch({ type: AUTH_TEACHER, payload: data.token });
this.props.history.push('/watchlist');
} catch (e) {
throw new SubmissionError({
email: 'Please try again',
password: 'You entered a bad password',
_error: 'Login Failed'
});
}
}
renderEmail = ({input,meta}) => {
return(
<Form.Input
{...input}
fluid
error={meta.touched && meta.error}
icon='user'
iconPosition='left'
autoComplete='off'
placeholder='Email Address'
/>
)
}
renderPassword = ({ input, meta }) => {
return (
<Form.Input
{...input}
error={meta.touched && meta.error }
fluid
type='password'
icon='lock'
placeholder='password'
autoComplete='off'
iconPosition='left'
/>
);
}
render(){
const {handleSubmit,invalid,submitting,submitFailed}=this.props
return(
<div>
<Helmet>
<style>{'body { background-color: #532f8c; }'}</style>
</Helmet>
{/* <div className='j2'>
<Image style={{backgroundColor:'white'}} className='im2'src={logo}/>
</div> */}
<Grid textAlign="center" style={{ height: '85vh',margin:'0px 0 25px 0' }} verticalAlign="middle">
<Grid.Column style={{ maxWidth: 500}}>
<Form size='large' onSubmit={handleSubmit(this.onSubmit)}>
<Segment style={{backgroundColor:'#f7f8fa'}} >
<Header color="grey" textAlign="center" style={{ fontSize: '34px' }}>
<Image style={{backgroundColor:'white'}} className='im'src={logo} />
Log-in to your account
</Header>
<Field
name='email'
component={this.renderEmail}
validate={[
required({msg:'Email is required'}),
email({ msg: 'You must provide a valid email address' })
]}
/>
<Field
name='password'
component={this.renderPassword}
validate={[
required({msg:'you must provide a password'})
]}
/>
<Button
content='Sign In'
color='purple'
fluid
size='large'
type='submit'
disabled={invalid || submitting || submitFailed}
/>
</Segment>
</Form>
<Message style={{backgroundColor:'#f7f8fa'}}>
New to the site?
<Button as={Link} to="/signup" color="purple" size="small" compact style={{ marginLeft: '5px' }}>Sign Up Here</Button>
</Message>
</Grid.Column>
</Grid>
<div className='div-tag1'style={{backgroundColor:'#222222'}}>
<Container>
<Segment vertical>
<Grid columns={3} divided>
<Grid.Row>
<Grid.Column>
<h1 style={{color:'white'}}className='how-it-works'>10/10 Stock Tracker</h1>
<div><p style={{color:'white',fontSize:'1.25rem',fontFamily:'"Helvetica Neue",Helvetica,Arial,sans-serif'}}>
This application is a helpful tool to save stocks onto a personal watchlist. It provides information on the stock markets top 10 winners and losers of the day. Users can also search and track any stock in the market and view stocks that are trending among other users.
</p></div>
</Grid.Column>
<Grid.Column>
<h1 style={{color:'white'}}className='how-it-works'> Get Started
</h1>
<p style={{color:'white',fontSize:'1.25rem',fontFamily:'"Helvetica Neue",Helvetica,Arial,sans-serif'}}> Get access to your Watchlist by creating an account.
</p>
<Link
as={Link} to='/signup'>
<Button color='purple'> Register Now</Button>
</Link>
</Grid.Column>
<Grid.Column>
<h1 style={{color:'white'}}className='how-it-works'> Contact Us</h1>
<p style={{color:'white',fontSize:'1.25rem',fontFamily:'"Helvetica Neue",Helvetica,Arial,sans-serif',marginBottom:'10px'}}> <span > <a href='mailto:fanuelnalem@outlook.com' style={{color:'white'}} > <Icon name='mail'></Icon>Send Feedback</a> </span></p>
<h1 className='how-it-works'style={{color:'white',marginTop:'0',marginBottom:'18px'}}>
Developed By
</h1>
<div>
<Grid>
<Grid.Row columns={4}>
<Grid.Column>
<Image className='img' src={vanessa} />
</Grid.Column>
<Grid.Column>
<Image className='img'src={husam} />
</Grid.Column>
<Grid.Column>
<Image className='img'src={fanuel} />
</Grid.Column>
<Grid.Column>
<Image className='img'src={ganesh} />
</Grid.Column>
</Grid.Row>
</Grid>
</div>
</Grid.Column>
</Grid.Row>
</Grid>
</Segment>
<p style={{backgroundColor:'rgb(55, 55, 59)',padding:'10px',borderRadius:'5px',color:'white',fontSize:'1.25rem',fontFamily:'"Helvetica Neue",Helvetica,Arial,sans-serif' }}className='p-tag' >Copyright 2020. All rights reserved.</p>
</Container>
</div>
</div>
)
}
}
export default reduxForm({ form: 'tsignin' })(TeacherSignIn);
解决方案
推荐阅读
- android - 如何在aosp中构建自定义系统权限应用程序
- python-3.x - 堆叠两个具有不同列的熊猫数据框,将源数据框保持为列,也
- java - 凌空请求队列 NullPointerException
- c# - ASP.NET Core DI 与 Simple Injector 共享 DbContext
- ios - 如何让应用程序在连接的设备上运行
- node.js - 路径在 tsconfig.app.json 中没有按预期工作
- vb.net - ConstraintException 未被捕获
- python - 数字平方的函数不打印数字< 1的输出
- javascript - MYSQL 节点问题
- css - 可以连接打印机的设备的媒体查询