Как правильно разграничить доступ
Есть мидлварь который запрещает доступ по роуту, если пользователь не авторизован
module.exports = async function (req, res, next) {
try {
const authorizationHeader = req.headers.authorization;
if (!authorizationHeader) {
return next(ApiError.UnauthorizedError());
}
const accessToken = authorizationHeader.split(' ')[1]; // отсекаем bearer берём токен
if (!accessToken) {
return next(ApiError.UnauthorizedError());
}
const userData = await tokenService.validateAccessToken(accessToken);
if (!userData) {
return next(ApiError.UnauthorizedError());
}
req.user = userData
next()
} catch (e) {
next(ApiError.UnauthorizedError());
}
};
Но не совсем понимаю как правильно реализовать удаление, редактирование (и тд) элемента, который принадлежит к конкретному юзеру
И в плане структуры, это делается ли это на уровне middleware, или сервиса, или БД?
п.с. - если это имеет значение, в проекте для авторизации используется jsonwebtoken. А так же express и mongoose
Ответы (1 шт):
Мне известно два пути реализации такого поведения:
- CASL Ability. Я отказался от использования этого решения, так как оно не подходило мне по нескольким параметрам: много бойлерплейт кода (В рамках NestJS); не хотелось тянуть лишнюю библиотеку; не известно, какие там есть подводные камни.
- Написать всё самому. Я выбрал этот путь.
В вашем случае, как я понял, используется чистый JavaScript, а не TypeScript, что, наверное, усложнит вам жизнь, если вы выберите второй путь, так как я использовал class-transformer, да и в принципе моя реализация была очень зависима от декораторов.
https://github.com/GrapeoffJS/CRMServer/tree/master/apps/crm/src/authorization <--- Если интересно посмотреть мою реализацию авторизации.
Думаю, вам следует почитать документацию у CASL Ability, и, если понравится, то внедрить его.
В моём случае, мне было необходимо скрывать данные от пользователя, а также запрещать доступ к каким-либо действиям в зависимости от его прав, что и потребовало реализации отдельных модулей, которыми будут этим заниматься. А в вашем примере со статьёй на Хабре это можно реализовать и на уровне контроллера, то есть перед удалением или редактированием статьи проверить пользователя на авторство, и, если нет, то выбрасывать res.status(403).end().
export const deletePost = (req, res) => {
const postId = req.params.id;
const userId = req.user.id;
const post = await PostModel.findOne({ id: postId, owner_id: userId });
if (!post) { return res.status(403).end() }
return res.json(await PostModel.findByIdAndDelete({ id: postId }));
}