DDD - Реализация инвариантов авторизации - PullRequest
0 голосов
/ 21 мая 2018

Я новичок в DDD и у меня есть вопрос о том, как реализовать инварианты авторизации для конкретного случая использования домена.

У меня есть два поддоменов: членство и идентификация.Идентификация обрабатывает проверку подлинности и управление пользователями и ролями.

Поддомен, о котором идет речь, - Членство.Участники могут иметь несколько статусов.При активации члена существует три инварианта:

  1. Глава Администраторы могут активировать только участника в своей главе
  2. Глава Администраторы могут активировать только неактивных участников.
  3. СистемаАдминистраторы могут активировать любого участника из любого статуса.

Пользователи имеют роли.Роли для этой ситуации - системный администратор и администратор главы (для отдельной главы).

Итак, у меня есть служба приложений.Идентификатор пользователя хранится в .Net Identity, но я чувствую, что служба приложений не знает о .Net Identity - это хорошая идея?

public void ActivateMember(UserId userId, MemberId memberId)
{
     //This handles invariants 1 & 3
     memberAccess.DoesUserHaveAccessToMember(userId, memberId);

     //But how to I handle 2?

     //here is the call into the domain
     commands.Handle(new ActivateMember(memberId);
}

Как справиться с 2?Обработчик команд - это служба домена, которая просто загружает участника, вызывает его активируемый член и сохраняет его обратно.Должны ли службы аутентификации из домена Identity быть настолько далеко?Я мог бы реализовать 2 в вышеприведенном классе, но затем я должен загрузить член дважды из хранилища.Это плохо?

1 Ответ

0 голосов
/ 22 мая 2018

Идентификация обрабатывает аутентификацию и управляет пользователем и ролями

Итак, Идентификация обрабатывает аутентификацию и авторизация ;roles - это просто детали реализации, которые должны быть скрыты от других ограниченных контекстов.Это означает, что Membership BC не должно волновать, как работает авторизация, только то, что она работает.Итак, чтобы скрыть это, авторизационный BC должен опубликовать интерфейс, подобный следующему: canUserActivateMember(userId,memberId).

Теперь сложная часть состоит в том, что в обоих BC есть понятие members, но это означает, чточто-то еще:

  • в Membership BC, члены содержат (много) свойств и поведения, характерных для этого домена, таких как ID, Name, Status, Genderвходя / выходя из клуба, независимо от того, что имеет отношение к этому домену
  • в Authorization BC, члены содержат только ID, Chapter и Status, без поведения.Свойство Status синхронизируется антикоррупционным слоем из Membership BC (в кроне или чем-либо еще).

Итак, ваша служба ActivateMember из Membership BC должна выглядетьвот так:

public void ActivateMember(UserId userId, MemberId memberId)
{
     //This handles invariants 1, 2 & 3
     if(!authorization.canUserActivateMember(userId,memberId)) {
         throw ExceptionOrSomething;
     }

     //here is the call into the domain
     commands.Handle(new ActivateMember(memberId);
}

В Authorization BC метод canUserActivateMember может выглядеть так:

public boolean canUserActivateMember(UserId userId, MemberId memberId)
{
    var user = userRepository.load(userId);
    var member = memberRepository.load(memberId);

    if(user.isSystemAdministrator()){
        return true;
    }

    if(user.isChapterAdministrator() && member.hasChapter(user.getChapter)){
        return true;
    }

    if(user.isChapterAdministrator() && member.isInactive()) {
        return  true;
    }

    return false;//the default  
}

Итак, у вас есть два Member класса, один вкаждый BC, но с разными свойствами и поведением.

...