首页 > 解决方案 > 在域事件中包含用户 ID

问题描述

我一直在从事一个使用 DDD 架构的新文档管理项目。我是 DDD 和事件驱动设计的新手,所以这是一次学习经历。
我的应用程序结构如下:

Domain 拥有我所有的领域逻辑,基础设施是持久性,应用程序主要是命令和处理程序,而 webapi 就是 webapi。

现在我正在努力实现用户授权,目前我决定使用授权处理程序,在执行命令或查询之前进行权限检查。我认为这给了我很好的灵活性来执行复杂的基于资源的授权,因为我的许多权限将取决于某个实体的当前状态。

到目前为止,这是可行的,我已经在我的应用程序层中实现了授权,而将大部分用户特定信息排除在我的域模型之外。

现在,我要解决的问题是如何最好地将用户信息包含在我的域事件中,这些事件是从我的域类中引发的。

比如我有一个聚合,比如说它的文档,这个文档有一定的审批流程。因此,当文档获得批准时,我想提出一个域事件,例如

public class DocumentApproved : IDomainEvent
{
    public DocumentApproved (Package package)
    {
        DocumentId= document.Id;
        Timestamp = DateTime.Now;
    }
    public Guid Id { get; }
    public Guid UserId { get; }
    public DateTime Timestamp { get; }
    public Guid PackageId { get; }
}

系统需要可审计,因此我计划将域事件用作审计跟踪以及引起副作用或向其他系统发送消息的机制。

Document 实体可能有一个看起来像这样的方法:

 public void Approve()
    {
        State = State.Approve(this);
        ApprovalRevision.Next();
        Events.Add(new DocumentApproved(this));
    }

我的问题

我想在几乎每个适用的域事件中包含 UserId,但我想不出如何做到这一点,而不必让 userId 成为我的域实体上每个相关方法的参数,这意味着它们只会是用于创建域事件的参数,因为所有授权类型的活动都将在应用层发生。

这是解决此问题的合理方法,还是我应该尝试以不同的方式捕获用户活动,例如我的请求管道,并将它们与域事件分开?这对我来说听起来不太对劲。将 userId 作为可能导致域事件的每个方法的参数确实不是什么问题,但这似乎只会给每个域实体签名添加混乱。

为了提高我的域事件,我正在做类似于这里建议的事情,其中​​实体有一个 DomainEvents 集合,并且它们在保存实体之前通过 MediatR 发布。

标签: c#dnsdomain-driven-designmediatr

解决方案


 我认为这给了我很好的灵活性来执行复杂的基于资源的授权,因为我的许多权限将取决于某个实体的当前状态。

听起来授权是业务规则的重要组成部分,应该在领域层实现。您需要使用用户信息来丰富域事件这一事实表明用户应该是域的一部分。

在不确切知道域的情况下,我可以想象您有一个不变量,例如:“文档只能由作者的直线经理批准”。如果没有用户/角色的概念,您无法在域中断言此不变量。


推荐阅读