Browse Source

Implemented enable/disable filters.

pull/179/head
Halil İbrahim Kalkan 9 years ago
parent
commit
adf83d4e25
  1. 7
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  2. 2
      src/Volo.Abp/Volo/Abp/AbpKernelModule.cs
  3. 103
      src/Volo.Abp/Volo/Abp/Data/DataFilter.cs
  4. 7
      src/Volo.Abp/Volo/Abp/Data/DataFilterItem.cs
  5. 26
      src/Volo.Abp/Volo/Abp/Data/IDataFilter.cs
  6. 19
      src/Volo.Abp/Volo/Abp/NullDisposable.cs
  7. 23
      test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DataFiltering/MultiTenant_Filter_Tests.cs
  8. 64
      test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DataFiltering/SoftDelete_Filter_Tests.cs
  9. 26
      test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/SoftDelete_Filter_Tests.cs

7
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
@ -21,13 +22,15 @@ namespace Volo.Abp.EntityFrameworkCore
{
public Guid? CurrentTenantId => CurrentTenant?.Id;
protected virtual bool IsMayHaveTenantFilterEnabled => true; //TODO: Change this when data filtering system is full implemented
protected virtual bool IsSoftDeleteFilterEnabled => true; //TODO: Change this when data filtering system is full implemented
protected virtual bool IsMayHaveTenantFilterEnabled => DataFilter.IsEnabled<IMultiTenant>();
protected virtual bool IsSoftDeleteFilterEnabled => DataFilter.IsEnabled<ISoftDelete>();
public ICurrentTenant CurrentTenant { get; set; }
public IGuidGenerator GuidGenerator { get; set; }
public IDataFilter DataFilter { get; set; }
private static readonly MethodInfo ConfigureGlobalFiltersMethodInfo = typeof(AbpDbContext<TDbContext>).GetMethod(nameof(ConfigureGlobalFilters), BindingFlags.Instance | BindingFlags.NonPublic);
protected AbpDbContext(DbContextOptions<TDbContext> options)

2
src/Volo.Abp/Volo/Abp/AbpKernelModule.cs

@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.ApiVersioning;
using Volo.Abp.Data;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.ObjectMapping;
@ -40,6 +41,7 @@ namespace Volo.Abp
services.AddAssemblyOf<AbpKernelModule>();
services.AddSingleton<IRequestedApiVersion>(NullRequestedApiVersion.Instance);
services.AddSingleton(typeof(IDataFilter<>), typeof(DataFilter<>));
services.Configure<ModuleLifecycleOptions>(options =>
{

103
src/Volo.Abp/Volo/Abp/Data/DataFilter.cs

@ -0,0 +1,103 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Data
{
public class DataFilter : IDataFilter, ISingletonDependency
{
private readonly ConcurrentDictionary<Type, object> _filters;
private readonly IServiceProvider _serviceProvider;
public DataFilter(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
_filters = new ConcurrentDictionary<Type, object>();
}
public IDisposable Enable<TFilter>()
where TFilter : class
{
return GetFilter<TFilter>().Enable();
}
public IDisposable Disable<TFilter>()
where TFilter : class
{
return GetFilter<TFilter>().Disable();
}
public bool IsEnabled<TFilter>()
where TFilter : class
{
return GetFilter<TFilter>().IsEnabled;
}
private IDataFilter<TFilter> GetFilter<TFilter>()
where TFilter : class
{
return _filters.GetOrAdd(
typeof(TFilter),
() => _serviceProvider.GetRequiredService<IDataFilter<TFilter>>()
) as IDataFilter<TFilter>;
}
}
public class DataFilter<TFilter> : IDataFilter<TFilter>
where TFilter : class
{
public bool IsEnabled
{
get
{
EnsureInitialized();
return _filter.Value.IsEnabled;
}
}
private readonly AsyncLocal<DataFilterItem> _filter;
public DataFilter()
{
_filter = new AsyncLocal<DataFilterItem>();
}
public IDisposable Enable()
{
if (IsEnabled)
{
return NullDisposable.Instance;
}
_filter.Value.IsEnabled = true;
return new DisposeAction(() => Disable());
}
public IDisposable Disable()
{
if (!IsEnabled)
{
return NullDisposable.Instance;
}
_filter.Value.IsEnabled = false;
return new DisposeAction(() => Enable());
}
private void EnsureInitialized()
{
if (_filter.Value != null)
{
return;
}
_filter.Value = new DataFilterItem { IsEnabled = true }; //TODO: Get from default setting!
}
}
}

7
src/Volo.Abp/Volo/Abp/Data/DataFilterItem.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.Data
{
internal class DataFilterItem
{
public bool IsEnabled { get; set; }
}
}

26
src/Volo.Abp/Volo/Abp/Data/IDataFilter.cs

@ -0,0 +1,26 @@
using System;
namespace Volo.Abp.Data
{
public interface IDataFilter<TFilter>
where TFilter : class
{
IDisposable Enable();
IDisposable Disable();
bool IsEnabled { get; }
}
public interface IDataFilter
{
IDisposable Enable<TFilter>()
where TFilter : class;
IDisposable Disable<TFilter>()
where TFilter : class;
bool IsEnabled<TFilter>()
where TFilter : class;
}
}

19
src/Volo.Abp/Volo/Abp/NullDisposable.cs

@ -0,0 +1,19 @@
using System;
namespace Volo.Abp
{
internal sealed class NullDisposable : IDisposable
{
public static NullDisposable Instance { get; } = new NullDisposable();
private NullDisposable()
{
}
public void Dispose()
{
}
}
}

23
test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/MultiTenant_Filter_Tests.cs → test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DataFiltering/MultiTenant_Filter_Tests.cs

@ -1,25 +1,29 @@
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.EntityFrameworkCore.Repositories
namespace Volo.Abp.EntityFrameworkCore.DataFiltering
{
public class MultiTenant_Filter_Tests : EntityFrameworkCoreTestBase
{
private ICurrentTenant _fakeCurrentTenant;
private readonly IRepository<Person> _personRepository;
private readonly IDataFilter<IMultiTenant> _multiTenantFilter;
public MultiTenant_Filter_Tests()
{
_personRepository = GetRequiredService<IRepository<Person>>();
_multiTenantFilter = GetRequiredService<IDataFilter<IMultiTenant>>();
}
protected override void AfterAddApplication(IServiceCollection services)
@ -55,5 +59,22 @@ namespace Volo.Abp.EntityFrameworkCore.Repositories
people = await _personRepository.GetListAsync();
people.Count.ShouldBe(0);
}
[Fact]
public async Task Should_Get_All_People_When_MultiTenant_Filter_Is_Disabled()
{
List<Person> 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);
}
}
}

64
test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/DataFiltering/SoftDelete_Filter_Tests.cs

@ -0,0 +1,64 @@
using System.Linq;
using Shouldly;
using Volo.Abp.Data;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.TestApp.Domain;
using Xunit;
namespace Volo.Abp.EntityFrameworkCore.DataFiltering
{
public class SoftDelete_Filter_Tests : EntityFrameworkCoreTestBase
{
private readonly IRepository<Person> _personRepository;
private readonly IDataFilter _dataFilter;
public SoftDelete_Filter_Tests()
{
_personRepository = GetRequiredService<IRepository<Person>>();
_dataFilter = GetRequiredService<IDataFilter>();
}
[Fact]
public void Should_Not_Get_Deleted_Entities_By_Default()
{
var people = _personRepository.GetList();
people.Count.ShouldBe(1);
people.Any(p => p.Name == "Douglas").ShouldBeTrue();
}
[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<ISoftDelete>())
{
//Soft delete is disabled
people = _personRepository.GetList();
people.Any(p => !p.IsDeleted).ShouldBeTrue();
people.Any(p => p.IsDeleted).ShouldBeTrue();
using (_dataFilter.Enable<ISoftDelete>())
{
//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();
}
}
}

26
test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/SoftDelete_Filter_Tests.cs

@ -1,26 +0,0 @@
using System.Linq;
using Shouldly;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.TestApp.Domain;
using Xunit;
namespace Volo.Abp.EntityFrameworkCore.Repositories
{
public class SoftDelete_Filter_Tests : EntityFrameworkCoreTestBase
{
private readonly IRepository<Person> _personRepository;
public SoftDelete_Filter_Tests()
{
_personRepository = GetRequiredService<IRepository<Person>>();
}
[Fact]
public void Should_Not_Get_Deleted_Entities_By_Default()
{
var people = _personRepository.GetList();
people.Count.ShouldBe(1);
people.Any(p => p.Name == "Douglas").ShouldBeTrue();
}
}
}
Loading…
Cancel
Save