Комментарии 16
А как с такими DSL решается задача «показать список объектов, которые я могу видеть? Надо же в SQL-запрос это как-то транслировать, не выгребать же все записи с БД.
Если допустим речь идет о таком вопросе — выдай мне все роли или разрешения для этого объекта, или этого субъекта, то в библиотеке реализована такая фукнциональность, которая называется [Management API](https://casbin.org/docs/en/rbac-api)
Вот как выглядит функция — выдай мне все роли по этому пользователю:
var res = e.GetRolesForUser("alice");
А вот — выдай мне все разрешения для этого пользователя.
var permissions = e.GetPermissionsForUser("bob");
И вернется массив разрешений, это может быть допустим id объектов, к которым пользователю предоставлен доступ.
Возможно ответ вы можете увидеть в примере Пример №3. Контроль доступа на основе ролей с поддержкой мультитенатности (RBAC with domains/tenants), когда предоставляем доступ пользователя только к тем клиенам, которые принадлежат к его компании.
Есть интерфейс на сайте, показывающий список чего-либо. Скажем — статей в админке CMS. Статей с базе — десятки тысяч, но обычно пользователь имеет доступ только к десятку. Как достать из БД статьи, которые видны конкретному пользователю? Ну, если мы все правила что кому видно — вынули из кода в какой-то DSL?
Другими словами — как написать запрос типа select * from objects as o where hasAssess(currentUser, o)
У меня такие правила в коде, в виде LINQ-выражений, и я такую задачу решать умею. А возникает такая задача даже чаще, чем «проверить есть ли доступ к одному вгруженному с память объекту»
Как достать из БД статьи, которые видны конкретному пользователю?
Ок, я уже начинаю лучше понимать что интересует, но еще пару вопросов. А как в вашем случае вы определяете принадлежность статьи к какому-нибудь пользователю? Есть таблица статьей, в которой тысячи записей. Есть таблица пользователей. Каким образов в вашем случае, и где, вы связываете статью с конкретным пользователем, т.е. как и где храниться та информация, что вот этому пользователю можно читать эту конкретную статью, а этому можно ее редактировать, а другому можно ее удалять? Где, в каком виде и как хранится эта информация?
Для твоего примера, может быть вот такое:
select * from articles a
join roles r on r.userId = currentUserId
where
article.owner = currentUserId
OR (r.role in ['admin', 'supevisor']) — админ всего
OR (r.domain = currentDomainId AND r.role in ['domain-admin', 'domain-supervisor']) — админ домена
Мы отобразили список статей в интерфейсе. Рядом с каждой записью, при наведении курсора отображается значек редактирования и удаления. Как теперь в твоей системе решается вопрос, отображать или не отображать этот значек, и можно ли пользователю удалить или отредактировать запись?
В примере jakobz фильтрация по правам на чтение выполнена на уровне хранилища. Когда пользователю доступно по правам 1% из 100 тыс. документов, то в PERM придётся отправить чуть менее 100 тыс. запросов, чтобы набрать одну страницу списка, что жутко медленно. Поэтому, как минимум, права на чтение должны проверяться как можно ближе к хранилищу. А если в системе есть массовые операции удаления или модификации, то и контроль по всем правам.
PERM хорош для контроля доступа к единичным объектам.
Вы видимо не совсем вникли в суть, для чего используется Casbin и область ее применения. Не надо отправлять 100 тыс запросов. Это абсурд.
В данной ситуации, вы можете 1 раз спросить у Casbin что можно видеть этому конкретному пользователю и 1м SQL запросом выбрать все доступные ему документы.
Ну, плохо что библиотека авторизации не учитывает нужный всем сценарий — когда юзер не авторизован вообще сущность видеть. В мульти-тенантном сценарии, например, ты же не будешь одним клиентам показывать данные других клиентов. Пусть даже и без кнопки view.
Поэтому, наверное, нигде эти библиотеки со странными своими DSL, и не используют.
Если надо просто для одного объекта проверить доступ — это делается обычной функцией. Обычный C# код куда лучше сделает тоже самое, что делают эти DSL.
Я еще через expression-ы реюзаю код — их можно и в EF-запрос в where сунуть, и сделать .Compile() и вызывать как функцию.
Ну, я так понимаю, что ценность такой библиотеки в переносе правил авторизации на уровень конфигурации с уровня кода, что позволяет более гибко ими управлять
И плюс еще ценность в том, что можно комбинировать различные сценарии и подходы к авторизации. Допустим делать гибрид RBAC и ABAC подхода, например описанного здесь www.mdpi.com/2073-8994/11/5/669/htm.
В вашей ситуации к сожалению, вы мыслите немного другими категориями. Casbin очень гибкий инструмент. Она учитывает разные сценарии авторизации. Вопрос только в том, как ее использовать.
В вашем сценарии, неавторизованный пользователь — это тоже роль — которая так и называется, — неавторизованный пользователь. Вы делаете 1 запрос к Casbin, выясняя, какими правами обладает этот неавторизованный пользователь. А затем делаете запрос к БД на основании этих данных, возвращая только те записи, которые доступны неавторизованному пользователю.
RBAC? ABAC?.. PERM! Новый подход к авторизации в облачных веб-службах и приложениях