我已经解决了这个问题。我找到Express.js role-based permissions middleware并使用它。太棒了,我会重写我的代码!
我想检查一下多个许可,但这对我没用。
我创建了三个检查传输的中间件:requiredAuth、checkAdmin和checkCompanyManager。
模型:User:{名称、许可、isBlocked、公司:{id,userPermistion}}
requiredAuth函数将检查并找到signedUser,并将其设置为res.locals.user
const checkAdmin = (req, res, next) => {
let user = res.locals.user
if (user.permission === 2) next()
else res.json({errors: "Only admin can do this action"})
}
const checkCompanyManager = (req, res, next) => {
let user = res.locals.user
let companyId = req.body.companyId ? req.body.companyId : req.query.companyId
if (user.company.id && user.company.id.equals(companyId)
&& user.company.userPermistion === 1) next()
else res.json({errors: "Only company member can do this action"})
}最后,我使用所有在路由器中检查动作块用户(只有管理员或公司经理可以阻止用户)。
router.post('/admin/block-by-ids',
requiredAuth,
checkAdmin || checkCompanyManager,
userController.blockByIds
)但是它不起作用,因为如果checkAdmin错了,就会中断并返回json,不能运行checkCompanyManager --我可以如下所示解决这个问题:
router.post('/admin/block-by-ids',
requiredAuth,
(req, res, next) => {
let user = res.locals.user
let companyId = req.body.companyId
if ((user.permission === 2) ||
(user.company.id && user.company.id.equals(companyId) &&
user.company.userPermistion === 1)) {
next()
} else next("Only admin or company manager can do this action")
},
userController.blockByIds
)但这不好玩!我只想使用中间件来检查,而不想再次编写代码。我该怎么做?我要你给我个主意!
发布于 2019-07-31 10:09:58
||操作符不执行您认为的操作。它返回第一个真实值:
var a = 1 || 2; // a is 1您需要的是一个或中间件。类似于:
function or (middleware1, middleware2) {
return function (req, res, next) {
var alreadyCalledNext = false;
function resolve () {
if (!alreadyCalledNext) {
alreadyCalledNext = true;
next();
}
}
middleware1(req,res,resolve);
middleware2(req,res,resolve);
}
}
router.post('/admin/block-by-ids',
requiredAuth,
or(checkAdmin, checkCompanyManager),
userController.blockByIds
)但是,上述实现遇到了另一个问题。一旦您发送了res.json,您就不能再发送另一个响应。因此,如果checkAdmin或checkCompanyManager都失败了,则需要阻止它们发送res.json,除非两者都失败。因此,您需要对res进行存根,并传递一个假的res (就像我们对next所做的一样):
function or (middleware1, middleware2) {
return function (req, res, next) {
var alreadyCalledNext = false;
function resolve () {
if (!alreadyCalledNext) {
alreadyCalledNext = true;
next();
}
}
var jsonCount = 0;
var fakeRes = {
locals: res.locals,
json: function (data) {
jsonCount ++;
if (jsonCount >= 2) { // both must fail for OR to fail
res.json(data);
}
}
}
middleware1(req,fakeRes,resolve);
middleware2(req,fakeRes,resolve);
}
}这应该能行。
上面的解决方案感觉设计过度了.我会亲自使checkAdmin和checkCompanyManager常规函数返回布尔值,然后将它们包装在checkPermissions中间件中:
const isAdmin = (req,res) => {
let user = res.locals.user
return user.permission === 2
}
const isCompanyManager = (req,res) => {
let user = res.locals.user
let companyId = req.body.companyId ? req.body.companyId : req.query.companyId
return user.company.id && user.company.id.equals(companyId) && user.company.userPermistion === 1
}
const checkPermissions = function (checks) {
return (req, res, next) => {
// Call next if any check passes:
for (let i=0; i<checks.length; i++) {
if (checks[i](req,res)) return next();
}
res.json({errors: "You don't have authorization to do this action"})
}
}
router.post('/admin/block-by-ids',
requiredAuth,
checkPermissions([isAdmin, isCompanyManager]),
userController.blockByIds
)https://stackoverflow.com/questions/57286564
复制相似问题