Как я уже говорил в моих комментариях, этот дизайн имеет некоторую бизнес-логику, которая может сделать его не лучшим образом подходящим для обычных элементов управления безопасностью типа ACL.На первый взгляд кажется, что проще найти решение, заключающееся в простой реализации ваших бизнес-правил в моделях Mongoose или в коде контроллера, в зависимости от ваших предпочтений.Тем не менее, ключевой момент в реализации ACL-подобного подхода заключается в дизайне вашего URL.Например, заманчиво сделать ваш API таким, чтобы все заказы были доступны через /api/orders
, и, возможно, человек запросит свои собственные заказы через /api/orders?userId=12345
.Но это делает большинство подходов, основанных на ACL, неудачными.Вместо этого вы должны думать об API с точки зрения иерархии так, как вы хотите, чтобы она была защищена (независимо от того, все ли заказы хранятся в модели Orders Mongoose и сохраняются в коллекции заказов).
Таким образом, используя ваше первое требование в качестве примера
Клиент может сделать несколько заказов и увидеть, какие продукты он заказал
Основное внимание здесь уделяетсячто вы защищаете вещи «владельцем» заказов клиента, поэтому, чтобы обезопасить его таким образом, вам нужно настроить маршрут таким образом, например (при условии, что вы используете первое промежуточное ПО, о котором вы спрашивали):
app.post('/api/customer/:customerId/orders', acl.middleware(), (req, res, next) => {
const order = new Order(req.body); // TODO: whitelist what info you take in here
order.customerId = req.user.id; // assuming you have a logged-in user that does this
order.save(e => {
if (e) return next(e);
return res.status(201).send(order);
});
});
Для поддержки этого вы должны зарегистрировать информацию ACL следующим образом:
acl.allow('12345', '/api/customer/12345/orders', ['post']);
Как минимум, вы это сделаете.Скорее всего, вы предоставите больше опций, таких как «получить» и т. Д. Как вы можете догадаться, это означает, что вам необходимо регистрировать разрешения для отдельных пользователей при каждом их создании (для поддержки концепции «владения»).
По вашему второму требованию
Он также может изменить заказ только в течение определенного периода времени, например, до его обработки.
Несмотря нато, что я сказал ранее, вы можете сделать это в ACL, если вы действительно этого хотите.Например, вы можете создать учетную запись URL для статуса, например, «/ api / Customers / 12345 / orders / modifiable / 6789», но в моем опыте это сложно поддерживать.Вам лучше поместить эту логику в контроллер или логику Mongoose.Вероятно, это проще сделать в контроллере, если только вы не планируете использовать свои модели Mongoose вне приложения Express.Примерно так (обратите внимание, в этом случае не используйте ACL, хотя вы могли бы, если хотите):
app.param('orderId', (req, res, next, id) => {
Order.findById(id, (err, order) => {
if (err) return next(err);
if (order) {
req.order = order;
return next();
}
const notFound = new Error('Order not found');
notFound.status = 404;
return next(notFound);
});
});
app.put('/api/orders/:orderId', (req, res, next) => {
if (req.order.status !== 'pending') {// or whatever your code setup is
const notProcessable = new Error('Cannot modify an order in process');
notProcessable.status = 422;
return next(notProcessable);
}
// handle the modification and save stuff
});