private void Handle(IAcSession acSession, IPrivilegeCreateIo input, bool isCommand) { var acDomain = _set._acDomain; var privilegeList = _set._privilegeList; var privilegeBigramRepository = acDomain.RetrieveRequiredService <IRepository <Privilege, Guid> >(); var accountRepository = acDomain.RetrieveRequiredService <IRepository <Account, Guid> >(); if (!input.Id.HasValue || input.Id.Value == Guid.Empty) { throw new GeneralException("意外的标识"); } AcElementType subjectType; if (!input.SubjectType.TryParse(out subjectType)) { throw new ValidationException("非法的主体类型" + input.SubjectType); } AcElementType acObjectType; if (!input.ObjectType.TryParse(out acObjectType)) { throw new ValidationException("非法的客体类型" + input.ObjectType); } Privilege entity; lock (Locker) { switch (subjectType) { case AcElementType.Undefined: throw new GeneralException("意外的主体类型" + subjectType.ToString()); case AcElementType.Account: if (!accountRepository.AsQueryable().Any(a => a.Id == input.SubjectInstanceId)) { throw new ValidationException("给定标识的账户不存在" + input.SubjectInstanceId);; } break; case AcElementType.Role: RoleState role; if (!acDomain.RoleSet.TryGetRole(input.SubjectInstanceId, out role)) { throw new ValidationException("意外的角色标识" + input.SubjectInstanceId); } break; case AcElementType.Catalog: CatalogState org; if (!acDomain.CatalogSet.TryGetCatalog(input.SubjectInstanceId, out org)) { throw new ValidationException("意外的目录标识" + input.SubjectInstanceId); } break; case AcElementType.Privilege: throw new NotSupportedException(); default: throw new GeneralException("意外的主体类型" + subjectType.ToString()); } switch (acObjectType) { case AcElementType.Undefined: throw new ValidationException("意外的账户权限类型" + input.SubjectType); case AcElementType.Catalog: CatalogState catalog; if (!acDomain.CatalogSet.TryGetCatalog(input.ObjectInstanceId, out catalog)) { throw new ValidationException("意外的目录标识" + input.ObjectInstanceId); } break; case AcElementType.Role: RoleState role; if (!acDomain.RoleSet.TryGetRole(input.ObjectInstanceId, out role)) { throw new ValidationException("意外的角色标识" + input.ObjectInstanceId); } break; case AcElementType.Group: GroupState group; if (!acDomain.GroupSet.TryGetGroup(input.ObjectInstanceId, out group)) { throw new ValidationException("意外的工作组标识" + input.ObjectInstanceId); } break; case AcElementType.Function: FunctionState function; if (!acDomain.FunctionSet.TryGetFunction(input.ObjectInstanceId, out function)) { throw new ValidationException("意外的功能标识" + input.ObjectInstanceId); } break; case AcElementType.Menu: MenuState menu; if (!acDomain.MenuSet.TryGetMenu(input.ObjectInstanceId, out menu)) { throw new ValidationException("意外的菜单标识" + input.ObjectInstanceId); } break; case AcElementType.AppSystem: if (!acDomain.AppSystemSet.ContainsAppSystem(input.ObjectInstanceId)) { throw new ValidationException("意外的应用系统标识" + input.ObjectInstanceId); } break; case AcElementType.Privilege: throw new ValidationException("暂不支持" + input.SubjectType + "类型的授权"); default: throw new ValidationException("意外的账户权限类型" + input.SubjectType); } if (subjectType == AcElementType.Role && acObjectType == AcElementType.Role) { if (input.SubjectInstanceId == input.ObjectInstanceId) { throw new ValidationException("角色不能继承自己"); } var descendantIds = new HashSet <Guid>(); RecDescendantRoles(input.SubjectInstanceId, descendantIds); if (descendantIds.Contains(input.SubjectInstanceId)) { throw new ValidationException("角色不能继承自己的子孙"); } } if (subjectType == AcElementType.Account && acObjectType == AcElementType.Account) { if (input.SubjectInstanceId == input.ObjectInstanceId) { throw new ValidationException("账户不能继承自己"); } var descendantIds = new HashSet <Guid>(); RecDescendantAccounts(input.SubjectInstanceId, descendantIds); if (descendantIds.Contains(input.SubjectInstanceId)) { throw new ValidationException("账户不能继承自己的子孙"); } } if (subjectType == AcElementType.Account && acObjectType == AcElementType.Role) { var sType = UserAcSubjectType.Account.ToName(); var oType = AcElementType.Role.ToName(); var rolePrivileges = privilegeBigramRepository.AsQueryable().Where(a => a.SubjectType == sType && a.SubjectInstanceId == input.SubjectInstanceId && a.ObjectType == oType); var roles = new HashSet <RoleState>(); RoleState role; if (acDomain.RoleSet.TryGetRole(input.ObjectInstanceId, out role)) { roles.Add(role); } foreach (var item in rolePrivileges) { if (acDomain.RoleSet.TryGetRole(item.ObjectInstanceId, out role)) { roles.Add(role); } } // TODO:考虑上角色继承 /* * 其实就是在当前账户的角色集中元素的数目有增加时执行责任分离验证。 * 这个地方没考虑清楚。可能只考虑(Account, Role)是对的,没有办法去考虑上Catalog上的角色、Group上的角色,甚至别的Account委托过来的角色。 * 那些角色是在进入这些场景、边界之后才会并入到当前账户的角色集的,离开那个边界时就会收回。也就是说可能需要在当前活动的账户进入某个Catalog、Group、和变身为某人时执行一下职责分离约束规则。 */ string msg; if (!acDomain.SsdSetSet.CheckRoles(roles, out msg)) { throw new ValidationException(msg); } } if (subjectType == AcElementType.Catalog && acObjectType == AcElementType.Catalog) { if (input.SubjectInstanceId == input.ObjectInstanceId) { throw new ValidationException("组织机构不能继承自己"); } var descendantIds = new HashSet <Guid>(); RecDescendantCatalogs(input.SubjectInstanceId, descendantIds); if (descendantIds.Contains(input.SubjectInstanceId)) { throw new ValidationException("组织机构不能继承自己的子孙"); } } if (acDomain.PrivilegeSet.Any(a => a.ObjectType == acObjectType && a.ObjectInstanceId == input.ObjectInstanceId && a.SubjectType == subjectType && a.SubjectInstanceId == input.SubjectInstanceId)) { return; } entity = Privilege.Create(input); if (subjectType != AcElementType.Account && privilegeList.All(a => a.Id != entity.Id)) { privilegeList.Add(PrivilegeState.Create(entity)); } if (isCommand) { try { privilegeBigramRepository.Add(entity); privilegeBigramRepository.Context.Commit(); } catch { if (subjectType != AcElementType.Account && privilegeList.Any(a => a.Id == entity.Id)) { var item = privilegeList.First(a => a.Id == entity.Id); privilegeList.Remove(item); } privilegeBigramRepository.Context.Rollback(); throw; } } } if (isCommand) { acDomain.MessageDispatcher.DispatchMessage(new PrivilegeAddedEvent(acSession, entity, input, isPrivate: true)); } if (subjectType == AcElementType.Role && acObjectType == AcElementType.Role) { acDomain.MessageDispatcher.DispatchMessage(new RoleRolePrivilegeAddedEvent(acSession, entity)); } }