我是DDD的初学者,对如何实现特定域用例的授权不变量有疑问。
我有两个子域名:成员资格和身份。身份处理身份验证和管理用户和角色。
有问题的子域名是会员资格。会员可以拥有多种状态。激活成员时,有三个不变量:
用户有角色。这种情况的角色是系统管理员和章节管理员(单章)。
所以我有一个应用程序服务。用户ID存储在.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?命令处理程序是一个域服务,它只加载成员,调用其激活成员并将其保留。来自身份域的身份验证服务是否应该被推下去?我可以在上面的类中实现2,但是我必须从存储库加载两次成员。那不好吗?
答案 0 :(得分:1)
身份处理身份验证和管理用户和角色
因此,Identity处理身份验证和授权;拥有roles
只是应该从其他有界上下文中隐藏的实现细节。这意味着Membership
BC不应该关心授权是如何工作的,只是它有效。因此,为了隐藏它,Authorization BC应该发布如下界面:canUserActivateMember(userId,memberId)
。
现在,棘手的部分是在两个BC中都有members
的概念,但它意味着其他的东西:
Membership
BC中,成员包含特定于此域的(很多)属性和行为,例如ID
,Name
,Status
,{{1} },进入/离开俱乐部,以及该领域的相关内容Gender
BC的Authorization
,ID
和Chapter
,没有任何行为。 Status
属性由来自Status
BC的反腐败层同步(以cron或其他形式)。因此,来自Membership
BC的ActivateMember
服务应如下所示:
Membership
在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);
}
BC中,方法Authorization
可能如下所示:
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
}
类,每个BC一个,但具有不同的属性和行为。