Browse Source

Merge pull request #376 from colinin/4.4.1

feat(data): 添加数据访问保护模块(仅供参考)
pull/396/head
yx lin 4 years ago
committed by GitHub
parent
commit
57f18c7afd
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      aspnet-core/LINGYUN.MicroService.Common.sln
  2. 17
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN.Abp.DataProtection.EntityFrameworkCore.csproj
  3. 14
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/AbpDataProtectionDbContext.cs
  4. 12
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/AbpDataProtectionEntityFrameworkCoreModule.cs
  5. 358
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/DataProtectionAsyncQueryableProvider.cs
  6. 297
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/EfCoreDataProtectionRepositoryBase.cs
  7. 19
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/ProtectedEntityHelper.cs
  8. 14
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN.Abp.DataProtection.csproj
  9. 11
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/AbpDataProtectionModule.cs
  10. 352
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/DataProtectionAsyncQueryableProvider.cs
  11. 12
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ExpressionType.cs
  12. 19
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/IDataProtectdChecker.cs
  13. 11
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/IDataProtection.cs
  14. 29
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ProtectBehavior.cs
  15. 22
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ProtectedField.cs
  16. 40
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ProtectedFieldRule.cs
  17. 27
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ProtectedResource.cs
  18. 19
      aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ResourceGrantedResult.cs
  19. 28
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN.Abp.DataProtection.Tests.csproj
  20. 9
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/AbpDataProtectionTestBase.cs
  21. 21
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/AbpDataProtectionTestModule.cs
  22. 16
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/EfCoreFakeProtectionObjectRepository.cs
  23. 25
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/FakeDataProtectdChecker.cs
  24. 24
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/FakeDataProtectedDbContext.cs
  25. 16
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/FakeProtectionObject.cs
  26. 8
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/IFakeProtectionObjectRepository.cs
  27. 297
      aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/ProtectionFieldTests.cs
  28. 118
      aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBase.cs

31
aspnet-core/LINGYUN.MicroService.Common.sln

@ -182,6 +182,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Localization.Dy
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Data.DbMigrator", "modules\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj", "{3993A315-B250-4C5D-98C7-90FD06841B66}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "data-protection", "data-protection", "{A0910407-CE69-4DC8-9721-F4324C22EEA8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection", "modules\data-protection\LINGYUN.Abp.DataProtection\LINGYUN.Abp.DataProtection.csproj", "{519BF5DA-30E4-40CF-829A-93F526E2AED8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.DataProtection.EntityFrameworkCore", "modules\data-protection\LINGYUN.Abp.DataProtection.EntityFrameworkCore\LINGYUN.Abp.DataProtection.EntityFrameworkCore.csproj", "{E16CCB14-E629-48E6-9603-53BBFF185318}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.DataProtection.Tests", "tests\LINGYUN.Abp.DataProtection.Tests\LINGYUN.Abp.DataProtection.Tests.csproj", "{FBE7D8CB-1D99-4342-A953-B9AB46E0B14D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj", "{2F556889-006C-4A9C-8CA3-E31200C06FC9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -472,6 +482,22 @@ Global
{3993A315-B250-4C5D-98C7-90FD06841B66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3993A315-B250-4C5D-98C7-90FD06841B66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3993A315-B250-4C5D-98C7-90FD06841B66}.Release|Any CPU.Build.0 = Release|Any CPU
{519BF5DA-30E4-40CF-829A-93F526E2AED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{519BF5DA-30E4-40CF-829A-93F526E2AED8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{519BF5DA-30E4-40CF-829A-93F526E2AED8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{519BF5DA-30E4-40CF-829A-93F526E2AED8}.Release|Any CPU.Build.0 = Release|Any CPU
{E16CCB14-E629-48E6-9603-53BBFF185318}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E16CCB14-E629-48E6-9603-53BBFF185318}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E16CCB14-E629-48E6-9603-53BBFF185318}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E16CCB14-E629-48E6-9603-53BBFF185318}.Release|Any CPU.Build.0 = Release|Any CPU
{FBE7D8CB-1D99-4342-A953-B9AB46E0B14D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FBE7D8CB-1D99-4342-A953-B9AB46E0B14D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FBE7D8CB-1D99-4342-A953-B9AB46E0B14D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FBE7D8CB-1D99-4342-A953-B9AB46E0B14D}.Release|Any CPU.Build.0 = Release|Any CPU
{2F556889-006C-4A9C-8CA3-E31200C06FC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F556889-006C-4A9C-8CA3-E31200C06FC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F556889-006C-4A9C-8CA3-E31200C06FC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F556889-006C-4A9C-8CA3-E31200C06FC9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -563,6 +589,11 @@ Global
{CCB4AE25-7059-4CA0-A3AB-CBB863A3F672} = {23F4260D-87C1-4AA6-A302-0A8A76D53BA1}
{4635BDFB-B647-43E2-BAA5-D3C17899AF24} = {E73A0F8B-2B4B-4CED-82A4-1EE5E0B89744}
{3993A315-B250-4C5D-98C7-90FD06841B66} = {086BE5BE-8594-4DA7-8819-935FEF76DABD}
{A0910407-CE69-4DC8-9721-F4324C22EEA8} = {02EA4E78-5891-43BC-944F-3E52FEE032E4}
{519BF5DA-30E4-40CF-829A-93F526E2AED8} = {A0910407-CE69-4DC8-9721-F4324C22EEA8}
{E16CCB14-E629-48E6-9603-53BBFF185318} = {A0910407-CE69-4DC8-9721-F4324C22EEA8}
{FBE7D8CB-1D99-4342-A953-B9AB46E0B14D} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
{2F556889-006C-4A9C-8CA3-E31200C06FC9} = {B86C21A4-73B7-471E-B73A-B4B905EC9435}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8}

