Есть следущая структура данных:
Mongo models: User, Course, Lesson
User roles: admin, teacher, student
Отношения будут например такие:
User: {
name: 'Teacher',
role: 'teacher',
courses: [{
title: 'Course',
lessons: [{
title: 'Lesson'
}]
}]
}
teacher - может CRUD свои курсы и уроки
admin - может CRUD все что угодно
student - может READ любые уроки, в идеале бы только те, к которым у него есть доступ
Для распределения прав доступа хочу использовать ABAC access control
Пример:
admin { courses: 'read:any' } - может read любые курсы
teacher { courses: 'read:own' } - может read только свои курсы
student - { courses: 'read:any' } - может read любые курсы
Вопрос 1. Каким образом давать доступ пользователю к конкретному уроку в ABAC стиле?
В кратце о CRUD
POST - Create
GET - Read
PUT - Update
DELETE - Delete
Как я вижу организацию архитектуры:
CRUD для /users - тут вроде все понятно
GET, POST /users
PUT, GET, DELETE /users/:uuid
Ничего сложного ;)
Теперь рассмотрим создание пользовательских ресурсов:
P.S. Мы используем passport и у нас всегда есть текущий пользователь в req.user
CREATE для courses
Первый подход:
request:
POST users/:userUuid/courses - req.body { title } // создаем курс у пользователя
handler:
userUuid === req.user.uuid // проверяем права доступа
course = Course.create({ title })
user = User.find({ uuid: userUuid })
user.courses.push(course._id).save()
Чтобы получить курсы пользователя будем делать так:
request:
GET /courses/:courseUuid
handler:
course = Course.findOne({ uuid: courseUuid })
user = User.findOne({ 'courses': course._id})
user.uuid === req.user.uuid // проверяем права доступа, если true возвращаем курс
но это какой-то странный restful,
POST user/:userUuid/course
но
GET /course/:courseUuid
Далее создание lesson:
request:
POST /courses/:courseUuid/lessons
handler:
course = Course.findOne({ uuid: courseUuid })
user = User.findOne({ courses: course._id})
user.uuid === req.user.uuid // проверяем права доступа, если true - можно создавать урок
lesson = Lesson.create({ title })
course.lessons.push(lesson._id)
И чтение
request:
GET /lesson/:lessonUuid
handler:
lesson = Lesson.findOne({ uuid: lessonUuid })
course = Course.findOne({ lessons: lesson._id })
user = User.findOne({ courses: course._id})
user.uuid === req.user.uuid // проверяем права доступа, если true - можно вернуть урок
А если мы захотим добавить к lesson какой-нибудь quiz, то это снова будет цепочка предпроверок владельца.
Как-то все не оптимально и на RESTful не оч похоже, посоветуйте пожалуйста, как это вообще организовывают обычно?