DDD CQRS - за запитом та авторизацією за командою


15

Підсумок

Чи має бути виконана авторизація в CQRS / DDD за командою / запитом чи ні?

Я вперше розробляю онлайн-додаток, використовуючи більш-менш строго схему DDD CQRS. Я зіткнувся з якоюсь проблемою, яку я не можу реально опустити.

Додаток, який я будую, - це головна програма, яка дозволяє людям створювати книги, а також дозволяє іншим людям їх переглядати / редагувати / видаляти, наприклад, працівникам. Творець книги повинен мати можливість редагувати права доступу до створеної ним книги. Може навіть змінити право власності. Домен має два агрегати TLedger і TUser .

Я читав багато публікацій із ключовим словом DDD / CQRS щодо безпеки, авторизації тощо. Більшість із них заявляли, що авторизація - це загальний субдомен , якщо тільки не створюється програма захисту.

У цьому випадку основний домен - це, безумовно, домен бухгалтерського обліку, зацікавлений у транзакціях, балансуванні та рахунках. Але також необхідна функціональність для управління дрібнозернистим доступом до книг. Мені цікаво, як спроектувати це в термінах DDD / CQRS.

У підручниках DDD по всьому місцю зазначено, що команди є частиною всюдисущої мови. Вони значущі. Вони конкретні дії, які представляють "реальну річ".

Оскільки всі ці команди та запити - це фактичні дії, які користувачі виконували б у реальному житті, чи має реалізація авторизації поєднуватися з усіма цими "командами" та "запитами"? Користувач мав би право на виконання TLedger.addTransaction (), але не TLedger.removeTransaction (), наприклад. Або користувачеві буде дозволено виконувати запит "getSummaries ()", але не "getTransaction ()".

Тривимірне відображення існувало б у формі користувальницької книги-команди або запиту користувача-книги для визначення прав доступу.

Або, нерозв'язаним способом, названі "дозволи" будуть зареєстровані для користувача. Дозволи, які потім будуть відображені для конкретних команд. Наприклад, дозвіл "ManageTransaction" дозволить користувачеві виконувати "AddTransaction ()", "RemoveTransaction ()" тощо.

  1. Дозвіл відображення користувача -> книга -> команда / запит

  2. Дозвіл відображення користувача -> книга -> дозвіл -> команда / запит

Ось перша частина питання. Або коротко, чи слід впроваджувати авторизацію в CQRS / DDD за командою чи запитом? Або слід відключити авторизацію від команд?

По-друге, щодо авторизації на основі дозволів. Користувач повинен мати можливість керувати дозволами на своїх книгах або на книгах, яким йому дозволяється керувати.

  1. Команди управління авторизацією трапляються в книзі

Я думав додати події / команди / обробники до сукупності Ledger , таких як grantPermission (), revokePermission () та ін. Але для цього потрібно, щоб усі команди містили ідентифікатор користувача, який видав цю команду. Тоді я би перевірив TLedger, чи існує дозвіл для цього користувача на виконання цієї команди.

Наприклад :

class TLedger{ 
    function addTransactionCmdHandler(cmd){
        if (!this.permissions.exist(user, 'addTransaction')
            throw new Error('Not Authorized');
    }
}
  1. Команди управління авторизацією у Користувача

Іншим способом буде включення дозволів до ТУЗара. TUser мав би набір дозволів. Тоді в обробниках команд TLedger я отримав би користувача та перевірив, чи має він дозвіл на виконання команди. Але для цього потрібно отримати агрегат TUser для кожної команди TLedger.

class TAddTransactionCmdHandler(cmd) {
    this.userRepository.find(cmd.userId)
    .then(function(user){
        if (!user.can(cmd)){
            throw new Error('Not authorized');
        }
        return this.ledgerRepository.find(cmd.ledgerId);
    })
    .then(function(ledger){
        ledger.addTransaction(cmd);
    })

}
  1. Ще один домен із сервісом

Іншою можливістю було б повністю моделювати інший домен авторизації. Цей домен був би зацікавлений у правах доступу, авторизації тощо. Потім піддомен бухгалтерського обліку використовував би послугу для доступу до цього домену авторизації у формі AuthorizationService.isAuthorized(user, command).

class TAddTransactionCmdHandler(cmd) {
    authService.isAuthorized(cmd)
    .then(function(authorized){
        if (!authorized) throw new Error('Not authorized');
        return this.ledgerRepository.find(cmd.ledgerId)
    })
    .then(function(){
        ledger.addTransaction(cmd);
    })

}

Яке рішення було б найбільш «DDD / CQRS» способом?


1
Чудове запитання - я намагався вирішити подібні проблеми, і, здається, жодна література не займається цим напрямом. Мене трохи збентежила друга половина вашого питання. Здавалося, вам було цікаво, де розмістити управління дозволами (додавання чи видалення дозволів), але наведені приклади стосуються додавання транзакції, тому схоже, що друга половина запитує "як мені запитувати дозволи". Чи можете ви уточнити, будь ласка, цю частину?
emragins

Кожна транзакція може мати політику виконання. Кожен користувач повинен належати до однієї або більше груп, кожна група матиме профіль доступу із зазначенням, які транзакції дозволені. Під час виконання, перед виконанням транзакції, політика перевіряється на сукупність профілів для користувача, що виконує. Звичайно, це простіше сказати, ніж зробити.
NoChance

Відповіді:


5

За перше питання я боровся з чимось подібним. Все більше я схиляюся до трифазної схеми авторизації:

1) Дозвіл на рівні команди / запит «робить цей користувач коли - або дозволу на виконання цієї команди?» У додатку MVC це, ймовірно, може бути оброблене на рівні контролера, але я вибираю загальний попередній обробник, який запитуватиме збереження дозволів на основі поточного користувача та команди виконання.

2) Авторизація в службі додатків "чи має цей користувач" коли-небудь * має дозвіл на доступ до цього об'єкта? "У моєму випадку це, ймовірно, буде неявною перевіркою просто за допомогою фільтрів у сховищі - у моєму домені це в основному Орендаря, який має трохи більш деталізацію організаціїId.

3) Авторизація, яка покладається на перехідні властивості ваших організацій (наприклад, Статус), буде оброблятися всередині домену. (Наприклад, "Тільки певні люди можуть змінювати закриту книгу".) Я вирішую вкласти це всередині домену, оскільки воно сильно покладається на домен та ділову логіку, і мені не дуже зручно викладати це в інших місцях.

Я хотів би почути відповіді інших на цю ідею - зірвіть її на шматочки, якщо хочете (просто надайте кілька альтернатив, якщо у вас є :))


Я думаю, у вас є деякі дійсні моменти щодо різних "шарів" авторизації. Система, над якою я працював, мала різні типи користувачів - зареєстровані користувачі та співробітники. Дозволи на обробку команд / запитів зробили основну перевірку типу користувача. Якщо це був персонал, він завжди проходив. Якщо це був зареєстрований користувач, тоді він був дозволений лише за умови дотримання певних умов (наприклад, дозволів на сукупність).
магнус

0

Я би реалізував авторизацію як частину вашого BC авторизації, але розгорнув би її як фільтр дій у вашій системі книги. Таким чином, вони можуть бути логічно від'єднані один від одного - ваш код книги не повинен викликати код авторизації - але ви все одно отримаєте високоефективну авторизацію кожного вхідного запиту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.