Node.js 根据注册中的用户角色切换配置文件路由(Express.js)
读得有点长 我目前正在为一个MERN项目构建后端,其结构非常有趣(我将更改细节,因为它是一个私有项目)Node.js 根据注册中的用户角色切换配置文件路由(Express.js),node.js,express,middleware,mern,express-router,Node.js,Express,Middleware,Mern,Express Router,读得有点长 我目前正在为一个MERN项目构建后端,其结构非常有趣(我将更改细节,因为它是一个私有项目) 数据库:目前有4个数据库模式,1个用户模式有3个不同的角色:学生、教师和赞助者 **这三种类型的用户角色都有自己独特但非常相似的配置文件模式(TeacherProfile、StudentProfile e.t.c),它们都通过ID**引用用户shcema const mongoose = require('mongoose'); const studentProfileSchema =
- 数据库:目前有4个数据库模式,1个用户模式有3个不同的角色:学生、教师和赞助者
const mongoose = require('mongoose');
const studentProfileSchema = new mongoose.Schema({
user: {
// create a reference to the user schema
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},.........
- 我有一个负责jwt逻辑的认证中间件
- 我有一个用户路径,负责用户注册
- 用于登录和身份验证的身份验证路由
- 和3条路线的配置文件
const express = require('express');
const router = express.Router();
const config = require('config');
// validator
const {check, validationResult} = require('express-validator');
// auth middleware
const auth = require('../../middleware/authMiddleware');
// db collections
const SponsorProfile = require('../../models/SponsorProfile');
const User = require('../../models/User');
// @route GET api/SponsorProfile/me
// @desc GET current user profile
// @access Private
router.get('/me', auth, async (req, res) => {
try {
// fetch profile object
const sponsorProfile = await SponsorProfile.findOne({user:req.user.id});
// check if profile exists
if(!sponsorProfile) {
return res.status(400).json({msg: 'Hello Sponsor, You have not created a profile'})
}
res.json(sponsorProfile)
} catch (error) {
console.error(error.message);
res.status(500).json({msg:'This is our fault not yours'})
}
})
module.exports= router;
现在我试着这么做:
- 我构建了一个主路由器,它使用所有的配置文件路由器作为从学生到赞助商的子路由器
- 然后在server.js中调用它,如下所示:
- 方法是在前两个路由器中放置一个中间件函数,并将第三个路由器保留为空,这样,如果前两个路由器中的标准通过,将有一个交换机
- 然后我尝试了这样的中间件功能
async function shouldRouterChange(req, res, next) {
try {
let userRole = await studentProfile.findOne({user:req.user.id}).populate('user', ['role']);
// conditional
console.log(userRole)
if (userRole.role==='mentor') {
return next('router')
}
return next()
} catch (error) {
console.error(error.message)
res.status(500).json({msg: 'Server Error'})
}
}
我尽可能地进行了调试,并意识到:
router.get()逻辑中调用
我的问题是如何使条件正确,从而使中间件结构正常工作(可能不会对我的应用程序结构做太多更改,无论如何都不会介意)我已经解决了错误,它工作起来很有魅力 使用路由器级中间件交换路由器(也可以交换单路由)
return next().
router.get('/me', [auth, partnerSwitch], async (req, res) => ...
也就是说,只要不满足条件,它就会不断切换,直到条件通过为止。
其工作原理与常规switch语句类似
这里我缺少的是,为了能够使用角色进行切换,我必须将其作为auth负载的一部分调用,这样它就成为req、res循环中请求对象的一部分,因此可以根据需要进行操作
我们永远不需要在最后一个路由器中调用另一个中间件,因为从逻辑上讲,只有当一切都失败时,交换才会到达那里,就像常规switch语句中的默认值一样
得到了我的一些帮助
一个用户使用它来手动解码我的JWT令牌,以准确地知道发生了什么
async function shouldRouterChange(req, res, next) {
let userRole = await User.findOne({user:req.role}).select('-password');
console.log(userRole)
if ( userRole === 'mentor') {
return next('router');
}
return next();
}
function shouldRouterChange(req, res, next) {
if (req.user.role === 'teacher') {
return next('router');
}
return next();
}
// @route GET api/studentProfile/me
// @desc GET current user profile
// @access Private
router.get('/me', [auth, shouldRouterChange], async (req, res) => {
try {
// check if profile exists
const studentProfile = await StudentProfile.findOne({user:req.user.id}).populate('user', ['role']);
if(!studentProfile) {
return res.status(400).json({msg: 'Hello student, You have not created a profile'})
}
res.json(studentProfile)
} catch (error) {
console.error(error.message);
res.status(500).json({msg:'This is our fault not yours'})
}
})
module.exports= router;
async function shouldRouterChange(req, res, next) {
let userRole = await User.findOne({user:req.role}).select('-password');
console.log(userRole)
if ( userRole === 'mentor') {
return next('router');
}
return next();
}
async function shouldRouterChange(req, res, next) {
try {
let userRole = await studentProfile.findOne({user:req.user.id}).populate('user', ['role']);
// conditional
console.log(userRole)
if (userRole.role==='mentor') {
return next('router')
}
return next()
} catch (error) {
console.error(error.message)
res.status(500).json({msg: 'Server Error'})
}
}
const express = require('express');
const profilesRouter = express.Router();
profilesRouter.use('/', require('./studentProfile'));
profilesRouter.use('/', require('./teacherProfile'));
profilesRouter.use('/', require('./sponsorProfile'));
module.exports = profilesRouter;
const jwt = require('jsonwebtoken');
const config = require('config');
// Check user profile
function teacherSwitch(req, res, next) {
const token = req.header('x-auth-token');
// if no token is returned
if (!token) {
return res.status(401).json({ msg: 'No token, permission denied' });
}
try {
// decode token
const decoded = jwt.verify(token, config.get('jwtSecret'));
// set role to the same value as in the request
req.user.role = decoded.user.role;
// check if role is teacher
if (decoded.user.role !== 'student') {
return next('router');
}
return next();
} catch (error) {
res.status(401).json({ msg: 'Wrong token, authentication failed' });
}
}
module.exports = teacherSwitch;
// create jwt payload
const payload = await {
user: {
id: user.id,
role: user.role,
},
};
// if user login is successful, return token
jwt.sign(payload, config.get('jwtSecret'),
{ expiresIn: 36000 }, (error, token) => {
if (error) throw error;
return res.json({ token });
});
} catch (error) {
console.error(error.message);
res.status(500).send('Server Error');
}
return next().
router.get('/me', [auth, teacherSwitch], async (req, res) => {
try {
// check if profile exists
const studentProfile = await StudentProfile.findOne({ user: req.user.id });
if (!teacherProfile) {
return res.status(400).json({ msg: 'Hello student, You have not created a profile' });
}
return res.json(studentProfile);
} catch (error) {
console.error(error.message);
return res.status(500).json({ msg: 'This is our fault not yours' });
}
});
function sponsorSwitch(req, res, next) {
const token = req.header('x-auth-token');
// if no token is returned
if (!token) {
return res.status(401).json({ msg: 'No token, permission denied' });
}
try {
// decode token
const decoded = jwt.verify(token, config.get('jwtSecret'));
// set role to the same value as in the request
req.user.role = decoded.user.role;
// check if role is partner
if (decoded.user.role !== 'teacher') {
return next('router');
}
return next();
} catch (error) {
res.status(401).json({ msg: 'Wrong token, authentication failed' });
}
}
router.get('/me', [auth, partnerSwitch], async (req, res) => ...