diff --git a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs index 93be92bd09..01568ff066 100644 --- a/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs +++ b/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs @@ -61,7 +61,7 @@ namespace Volo.Abp.Domain.Repositories.MemoryDb protected override IQueryable GetQueryable() { - return Collection.AsQueryable(); + return ApplyDataFilters(Collection.AsQueryable()); } } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs b/src/Volo.Abp/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs index 32911a9af0..ad917d0684 100644 --- a/src/Volo.Abp/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs +++ b/src/Volo.Abp/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs @@ -5,7 +5,9 @@ using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; +using Volo.Abp.Data; using Volo.Abp.Domain.Entities; +using Volo.Abp.MultiTenancy; namespace Volo.Abp.Domain.Repositories { @@ -24,6 +26,10 @@ namespace Volo.Abp.Domain.Repositories public virtual IQueryProvider Provider => GetQueryable().Provider; + public IDataFilter DataFilter { get; set; } + + public ICurrentTenant CurrentTenant { get; set; } + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); @@ -64,5 +70,21 @@ namespace Volo.Abp.Domain.Repositories { return GetQueryable().LongCount(); } + + protected virtual IQueryable ApplyDataFilters(IQueryable query) + { + if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) + { + query = query.WhereIf(DataFilter.IsEnabled(), e => ((ISoftDelete)e).IsDeleted == false); + } + + if (typeof(IMultiTenant).IsAssignableFrom(typeof(TEntity))) + { + var tenantId = CurrentTenant.Id; + query = query.WhereIf(DataFilter.IsEnabled(), e => ((IMultiTenant)e).TenantId == tenantId); + } + + return query; + } } } \ No newline at end of file diff --git a/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/DataFilters/MemoryDb_SoftDelete_DataFilter_Tests.cs b/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/DataFilters/MemoryDb_SoftDelete_DataFilter_Tests.cs new file mode 100644 index 0000000000..d627dfbabd --- /dev/null +++ b/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/DataFilters/MemoryDb_SoftDelete_DataFilter_Tests.cs @@ -0,0 +1,57 @@ +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Data; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.TestApp.Domain; +using Xunit; + +namespace Volo.Abp.MemoryDb.DataFilters +{ + public class MemoryDb_SoftDelete_DataFilter_Tests : MemoryDbTestBase + { + private readonly IQueryableRepository _personRepository; + private readonly IDataFilter _dataFilter; + + public MemoryDb_SoftDelete_DataFilter_Tests() + { + _personRepository = ServiceProvider.GetRequiredService>(); + _dataFilter = GetRequiredService(); + } + + [Fact] + public void Should_Get_Deleted_Entities_When_Filter_Is_Disabled() + { + //Soft delete is enabled by default + var people = _personRepository.GetList(); + people.Any(p => !p.IsDeleted).ShouldBeTrue(); + people.Any(p => p.IsDeleted).ShouldBeFalse(); + + using (_dataFilter.Disable()) + { + //Soft delete is disabled + people = _personRepository.GetList(); + people.Any(p => !p.IsDeleted).ShouldBeTrue(); + people.Any(p => p.IsDeleted).ShouldBeTrue(); + + using (_dataFilter.Enable()) + { + //Soft delete is enabled again + people = _personRepository.GetList(); + people.Any(p => !p.IsDeleted).ShouldBeTrue(); + people.Any(p => p.IsDeleted).ShouldBeFalse(); + } + + //Soft delete is disabled (restored previous state) + people = _personRepository.GetList(); + people.Any(p => !p.IsDeleted).ShouldBeTrue(); + people.Any(p => p.IsDeleted).ShouldBeTrue(); + } + + //Soft delete is enabled (restored previous state) + people = _personRepository.GetList(); + people.Any(p => !p.IsDeleted).ShouldBeTrue(); + people.Any(p => p.IsDeleted).ShouldBeFalse(); + } + } +} diff --git a/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/DataFilters/MultiTenant_Filter_Tests.cs b/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/DataFilters/MultiTenant_Filter_Tests.cs new file mode 100644 index 0000000000..33d79461e4 --- /dev/null +++ b/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/DataFilters/MultiTenant_Filter_Tests.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using Shouldly; +using Volo.Abp.Data; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.MultiTenancy; +using Volo.Abp.TestApp; +using Volo.Abp.TestApp.Domain; +using Xunit; + +namespace Volo.Abp.MemoryDb.DataFilters +{ + public class MemoryDb_MultiTenant_Filter_Tests : MemoryDbTestBase + { + private ICurrentTenant _fakeCurrentTenant; + private readonly IRepository _personRepository; + private readonly IDataFilter _multiTenantFilter; + + public MemoryDb_MultiTenant_Filter_Tests() + { + _personRepository = GetRequiredService>(); + _multiTenantFilter = GetRequiredService>(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + _fakeCurrentTenant = Substitute.For(); + services.AddSingleton(_fakeCurrentTenant); + } + + [Fact] + public async Task Should_Get_Person_For_Current_Tenant() + { + //TenantId = null + + _fakeCurrentTenant.Id.Returns((Guid?)null); + + var people = await _personRepository.GetListAsync(); + people.Count.ShouldBe(1); + people.Any(p => p.Name == "Douglas").ShouldBeTrue(); + + //TenantId = TestDataBuilder.TenantId1 + + _fakeCurrentTenant.Id.Returns(TestDataBuilder.TenantId1); + + people = await _personRepository.GetListAsync(); + people.Count.ShouldBe(2); + people.Any(p => p.Name == TestDataBuilder.TenantId1 + "-Person1").ShouldBeTrue(); + people.Any(p => p.Name == TestDataBuilder.TenantId1 + "-Person2").ShouldBeTrue(); + + //TenantId = TestDataBuilder.TenantId2 + + _fakeCurrentTenant.Id.Returns(TestDataBuilder.TenantId2); + + people = await _personRepository.GetListAsync(); + people.Count.ShouldBe(0); + } + + [Fact] + public async Task Should_Get_All_People_When_MultiTenant_Filter_Is_Disabled() + { + List people; + + using (_multiTenantFilter.Disable()) + { + //Filter disabled manually + people = await _personRepository.GetListAsync(); + people.Count.ShouldBe(3); + } + + //Filter re-enabled automatically + people = await _personRepository.GetListAsync(); + people.Count.ShouldBe(1); + } + } +}