Estou trabalhando em um pequeno aplicativo tentando entender os princípios do design controlado por domínio. Se for bem-sucedido, pode ser um piloto para um projeto maior. Estou tentando seguir o livro "Implementing Design Orientado a Domínios" (de Vaughn Vernon) e tentando implementar um fórum de discussão simples e semelhante. Também verifiquei as amostras do IDDD no github. Tenho algumas dificuldades em adotar a identidade e o acesso ao meu caso. Deixe-me dar algumas informações básicas:
- (Espero) compreendo o raciocínio por trás da separação da lógica de usuários e permissões: é um domínio de suporte e é um contexto limitado diferente.
- No domínio principal, não há usuários, apenas Autores, Moderadores, etc. Eles são criados acessando o contexto de Identidade e Acesso usando um serviço e, em seguida, convertendo os objetos Usuário recebidos para e Moderador.
As operações de domínio são chamadas com uma função relacionada como parâmetro: por exemplo:
ModeratePost( ..., moderator);
O método do objeto de domínio verifica se a instância do Moderador fornecida não é nula (a instância do Moderador será nula se o usuário solicitado no contexto Identidade e Acesso não tiver a função de Moderador).
Em um caso, ele faz uma verificação adicional antes de alterar uma postagem:
if (forum.IsModeratedby(moderator))
Minhas perguntas são:
Neste último caso, as preocupações de segurança não são misturadas novamente no domínio principal? Anteriormente, os livros afirmam "com quem pode postar um assunto ou sob quais condições são permitidas. Um fórum precisa saber que um autor está fazendo isso no momento".
A implementação baseada em funções no livro é bastante direta: quando um Moderador é o domínio principal, tenta converter o userId atual em uma instância do Moderador ou em um Autor quando necessário. O serviço responderá com a instância apropriada ou um valor nulo se o usuário não tiver a função necessária. No entanto, não vejo como adaptar isso a um modelo de segurança mais complexo; nosso projeto atual para o qual estou pilotando tem um modelo bastante complexo com grupos, ACLs etc.
Mesmo com regras que não são muito complexas, como: "Uma postagem deve ser editada apenas por seu proprietário ou por um editor", essa abordagem parece desmoronar, ou pelo menos não vejo a maneira correta de implementá-la.
Perguntar ao contexto Identity and Access que uma instância OwnerOrEditor não parece correta e eu terminaria com mais e mais classes relacionadas à segurança no domínio principal. Além disso, eu precisaria passar não apenas o userId, mas o identificador do recurso protegido (o ID da postagem, fórum etc.) para o contexto de segurança, que provavelmente não deveria se importar com essas coisas (está correto? )
Ao puxar as permissões para o domínio principal e verificá-las nos métodos dos objetos de domínio ou nos serviços, eu terminaria na estaca zero: misturando preocupações de segurança com o domínio.
Li em algum lugar (e tendem a concordar com isso) que essas coisas relacionadas a permissões não devem fazer parte do domínio principal, a menos que segurança e permissões sejam o próprio domínio principal. Uma regra simples como a mencionada acima justifica tornar a segurança parte do domínio principal?
fonte
HasPermissionToEdit(userId, resourceId)
mas não me sinto bem em contaminar a lógica do domínio com essas chamadas. Provavelmente eu deveria verificar isso nos métodos de serviço de aplicativo, antes de chamar a lógica do domínio?UserService @AccessControlList[inf3rno]
na resposta à qual vinculei.Respostas:
Às vezes, é difícil distinguir entre regras reais de controle de acesso e invariantes de domínio que fazem fronteira com o controle de acesso.
Especialmente, as regras que dependem de dados disponíveis apenas no decorrer de uma parte específica da lógica do domínio podem não ser facilmente extraíveis do domínio. Normalmente, o Controle de Acesso é chamado antes ou depois de uma operação de domínio ser realizada, mas não durante.
O
assert (forum.IsModeratedBy(moderator))
exemplo de Vaughn Vernon provavelmente deveria estar fora do Domínio, mas nem sempre é viável.Se existe um Security BC e você deseja que ele lide com essa lógica, ele não precisa saber o que é um fórum em detalhes, mas:
fonte
moderator = securityService.GetModerator(userId, forumId)
4. A lógica do domínio será implementada nesses objetos, como no moderator.EditPost () 5. Métodos como o EditPost não saberão nada sobre conceitos de segurança, não haverá verificações adicionais láAutenticação e autorização é um mau exemplo para o DDD.
Nenhuma dessas coisas faz parte de um domínio, a menos que sua empresa crie produtos de segurança.
O requisito comercial ou de domínio é ou deve ser "eu exijo autenticação baseada em função"
Você então verifica a função antes de chamar uma função de domínio.
Onde você tem requisitos complexos, como 'Eu posso editar minhas próprias postagens, mas não outras', verifique se o seu domínio separa a função de edição
EditOwnPost()
eEditOthersPost()
para que você tenha uma função simples no mapeamento de funçõesVocê também pode separar a funcionalidade em Objetos de Domínio, como
Poster.EditPost()
eModerator.EditPost()
essa é uma abordagem mais OOP, embora sua escolha possa depender se o seu método está em um Serviço de Domínio ou em um Objeto de Domínio.No entanto, você escolhe separar o código que o mapeamento de função ocorrerá fora do domínio. por exemplo, se você possui um controlador webapi:
Como você pode ver, embora o mapeamento de funções seja feito na camada de hospedagem, a lógica complexa do que constitui a edição da sua própria publicação ou de uma publicação de outras pessoas faz parte do domínio.
O domínio reconhece a diferença das ações, mas o requisito de segurança é simplesmente que "a funcionalidade possa ser limitada por funções" .
Talvez isso seja mais claro com a separação dos objetos de domínio, mas, essencialmente, você está verificando o método que constrói o objeto em vez do método que chama o método de serviço. Seu requisito, se você ainda deseja expressá-lo como parte do domínio, se tornará 'apenas moderadores podem construir o objeto moderador'
fonte