diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json index c608cb0c9d..22dc4880ad 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en-GB.json @@ -76,7 +76,7 @@ "Volo.Abp.Identity:010007": "You can't change your two factor setting.", "Volo.Abp.Identity:010008": "Changing the two factor setting is not allowed.", "Volo.Abp.Identity:010009": "You cannot delegate yourself!", - "Volo.Abp.Identity:010010": "The parent organisation unit ('{ParentId}') does not exist or belongs to a different tenant.", + "Volo.Abp.Identity:010010": "The parent organisation unit ('{ParentId}') does not exist or belong to a different tenant.", "Volo.Abp.Identity:010021": "Name exist: '{0}'", "Volo.Abp.Identity:010022": "Can not update a static ClaimType.", "Volo.Abp.Identity:010023": "Can not delete a static ClaimType.", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json index e69c1584cb..9c508f28ae 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json @@ -77,7 +77,7 @@ "Volo.Abp.Identity:010007": "You can't change your two factor setting.", "Volo.Abp.Identity:010008": "It's not allowed to change two factor setting.", "Volo.Abp.Identity:010009": "You can not delegate yourself.", - "Volo.Abp.Identity:010010": "The parent organization unit ('{ParentId}') does not exist or belongs to a different tenant.", + "Volo.Abp.Identity:010010": "The parent organization unit ('{ParentId}') does not exist or belong to a different tenant.", "Volo.Abp.Identity:010021": "Name exist: '{0}'.", "Volo.Abp.Identity:010022": "Can not update a static ClaimType.", "Volo.Abp.Identity:010023": "Can not delete a static ClaimType.", diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs index ed4fe22367..0a1866f6e0 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/OrganizationUnitManager.cs @@ -41,11 +41,14 @@ public class OrganizationUnitManager : DomainService [UnitOfWork] public virtual async Task CreateAsync(OrganizationUnit organizationUnit) { - await ValidateParentTenantAsync(organizationUnit.ParentId, organizationUnit.TenantId); + using (CurrentTenant.Change(organizationUnit.TenantId)) + { + await ValidateParentTenantAsync(organizationUnit.ParentId, organizationUnit.TenantId); - organizationUnit.Code = await GetNextChildCodeAsync(organizationUnit.ParentId); - await ValidateOrganizationUnitAsync(organizationUnit); - await OrganizationUnitRepository.InsertAsync(organizationUnit); + organizationUnit.Code = await GetNextChildCodeAsync(organizationUnit.ParentId); + await ValidateOrganizationUnitAsync(organizationUnit); + await OrganizationUnitRepository.InsertAsync(organizationUnit); + } } public virtual async Task UpdateAsync(OrganizationUnit organizationUnit) @@ -109,28 +112,31 @@ public class OrganizationUnitManager : DomainService return; } - await ValidateParentTenantAsync(parentId, organizationUnit.TenantId); + using (CurrentTenant.Change(organizationUnit.TenantId)) + { + await ValidateParentTenantAsync(parentId, organizationUnit.TenantId); - //Should find children before Code change - var children = await FindChildrenAsync(id, true); + //Should find children before Code change + var children = await FindChildrenAsync(id, true); - //Store old code of OU - var oldCode = organizationUnit.Code; + //Store old code of OU + var oldCode = organizationUnit.Code; - //Move OU - organizationUnit.Code = await GetNextChildCodeAsync(parentId); - organizationUnit.ParentId = parentId; + //Move OU + organizationUnit.Code = await GetNextChildCodeAsync(parentId); + organizationUnit.ParentId = parentId; - await ValidateOrganizationUnitAsync(organizationUnit); + await ValidateOrganizationUnitAsync(organizationUnit); - //Update Children Codes - foreach (var child in children) - { - child.Code = OrganizationUnit.AppendCode(organizationUnit.Code, OrganizationUnit.GetRelativeCode(child.Code, oldCode)); - await OrganizationUnitRepository.UpdateAsync(child); - } + //Update Children Codes + foreach (var child in children) + { + child.Code = OrganizationUnit.AppendCode(organizationUnit.Code, OrganizationUnit.GetRelativeCode(child.Code, oldCode)); + await OrganizationUnitRepository.UpdateAsync(child); + } - await OrganizationUnitRepository.UpdateAsync(organizationUnit); + await OrganizationUnitRepository.UpdateAsync(organizationUnit); + } } public virtual async Task GetCodeOrDefaultAsync(Guid id) @@ -165,7 +171,7 @@ public class OrganizationUnitManager : DomainService parent = await OrganizationUnitRepository.FindAsync(parentId.Value); } - if (parent == null) + if (parent == null || parent.TenantId != tenantId) { throw new BusinessException(IdentityErrorCodes.OrganizationUnitParentTenantMismatch) .WithData("ParentId", parentId); diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs index af8a0ba31a..1f37f6ed9e 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/OrganizationUnitManager_Tests.cs @@ -3,6 +3,7 @@ using Shouldly; using System; using System.Linq; using System.Threading.Tasks; +using Volo.Abp.Data; using Volo.Abp.Guids; using Volo.Abp.MultiTenancy; using Volo.Abp.Uow; @@ -20,6 +21,7 @@ public class OrganizationUnitManager_Tests : AbpIdentityDomainTestBase private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IGuidGenerator _guidGenerator; private readonly ICurrentTenant _currentTenant; + private readonly IDataFilter _dataFilter; public OrganizationUnitManager_Tests() { _organizationUnitManager = GetRequiredService(); @@ -30,6 +32,7 @@ public class OrganizationUnitManager_Tests : AbpIdentityDomainTestBase _unitOfWorkManager = GetRequiredService(); _guidGenerator = GetService(); _currentTenant = GetRequiredService(); + _dataFilter = GetRequiredService(); } [Fact] @@ -191,6 +194,27 @@ public class OrganizationUnitManager_Tests : AbpIdentityDomainTestBase loaded.ShouldNotBeNull(); loaded.ParentId.ShouldBe(tenantRoot.Id); loaded.TenantId.ShouldBe(tenantId); + loaded.Code.ShouldBe(OrganizationUnit.AppendCode(tenantRoot.Code, OrganizationUnit.CreateCode(1))); + } + } + + [Fact] + public async Task Should_Reject_Cross_Tenant_Parent_When_Multi_Tenancy_Filter_Disabled() + { + var hostOu = await _organizationUnitRepository.GetAsync("OU1"); + + using (_dataFilter.Disable()) + { + var tenantId = Guid.NewGuid(); + using (_currentTenant.Change(tenantId)) + { + var newOu = new OrganizationUnit(_guidGenerator.Create(), "Cross", hostOu.Id, tenantId); + + var ex = await Assert.ThrowsAsync( + async () => await _organizationUnitManager.CreateAsync(newOu)); + + ex.Code.ShouldBe(IdentityErrorCodes.OrganizationUnitParentTenantMismatch); + } } } }