17
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN.Abp.DataProtection.EntityFrameworkCore.csproj

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>9.0</LangVersion>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="4.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.DataProtection\LINGYUN.Abp.DataProtection.csproj" />
</ItemGroup>
</Project>

14
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/AbpDataProtectionDbContext.cs

@ -0,0 +1,14 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore
{
public class AbpDataProtectionDbContext<TDbContext> : AbpDbContext<TDbContext>
where TDbContext : DbContext
{
public AbpDataProtectionDbContext(
DbContextOptions<TDbContext> options) : base(options)
{
}
}
}

12
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/AbpDataProtectionEntityFrameworkCoreModule.cs

@ -0,0 +1,12 @@
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore
{
[DependsOn(
typeof(AbpDataProtectionModule),
typeof(AbpEntityFrameworkCoreModule))]
public class AbpDataProtectionEntityFrameworkCoreModule : AbpModule
{
}
}

358
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/DataProtectionAsyncQueryableProvider.cs

@ -0,0 +1,358 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Linq;
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore
{
/// <summary>
/// TODO: 需要实现动态数据权限规则
/// </summary>
[Dependency(ReplaceServices = true)]
public class DataProtectionAsyncQueryableProvider : IAsyncQueryableProvider, ISingletonDependency
{
public bool CanExecute<T>(IQueryable<T> queryable)
{
return queryable.Provider is EntityQueryProvider;
}
public Task<bool> ContainsAsync<T>(IQueryable<T> queryable, T item, CancellationToken cancellationToken = default)
{
return queryable.ContainsAsync(item, cancellationToken);
}
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.AnyAsync(cancellationToken);
}
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.AnyAsync(predicate, cancellationToken);
}
public Task<bool> AllAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.AllAsync(predicate, cancellationToken);
}
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.CountAsync(cancellationToken);
}
public Task<int> CountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.CountAsync(predicate, cancellationToken);
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.LongCountAsync(cancellationToken);
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.LongCountAsync(predicate, cancellationToken);
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.FirstAsync(cancellationToken);
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.FirstAsync(predicate, cancellationToken);
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.FirstOrDefaultAsync(cancellationToken);
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return queryable.FirstOrDefaultAsync(predicate, cancellationToken);
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.LastAsync(cancellationToken);
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.LastAsync(predicate, cancellationToken);
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.LastOrDefaultAsync(cancellationToken);
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return queryable.LastOrDefaultAsync(predicate, cancellationToken);
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.SingleAsync(cancellationToken);
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
return queryable.SingleAsync(predicate, cancellationToken);
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.SingleOrDefaultAsync(cancellationToken);
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
return queryable.SingleOrDefaultAsync(predicate, cancellationToken);
}
public Task<T> MinAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.MinAsync(cancellationToken);
}
public Task<TResult> MinAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
return queryable.MinAsync(selector, cancellationToken);
}
public Task<T> MaxAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.MaxAsync(cancellationToken);
}
public Task<TResult> MaxAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
return queryable.MaxAsync(selector, cancellationToken);
}
public Task<decimal> SumAsync(IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<decimal?> SumAsync(IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<decimal> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<decimal?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<int> SumAsync(IQueryable<int> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<int?> SumAsync(IQueryable<int?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<int> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<int?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<long> SumAsync(IQueryable<long> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<long?> SumAsync(IQueryable<long?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<long> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<long?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<double> SumAsync(IQueryable<double> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<double?> SumAsync(IQueryable<double?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<double> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<double?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<float> SumAsync(IQueryable<float> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<float?> SumAsync(IQueryable<float?> queryable, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(cancellationToken);
}
public Task<float> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<float?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
return queryable.SumAsync(selector, cancellationToken);
}
public Task<decimal> AverageAsync(IQueryable<decimal> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<decimal?> AverageAsync(IQueryable<decimal?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<decimal> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<decimal?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<int> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<int?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<long> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<long?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double> AverageAsync(IQueryable<double> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double?> AverageAsync(IQueryable<double?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<float> AverageAsync(IQueryable<float> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<float?> AverageAsync(IQueryable<float?> queryable, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(cancellationToken);
}
public Task<float> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<float?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
return queryable.AverageAsync(selector, cancellationToken);
}
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.ToListAsync(cancellationToken);
}
public Task<T[]> ToArrayAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
return queryable.ToArrayAsync(cancellationToken);
}
}
}

297
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/EfCoreDataProtectionRepositoryBase.cs

@ -0,0 +1,297 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Users;
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore
{
/// <summary>
/// 受保护的资源仓储接口需要继承此接口,否则需要自行实现过滤器
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
/// <typeparam name="TEntity"></typeparam>
/// <typeparam name="TKey"></typeparam>
public abstract class EfCoreDataProtectionRepositoryBase<TDbContext, TEntity, TKey> : EfCoreRepository<TDbContext, TEntity, TKey>
where TEntity : class, IEntity<TKey>, IDataProtection
where TDbContext: IEfCoreDbContext
{
protected ICurrentUser CurrentUser => LazyServiceProvider.LazyGetService<ICurrentUser>();
protected IDataProtectdChecker DataProtectdChecker => LazyServiceProvider.LazyGetService<IDataProtectdChecker>();
protected EfCoreDataProtectionRepositoryBase(
IDbContextProvider<TDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public override async Task<TEntity> InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default)
{
if (CurrentUser.IsAuthenticated &&
entity is IDataProtection protectedEntity)
{
ProtectedEntityHelper.TrySetOwner(
protectedEntity,
() => string.Join(",", CurrentUser.UserName, CurrentUser.Roles.JoinAsString(",")));
}
return await base.InsertAsync(entity, autoSave, cancellationToken);
}
public override async Task InsertManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, CancellationToken cancellationToken = default)
{
if (CurrentUser.IsAuthenticated &&
typeof(IDataProtection).IsAssignableFrom(typeof(TEntity)))
{
foreach (var entity in entities)
{
ProtectedEntityHelper.TrySetOwner(
entity,
() => string.Join(",", CurrentUser.UserName, CurrentUser.Roles.JoinAsString(",")));
}
}
await base.InsertManyAsync(entities, autoSave, cancellationToken);
}
public override async Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
{
return includeDetails
? await(await WithDetailsAsync(ProtectBehavior.Query)).ToListAsync(GetCancellationToken(cancellationToken))
: await(await GetQueryableAsync(ProtectBehavior.Query)).ToListAsync(GetCancellationToken(cancellationToken));
}
public override async Task<TEntity> FindAsync(TKey id, bool includeDetails = true, CancellationToken cancellationToken = default)
{
return includeDetails
? await(await WithDetailsAsync(ProtectBehavior.Query)).OrderBy(e => e.Id).FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken))
: await(await GetQueryableAsync(ProtectBehavior.Query)).OrderBy(e => e.Id).FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken));
}
public override async Task<List<TEntity>> GetListAsync(
Expression<Func<TEntity, bool>> predicate,
bool includeDetails = false,
CancellationToken cancellationToken = default)
{
return includeDetails
? await (await WithDetailsAsync(ProtectBehavior.Query)).Where(predicate).ToListAsync(GetCancellationToken(cancellationToken))
: await (await GetQueryableAsync(ProtectBehavior.Query)).Where(predicate).ToListAsync(GetCancellationToken(cancellationToken));
}
public override async Task DeleteAsync(TKey id, bool autoSave = false, CancellationToken cancellationToken = default)
{
var queryable = await GetQueryableAsync(ProtectBehavior.Delete);
var entity = await queryable
.FirstOrDefaultAsync(e => e.Id.Equals(id), GetCancellationToken(cancellationToken));
if (entity == null)
{
return;
}
await DeleteAsync(entity, autoSave, cancellationToken);
}
public override async Task DeleteManyAsync(IEnumerable<TKey> ids, bool autoSave = false, CancellationToken cancellationToken = default)
{
var queryable = await GetQueryableAsync(ProtectBehavior.Delete);
var entities = await queryable.Where(x => ids.Contains(x.Id)).ToListAsync(cancellationToken);
await DeleteManyAsync(entities, autoSave, cancellationToken);
}
public override async Task DeleteAsync(
Expression<Func<TEntity, bool>> predicate,
bool autoSave = false,
CancellationToken cancellationToken = default)
{
var queryable = await GetQueryableAsync(ProtectBehavior.Delete);
var entities = await queryable.Where(predicate).ToListAsync(cancellationToken);
await DeleteManyAsync(entities, autoSave, cancellationToken);
}
protected virtual async Task<IQueryable<TEntity>> WithDetailsAsync(ProtectBehavior behavior = ProtectBehavior.All)
{
if (typeof(IDataProtection).IsAssignableFrom(typeof(TEntity)))
{
var result = await DataProtectdChecker.IsGrantedAsync<TEntity>(behavior);
if (!result.Succeeded)
{
var queryable = await base.GetQueryableAsync();
return queryable.Where((t) => false);
}
return await WithDetailsAsync(result);
}
return await base.WithDetailsAsync();
}
protected virtual async Task<IQueryable<TEntity>> WithDetailsAsync(ResourceGrantedResult resourceGranted)
{
if (AbpEntityOptions.DefaultWithDetailsFunc == null)
{
return await GetQueryableAsync(resourceGranted);
}
return AbpEntityOptions.DefaultWithDetailsFunc(await GetQueryableAsync(resourceGranted));
}
protected virtual async Task<IQueryable<TEntity>> GetQueryableAsync(ProtectBehavior behavior = ProtectBehavior.All)
{
if (typeof(IDataProtection).IsAssignableFrom(typeof(TEntity)))
{
var result = await DataProtectdChecker.IsGrantedAsync<TEntity>(behavior);
if (!result.Succeeded)
{
var queryable = await base.GetQueryableAsync();
return queryable.Where((t) => false);
}
return await GetQueryableAsync(result);
}
return await base.GetQueryableAsync();
}
protected virtual async Task<IQueryable<TEntity>> GetQueryableAsync(ResourceGrantedResult resourceGranted)
{
var queryable = await base.GetQueryableAsync();
if (!resourceGranted.Succeeded)
{
// 无资源访问权限, 不返回结果
return queryable.Where((t) => false);
}
// 资源过滤,用户是否有对某个资源的访问权限
// 方案1、Resource.Owner In ("user1", "user2", "role1", "role2", "organization1", "...") 独立模块,业务增加Owner字段
// 方案2、Select R.* From Resource R Inner Join Protect T On T.Visitor = R.Owner Where T.Resource = 'Resource' 业务侵入,增加Protect表
queryable = FilterResource(queryable, resourceGranted.Resource);
// 对于可访问资源的进一步动态规则过滤 1 == 1 And Resource.Field1 = 'allow' And Resource.Field2 >= 100 And Resource.Field2 <= 200
queryable = FilterFieldRule(queryable, resourceGranted.Rules);
// 对于资源可访问字段过滤 Select Resource.Field1, Resource.Field2, Resource.Field3
queryable = FilterFieldReturn(queryable, resourceGranted.Fields);
return queryable;
}
protected virtual IQueryable<T> FilterResource<T>(IQueryable<T> queryable, ProtectedResource resource)
where T : IDataProtection
{
ParameterExpression pe = Expression.Parameter(typeof(T));
// 检查资源的可访问者
// any: 内置常量,允许访问所有资源
if (!resource.Visitor.IsNullOrWhiteSpace() || !resource.Visitor.Contains("any"))
{
// 过滤允许的资源访问者
// 方案一:模块之间独立,传递当前访问者即可
// Select * From Resource As R Where R.Owner LIKE ('visitor1', 'visitorRole1')
var ownerExp = Expression.PropertyOrField(pe, nameof(IDataProtection.Owner));
var visities = resource.Visitor.Split(',');
Expression visitorExpr = null;
foreach (var visitor in visities)
{
visitorExpr = visitorExpr == null
? Expression.Call(
ownerExp,
typeof(string).GetMethod(nameof(string.Contains), new Type[] { typeof(string) }),
Expression.Constant(visitor, ownerExp.Type))
: Expression.Or(
visitorExpr,
Expression.Call(
ownerExp,
typeof(string).GetMethod(nameof(string.Contains), new Type[] { typeof(string) }),
Expression.Constant(visitor, ownerExp.Type)));
}
// 方案二:节省网络带宽,快速查询
// Select R.* From Resource As R
// Inner Join Protect As P On P.Resource = 'Resource'
// Where 1 == 1
// And P.Behavior = ProtectBehavior.Query
// And ((P.Visitor = 'visitor1') Or (P.Visitor = 'visitorRole1') Or (P.Visitor = 'visitorRole2'))
queryable = queryable.Where(Expression.Lambda<Func<T, bool>>(visitorExpr, pe));
}
return queryable;
}
protected virtual IQueryable<T> FilterFieldRule<T>(IQueryable<T> queryable, IEnumerable<ProtectedFieldRule> rules)
where T : IDataProtection
{
ParameterExpression pe = Expression.Parameter(typeof(T));
// 默认未指定访问规则
// 则可访问所有允许的资源
if (rules.Any())
{
Expression<Func<T, bool>> where = PredicateBuilder.New<T>((t) => true);
foreach (var fieldRule in rules)
{
var memberExp = Expression.PropertyOrField(pe, fieldRule.Field);
Expression memberCondition = null;
memberCondition = fieldRule.Operator switch
{
// LIKE
ExpressionType.Contains => Expression.Call(
memberExp,
typeof(string).GetMethod(nameof(string.Contains), new Type[] { typeof(string) }),
Expression.Constant(fieldRule.Value, memberExp.Type)),
// ==
ExpressionType.Equal => Expression.Equal(memberExp, Expression.Constant(fieldRule.Value, memberExp.Type)),
// <
ExpressionType.LessThan => Expression.LessThan(memberExp, Expression.Constant(fieldRule.Value, memberExp.Type)),
// <=
ExpressionType.LessThanOrEqual => Expression.LessThanOrEqual(memberExp, Expression.Constant(fieldRule.Value, memberExp.Type)),
// >
ExpressionType.GreaterThan => Expression.GreaterThan(memberExp, Expression.Constant(fieldRule.Value, memberExp.Type)),
// >=
ExpressionType.GreaterThanOrEqual => Expression.GreaterThanOrEqual(memberExp, Expression.Constant(fieldRule.Value, memberExp.Type)),
// 其他操作符未引入
_ => throw new NotSupportedException($"Dynamic rules do not support operator: {fieldRule.Operator}"),
};
switch (fieldRule.Logic)
{
case PredicateOperator.And:
where = where.And(Expression.Lambda<Func<T, bool>>(memberCondition, pe));
break;
case PredicateOperator.Or:
where = where.Or(Expression.Lambda<Func<T, bool>>(memberCondition, pe));
break;
}
}
queryable = queryable.Where(where);
}
return queryable;
}
protected virtual IQueryable<T> FilterFieldReturn<T>(IQueryable<T> queryable, IEnumerable<ProtectedField> fields)
{
// 默认未指定可访问字段则返回所有字段
if (fields.Any())
{
ParameterExpression pe = Expression.Parameter(typeof(T));
Type queryableResultType = typeof(T);
NewExpression ne = Expression.New(queryableResultType);
List<MemberAssignment> members = new List<MemberAssignment>();
foreach (var field in fields)
{
var fieldProp = queryableResultType.GetProperty(field.Field);
var meField = Expression.MakeMemberAccess(pe, fieldProp);
members.Add(Expression.Bind(fieldProp, meField));
}
var mie = Expression.MemberInit(ne, members);
Expression<Func<T, T>> personSelectExpression = Expression.Lambda<Func<T, T>>(mie, pe);
queryable = queryable.Select(personSelectExpression);
}
return queryable;
}
}
}

19
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection.EntityFrameworkCore/LINGYUN/Abp/DataProtection/EntityFrameworkCore/ProtectedEntityHelper.cs

@ -0,0 +1,19 @@
using System;
using Volo.Abp;
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore
{
public static class ProtectedEntityHelper
{
public static void TrySetOwner(
IDataProtection protectedEntity,
Func<string> ownerFactory)
{
ObjectHelper.TrySetProperty(
protectedEntity,
x => x.Owner,
ownerFactory,
new Type[] { });
}
}
}

14
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN.Abp.DataProtection.csproj

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Threading" Version="4.4.0" />
</ItemGroup>
</Project>

11
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/AbpDataProtectionModule.cs

@ -0,0 +1,11 @@
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.DataProtection
{
[DependsOn(
typeof(AbpThreadingModule))]
public class AbpDataProtectionModule : AbpModule
{
}
}

352
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/DataProtectionAsyncQueryableProvider.cs

@ -0,0 +1,352 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Linq;
namespace LINGYUN.Abp.DataProtection
{
public class DataProtectionAsyncQueryableProvider : IAsyncQueryableProvider
{
public Task<bool> AllAsync<T>(
IQueryable<T> queryable,
Expression<Func<T, bool>> predicate,
CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<bool> AnyAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<decimal> AverageAsync(IQueryable<decimal> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<decimal?> AverageAsync(IQueryable<decimal?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<decimal> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<decimal?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double> AverageAsync(IQueryable<int> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double?> AverageAsync(IQueryable<int?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double> AverageAsync(IQueryable<long> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double?> AverageAsync(IQueryable<long?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double> AverageAsync(IQueryable<double> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double?> AverageAsync(IQueryable<double?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<float> AverageAsync(IQueryable<float> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<float?> AverageAsync(IQueryable<float?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<float> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<float?> AverageAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public bool CanExecute<T>(IQueryable<T> queryable)
{
throw new NotImplementedException();
}
public Task<bool> ContainsAsync<T>(IQueryable<T> queryable, T item, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<int> CountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<int> CountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> FirstAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> LastAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> LastOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<long> LongCountAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> MaxAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<TResult> MaxAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> MinAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<TResult> MinAsync<T, TResult>(IQueryable<T> queryable, Expression<Func<T, TResult>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> SingleAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T> SingleOrDefaultAsync<T>(IQueryable<T> queryable, Expression<Func<T, bool>> predicate, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<decimal> SumAsync(IQueryable<decimal> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<decimal?> SumAsync(IQueryable<decimal?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<decimal> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<decimal?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, decimal?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<int> SumAsync(IQueryable<int> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<int?> SumAsync(IQueryable<int?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<int> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<int?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, int?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<long> SumAsync(IQueryable<long> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<long?> SumAsync(IQueryable<long?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<long> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<long?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, long?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double> SumAsync(IQueryable<double> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double?> SumAsync(IQueryable<double?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<double?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, double?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<float> SumAsync(IQueryable<float> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<float?> SumAsync(IQueryable<float?> source, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<float> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<float?> SumAsync<T>(IQueryable<T> queryable, Expression<Func<T, float?>> selector, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<T[]> ToArrayAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken = default)
{
throw new NotImplementedException();
}
}
}

12
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ExpressionType.cs

@ -0,0 +1,12 @@
namespace LINGYUN.Abp.DataProtection
{
public enum ExpressionType
{
Contains,
Equal,
LessThan,
LessThanOrEqual,
GreaterThan,
GreaterThanOrEqual,
}
}

19
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/IDataProtectdChecker.cs

@ -0,0 +1,19 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.DataProtection
{
/// <summary>
/// 实现此接口
/// 检查资源的访问权限
/// </summary>
public interface IDataProtectdChecker
{
/// <summary>
/// 资源是否拥有某种行为的访问权限
/// </summary>
/// <typeparam name="T">受保护的资源(实体)</typeparam>
/// <param name="behavior">访问行为</param>
/// <returns>不管是否拥有访问权限,请返回非空结果,由EF模块检查</returns>
Task<ResourceGrantedResult> IsGrantedAsync<T>(ProtectBehavior behavior = ProtectBehavior.All);
}
}

11
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/IDataProtection.cs

@ -0,0 +1,11 @@
namespace LINGYUN.Abp.DataProtection
{
/// <summary>
/// 实现接口
/// 数据访问保护
/// </summary>
public interface IDataProtection
{
string Owner { get; }
}
}

29
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ProtectBehavior.cs

@ -0,0 +1,29 @@
namespace LINGYUN.Abp.DataProtection
{
/// <summary>
/// 保护行为
/// </summary>
public enum ProtectBehavior
{
/// <summary>
/// 所有
/// </summary>
All,
/// <summary>
/// 查询
/// </summary>
Query,
/// <summary>
/// 新增
/// </summary>
Insert,
/// <summary>
/// 修改
/// </summary>
Update,
/// <summary>
/// 删除
/// </summary>
Delete
}
}

22
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ProtectedField.cs

@ -0,0 +1,22 @@
namespace LINGYUN.Abp.DataProtection
{
public class ProtectedField
{
/// <summary>
/// 资源
/// </summary>
public string Resource { get; set; }
/// <summary>
/// 资源拥有者
/// </summary>
public string Owner { get; set; }
/// <summary>
/// 资源访问者
/// </summary>
public string Visitor { get; set; }
/// <summary>
/// 字段
/// </summary>
public string Field { get; set; }
}
}

40
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ProtectedFieldRule.cs

@ -0,0 +1,40 @@
using System;
using System.Linq;
using System.Linq.Expressions;
namespace LINGYUN.Abp.DataProtection
{
public class ProtectedFieldRule
{
/// <summary>
/// 资源
/// </summary>
public string Resource { get; set; }
/// <summary>
/// 资源拥有者
/// </summary>
public string Owner { get; set; }
/// <summary>
/// 资源访问者
/// </summary>
public string Visitor { get; set; }
/// <summary>
/// 字段
/// </summary>
public string Field { get; set; }
/// <summary>
/// 值
/// </summary>
public object Value { get; set; }
/// <summary>
/// 连接类型
/// Or 或
/// And 且
/// </summary>
public PredicateOperator Logic { get; set; }
/// <summary>
/// 操作符
/// </summary>
public ExpressionType Operator { get; set; }
}
}

27
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ProtectedResource.cs

@ -0,0 +1,27 @@
namespace LINGYUN.Abp.DataProtection
{
public class ProtectedResource
{
/// <summary>
/// 资源
/// </summary>
public string Resource { get; set; }
/// <summary>
/// 资源拥有者
/// </summary>
public string Owner { get; set; }
/// <summary>
/// 资源访问者
/// </summary>
public string Visitor { get; set; }
/// <summary>
/// 优先级
/// 值越大排名越靠前
/// </summary>
public int Priority { get; set; }
/// <summary>
/// 行为
/// </summary>
public ProtectBehavior Behavior { get; set; }
}
}

19
aspnet-core/modules/data-protection/LINGYUN.Abp.DataProtection/LINGYUN/Abp/DataProtection/ResourceGrantedResult.cs

@ -0,0 +1,19 @@
namespace LINGYUN.Abp.DataProtection
{
public class ResourceGrantedResult
{
public bool Succeeded => Resource != null;
public ProtectedResource Resource { get; }
public ProtectedField[] Fields { get; }
public ProtectedFieldRule[] Rules { get; }
public ResourceGrantedResult(
ProtectedResource resource,
ProtectedField[] fields,
ProtectedFieldRule[] rules)
{
Resource = resource;
Fields = fields;
Rules = rules;
}
}
}

28
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN.Abp.DataProtection.Tests.csproj

@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\data-protection\LINGYUN.Abp.DataProtection.EntityFrameworkCore\LINGYUN.Abp.DataProtection.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" />
</ItemGroup>
</Project>

9
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/AbpDataProtectionTestBase.cs

@ -0,0 +1,9 @@
using LINGYUN.Abp.Tests;
namespace LINGYUN.Abp.DataProtection
{
public abstract class AbpDataProtectionTestBase : AbpTestsBase<AbpDataProtectionTestModule>
{
}
}

21
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/AbpDataProtectionTestModule.cs

@ -0,0 +1,21 @@
using LINGYUN.Abp.DataProtection.EntityFrameworkCore;
using LINGYUN.Abp.EntityFrameworkCore.Tests;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.DataProtection
{
[DependsOn(
typeof(AbpDataProtectionEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreTestModule))]
public class AbpDataProtectionTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<FakeDataProtectedDbContext>(options =>
{
options.AddRepository<FakeProtectionObject, EfCoreFakeProtectionObjectRepository>();
});
}
}
}

16
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/EfCoreFakeProtectionObjectRepository.cs

@ -0,0 +1,16 @@
using LINGYUN.Abp.DataProtection.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.DataProtection
{
public class EfCoreFakeProtectionObjectRepository :
EfCoreDataProtectionRepositoryBase<FakeDataProtectedDbContext, FakeProtectionObject, int>,
IFakeProtectionObjectRepository
{
public EfCoreFakeProtectionObjectRepository(
IDbContextProvider<FakeDataProtectedDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}
}

25
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/FakeDataProtectdChecker.cs

@ -0,0 +1,25 @@
using System;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.DataProtection
{
public class FakeDataProtectdChecker : IDataProtectdChecker, ISingletonDependency
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
public FakeDataProtectdChecker(IUnitOfWorkManager unitOfWorkManager)
{
_unitOfWorkManager = unitOfWorkManager;
}
public virtual Task<ResourceGrantedResult> IsGrantedAsync<T>(ProtectBehavior behavior = ProtectBehavior.All)
{
var cacheItem = _unitOfWorkManager.Current.Items["ResourceGranted"];
var result = cacheItem.As<ResourceGrantedResult>();
return Task.FromResult(result);
}
}
}

24
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/FakeDataProtectedDbContext.cs

@ -0,0 +1,24 @@
using LINGYUN.Abp.DataProtection.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace LINGYUN.Abp.DataProtection
{
public class FakeDataProtectedDbContext : AbpDataProtectionDbContext<FakeDataProtectedDbContext>
{
public FakeDataProtectedDbContext(
DbContextOptions<FakeDataProtectedDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<FakeProtectionObject>(b =>
{
b.Property(p => p.Owner).HasColumnName(nameof(IDataProtection.Owner)).HasMaxLength(200);
});
}
}
}

16
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/FakeProtectionObject.cs

@ -0,0 +1,16 @@
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.DataProtection
{
public class FakeProtectionObject : Entity<int>, IDataProtection
{
public virtual string Owner { get; set; }
public virtual string Protect1 { get; set; }
public virtual string Protect2 { get; set; }
public virtual string Value1 { get; set; }
public virtual string Value2 { get; set; }
public virtual int ProtectNum1 { get; set; }
public virtual int ProtectNum2 { get; set; }
public virtual int Num3 { get; set; }
}
}

8
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/IFakeProtectionObjectRepository.cs

@ -0,0 +1,8 @@
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.DataProtection
{
public interface IFakeProtectionObjectRepository : IBasicRepository<FakeProtectionObject, int>
{
}
}

297
aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN/Abp/DataProtection/ProtectionFieldTests.cs

@ -0,0 +1,297 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Volo.Abp.Security.Claims;
using System.Security.Claims;
using System;
using Shouldly;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.DataProtection
{
public class ProtectionFieldTests : AbpDataProtectionTestBase
{
private readonly IFakeProtectionObjectRepository _repository;
private readonly ICurrentPrincipalAccessor _accessor;
public ProtectionFieldTests()
{
_repository = GetRequiredService<IFakeProtectionObjectRepository>();
_accessor = GetRequiredService<ICurrentPrincipalAccessor>();
}
[Fact]
public virtual async Task FakeAsync()
{
var values = new List<FakeProtectionObject>()
{
new FakeProtectionObject
{
Protect1 = "Protect1",
Protect2 = "Protect1",
Value1 = "Value1",
Value2 = "Value1",
ProtectNum1 = 100,
ProtectNum2 = 200,
Num3 = 400
},
new FakeProtectionObject
{
Protect1 = "test",
Protect2 = "Protect2",
Value1 = "Value2",
Value2 = "Value2",
ProtectNum1 = 1000,
ProtectNum2 = 2000,
Num3 = 3000
},
new FakeProtectionObject
{
Protect1 = "test1",
Protect2 = "Protect3",
Value1 = "Value3",
Value2 = "Value3",
ProtectNum1 = 10000,
ProtectNum2 = 20000,
Num3 = 300
},
new FakeProtectionObject
{
Protect1 = "test3",
Protect2 = "Protect4",
Value1 = "Value4",
Value2 = "Value4",
ProtectNum1 = 10000,
ProtectNum2 = 20000,
Num3 = 300
}
};
await WithUnitOfWorkAsync(async () =>
{
var resource = new ProtectedResource
{
Resource = typeof(FakeProtectionObject).FullName,
Behavior = ProtectBehavior.All,
Owner = "user1",
Priority = 10,
Visitor = "user1,role1"
};
var fields = new List<ProtectedField>()
{
new ProtectedField
{
Field = nameof(FakeProtectionObject.Num3),
Owner = "user1",
Resource = resource.Resource,
Visitor = "",
},
new ProtectedField
{
Field = nameof(FakeProtectionObject.Value1),
Owner = "user2",
Resource = resource.Resource,
Visitor = "",
},
new ProtectedField
{
Field = nameof(FakeProtectionObject.Value2),
Owner = "user1",
Resource = resource.Resource,
Visitor = "",
},
new ProtectedField
{
Field = nameof(FakeProtectionObject.Protect1),
Owner = "role1",
Resource = resource.Resource,
Visitor = "",
},
};
var rules = new List<ProtectedFieldRule>()
{
new ProtectedFieldRule
{
Field = nameof(FakeProtectionObject.Protect1),
Logic = PredicateOperator.And,
Operator = ExpressionType.Equal,
Resource = resource.Resource,
Value = "test"
},
new ProtectedFieldRule
{
Field = nameof(FakeProtectionObject.Num3),
Logic = PredicateOperator.Or,
Operator = ExpressionType.LessThanOrEqual,
Resource = resource.Resource,
Value = 300
},
};
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
unitOfWorkManager.Current.AddItem<ResourceGrantedResult>(
"ResourceGranted",
new ResourceGrantedResult(
resource,
fields.ToArray(),
rules.ToArray()));
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()));
identity.AddClaim(new Claim(AbpClaimTypes.UserName, "user1"));
identity.AddClaim(new Claim(AbpClaimTypes.Role, "role1"));
identity.AddClaim(new Claim(AbpClaimTypes.Role, "role2"));
using (_accessor.Change(new ClaimsPrincipal(identity)))
{
await _repository.InsertManyAsync(values, true);
}
});
await WithUnitOfWorkAsync(async () =>
{
var resource = new ProtectedResource
{
Resource = typeof(FakeProtectionObject).FullName,
Behavior = ProtectBehavior.All,
Owner = "user1",
Priority = 10,
Visitor = "user1,role1"
};
var fields = new List<ProtectedField>()
{
new ProtectedField
{
Field = nameof(FakeProtectionObject.Num3),
Owner = "user1",
Resource = resource.Resource,
Visitor = "",
},
new ProtectedField
{
Field = nameof(FakeProtectionObject.Value1),
Owner = "user2",
Resource = resource.Resource,
Visitor = "",
},
new ProtectedField
{
Field = nameof(FakeProtectionObject.Value2),
Owner = "user1",
Resource = resource.Resource,
Visitor = "",
},
new ProtectedField
{
Field = nameof(FakeProtectionObject.Protect1),
Owner = "role1",
Resource = resource.Resource,
Visitor = "",
},
};
var rules = new List<ProtectedFieldRule>()
{
new ProtectedFieldRule
{
Field = nameof(FakeProtectionObject.Protect1),
Logic = PredicateOperator.And,
Operator = ExpressionType.Equal,
Resource = resource.Resource,
Value = "test"
},
new ProtectedFieldRule
{
Field = nameof(FakeProtectionObject.Num3),
Logic = PredicateOperator.Or,
Operator = ExpressionType.LessThanOrEqual,
Resource = resource.Resource,
Value = 300
},
};
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
unitOfWorkManager.Current.AddItem<ResourceGrantedResult>(
"ResourceGranted",
new ResourceGrantedResult(
resource,
fields.ToArray(),
rules.ToArray()));
var identity2 = new ClaimsIdentity();
identity2.AddClaim(new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()));
identity2.AddClaim(new Claim(AbpClaimTypes.UserName, "user2"));
identity2.AddClaim(new Claim(AbpClaimTypes.Role, "role2"));
using (_accessor.Change(identity2))
{
var result = await _repository.GetListAsync();
result.Count.ShouldBe(3);
}
});
await WithUnitOfWorkAsync(async () =>
{
var resource = new ProtectedResource
{
Resource = typeof(FakeProtectionObject).FullName,
Behavior = ProtectBehavior.All,
Priority = 10,
Visitor = "user3"
};
var fields = new List<ProtectedField>()
{
new ProtectedField
{
Field = nameof(FakeProtectionObject.Num3),
Owner = "user1",
Resource = resource.Resource,
Visitor = "",
}
};
var rules = new List<ProtectedFieldRule>()
{
new ProtectedFieldRule
{
Field = nameof(FakeProtectionObject.Protect1),
Logic = PredicateOperator.And,
Operator = ExpressionType.Equal,
Resource = resource.Resource,
Value = "test"
},
new ProtectedFieldRule
{
Field = nameof(FakeProtectionObject.Num3),
Logic = PredicateOperator.Or,
Operator = ExpressionType.LessThanOrEqual,
Resource = resource.Resource,
Value = 300
},
};
var unitOfWorkManager = GetRequiredService<IUnitOfWorkManager>();
unitOfWorkManager.Current.AddItem<ResourceGrantedResult>(
"ResourceGranted",
new ResourceGrantedResult(
resource,
fields.ToArray(),
rules.ToArray()));
var identity3 = new ClaimsIdentity();
identity3.AddClaim(new Claim(AbpClaimTypes.UserId, Guid.NewGuid().ToString()));
identity3.AddClaim(new Claim(AbpClaimTypes.UserName, "user3"));
identity3.AddClaim(new Claim(AbpClaimTypes.Role, "role3"));
using (_accessor.Change(identity3))
{
var result = await _repository.GetListAsync();
result.Count.ShouldBe(0);
}
});
}
}
}

118
aspnet-core/tests/LINGYUN.Abp.TestBase/LINGYUN/Abp/Tests/AbpTestsBase.cs

@ -1,59 +1,59 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Modularity;
using Volo.Abp.Testing;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.Tests
{
public abstract class AbpTestsBase<TStartupModule> : AbpIntegratedTest<TStartupModule>
where TStartupModule : IAbpModule
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
protected virtual Task WithUnitOfWorkAsync(Func<Task> func)
{
return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
}
protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func<Task> action)
{
using (var scope = ServiceProvider.CreateScope())
{
var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
using (var uow = uowManager.Begin(options))
{
await action();
await uow.CompleteAsync();
}
}
}
protected virtual Task<TResult> WithUnitOfWorkAsync<TResult>(Func<Task<TResult>> func)
{
return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
}
protected virtual async Task<TResult> WithUnitOfWorkAsync<TResult>(AbpUnitOfWorkOptions options, Func<Task<TResult>> func)
{
using (var scope = ServiceProvider.CreateScope())
{
var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
using (var uow = uowManager.Begin(options))
{
var result = await func();
await uow.CompleteAsync();
return result;
}
}
}
}
}
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Modularity;
using Volo.Abp.Testing;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.Tests
{
public abstract class AbpTestsBase<TStartupModule> : AbpIntegratedTest<TStartupModule>
where TStartupModule : IAbpModule
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
protected virtual Task WithUnitOfWorkAsync(Func<Task> func)
{
return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
}
protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func<Task> action)
{
using (var scope = ServiceProvider.CreateScope())
{
var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
using (var uow = uowManager.Begin(options))
{
await action();
await uow.CompleteAsync();
}
}
}
protected virtual Task<TResult> WithUnitOfWorkAsync<TResult>(Func<Task<TResult>> func)
{
return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func);
}
protected virtual async Task<TResult> WithUnitOfWorkAsync<TResult>(AbpUnitOfWorkOptions options, Func<Task<TResult>> func)
{
using (var scope = ServiceProvider.CreateScope())
{
var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
using (var uow = uowManager.Begin(options))
{
var result = await func();
await uow.CompleteAsync();
return result;
}
}
}
}
}

Loading…
Cancel
Save