5

Предположим, у меня сложная система, где есть большие деревья людей. Простые мысли - отношения между сотрудниками и менеджерами, многие сотрудники сообщают одному менеджеру. Теперь помимо менеджера есть сотрудники службы поддержки, которые способны действовать от имени менеджера, могут манипулировать сотрудниками менеджеров.CQRS, применяющие сквозные проблемы, такие как безопасность

В системе CQRS, как бы вы моделировали сообщение для гипотетического действия «edit employee», где invoker of the action является персоналом службы поддержки. Действие может быть выполнено только в том случае, если сотрудник в соответствии с отношениями безопасности менеджера действует на сотрудника в своей сфере.

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

Где этот запрос возникнет? Перед отправкой сообщения «Редактировать сотрудника»?

Если данные предварительно подтверждены перед отправкой сообщения, в согласованной системе предположим, что перед обработкой сообщения «Редактировать сотрудник» произошло отдельное действие, которое удалило бы полномочия пользователя на завершение " редактировать сотрудника ". Если обработчик команд не проверяет проблемы безопасности этого сообщения, сообщение все равно будет успешным, даже если пользователь больше не имеет права его выполнять.

Это, по-видимому, подразумевает, что проверка двусторонней валидации, аналогичная проверке UI &, будет лучшей практикой. Однако метод завершения этой проверки кажется, что он нарушит ключевые принципы для CQRS.

Какими подходами лучше всего справляться с этими и другими подобными проблемами поперечной резки при использовании CQRS?

+1

IMO нет общего ответа ... Я бы всегда проверял на стороне обработчика * как минимум * и ** опционально ** «вверх» (который может быть в той части, которая принимает сообщение в очередь) – Yahia

+0

Я также думаю, что важно различать истинные сквозные проблемы, такие как аутентификация, простая авторизация (разрешено ли этому пользователю выполнять такое действие), из бизнес-правил, которые определяют, разрешено ли что-либо для определенного объекта. –

ответ

3

Я бы, вероятно, пропустил CQRS полностью для этого домена и поговорил с веб-уровнем напрямую с уровнем БД (без обмена сообщениями). Простой оптимистический параллелизм должен обрабатывать несколько конфликтов, которые произойдут.

+0

Можете ли вы объяснить свой мыслительный процесс о причинах вашего первого заявления? –

+1

Потому что это самое простое решение, которое могло бы работать :) –

+0

Это, безусловно, верно, однако если бы самый простой был всегда лучшим способом, не было бы вообще никакого шаблона CQRS? –

5

Во-первых, я согласен с комментарием @ Yahia, что нет общего ответа. С этим сказал, вот как я подхожу к нему.

Для начала я бы, вероятно, пошел с двойной проверкой - один раз в моем контроллере, когда запрос был впервые получен, а затем позже в моем домене, когда он обрабатывает команду. Некоторые могут не согласиться с этим, но я предпочел бы предотвратить выдачу команды и немедленное информирование пользователя о том, что им не разрешено выполнять какие-либо действия, а не выполнять команду и полагаться на возможную согласованность для уведомления об ошибке пользователь после того, что они не смогли выполнить действие.

Таким образом, в терминах псевдокода, вот мой подход к Edit Employee:

Контроллер

[HttpPost] 
ActionResult Edit(Employee emp){ 

    //get employee org information from _employeeRepository 
    //validate if _loggedInUserID is able to edit emp.ID 

    if(isValid) { 
    //construct command 
    _commandService.EnqueueCommand(new EditEmployee(emp.ID, emp.Name, emp.Salary)); 
    } else { 
    return View("PermissionError"); 
    } 

    return Redirect("EmployeeProperties"); 
} 

Так вот моя команда сервис подбирает команду и направляет его в соответствующий AR в моем домене, который будет Employee.

Сотрудник домена

protected void EditEmployee(userID, employeeID, employeeName, salary){ 
    //get employee org information from _employeeRepository 
    //validate if userID is able to edit employeeID 

    if(isValid) { 
    //apply event 
    ApplyEvent(new EmployeeEdited(userID, employeeID, employeeName, salary)); 
    } 
} 

Так что я бы применить ту же проверку безопасности как в моем контроллере и в моем домене. У меня было бы это, вероятно, как инкапсулированный метод (ну, вероятно, инкапсулированный класс критериев, который я бы передал в репозиторий).

Так что я надеюсь, что это поможет в том, как я подхожу к этому сценарию.Дайте мне знать, если есть вопросы, и я уточню в своем ответе.

Надеюсь, это поможет. Удачи!

+0

Зачем вам применять его на обоих уровнях? Разве домен не является точкой, где все должно пройти, и поэтому такие проблемы, как безопасность и валидация, должны обрабатываться там? – Juri