Ответы пользователя по тегу Проектирование программного обеспечения
  • Где лучше проверять права пользователя - модель/контроллер/%else%?

    tiabc
    @tiabc
    Бизнес-партнер и консультант по технологиям
    С системой прав всегда сложно работать и всегда нужно смотреть на конкретную реализацию и учитывать как она будет изменяться в будущем. В любом случае, я сейчас слегка включен в работу над подобной задачей в нашей компании и попробую дать какой-то полезный ответ.

    В контроллере действительно проверять стоит только простые кейсы и недостаток проверки в контроллере как раз в том, что если, например, реализовали проверку в одном HTTP-контроллере и вдруг появляется CLI-контроллер, то хочется чтобы вызовы доменной логики были одинаковыми с любого места, включая валидацию. Соответственно, попробуем унести проверку доступа в другое место.

    В модель все тоже уносить не хочется. Соблюдая принцип SoC и слоистости приложения, доменные модели в общем случае ничего не должны знать про пользователя, который производит над ними действие. Соответственно, есть предложение ввести некий третий компонент, который отвечает именно за проверку есть ли у пользователя доступ к определенному действию. Плюс уверен, что иногда захочется произвести какое-то действие над моделью без проверки прав.

    Как вы написали, у вас есть некий набор прав и некие действия (модерация, редактирование) с некоторыми параметрами (поля для редактирования), которые можно производить над моделью. Соответственно, сформулируем какое-то решение. Оно может вам совершенно не подойти, это лишь простой вариант пальцем в небо, который иллюстрирует подход. Введем PolicyChecker с методами в духе canCreatePost(user, createPostRequest) bool, где каждый метод соответствует проверке конкретного действия с конкретными параметрами запроса у конкретного пользователя. Этот PolicyChecker все знает про авторизованных пользователей, про роли, группы и что бы то ни было у них есть, а если ему нужны дополнительные зависимости для проверки, они передаются ему в конструкторе или какой там у вас подход к управлению зависимостями.

    Таким образом, в каждом контроллере вы на основе PolicyChecker'а сможете проверить, что данный пользователь авторизован на данное действие. Если появится еще один контроллер, то придется эту проверку писать заново и я считаю, что это правильно, т.е. PolicyChecker'ы могут быть опять же разные для разных контроллеров и правила проверки в них могут отличаться. Либо может быть необходимость вообще выполнить действие над моделью без авторизованного пользователя, как уже писал выше, и тогда никакие права можно и не проверять и просто забыть про PolicyChecker.

    Конкретная реализация опять же зависит от вашего конкретного юз кейса и систему прав нужно хорошенько проектировать в связи с нуждами бизнеса потому что она имеет свойство лавинообразно разрастаться и приводить к сложностям в поддержке кода и вообще уязвимостям.

    Надеюсь, мои рассуждения оказались вам полезны.
    Ответ написан
    2 комментария