224 changed files with 7953 additions and 1156 deletions
@ -1,6 +1,16 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<configuration> |
<configuration> |
||||
<packageSources> |
<packageSources> |
||||
|
<clear /> |
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> |
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> |
||||
|
<add key="local" value="./aspnet-core/LocalNuget" /> |
||||
</packageSources> |
</packageSources> |
||||
|
<packageSourceMapping> |
||||
|
<packageSource key="nuget.org"> |
||||
|
<package pattern="*" /> |
||||
|
</packageSource> |
||||
|
<packageSource key="local"> |
||||
|
<package pattern="LINGYUN.*" /> |
||||
|
</packageSource> |
||||
|
</packageSourceMapping> |
||||
</configuration> |
</configuration> |
||||
@ -1,7 +1,6 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<configuration> |
<configuration> |
||||
<packageSources> |
<packageSources> |
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> |
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> |
||||
<!--<add key="LocalNuget" value="./LocalNuget" />--> |
</packageSources> |
||||
</packageSources> |
|
||||
</configuration> |
</configuration> |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,15 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.ObjectExtending" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
[DependsOn(typeof(AbpObjectExtendingModule))] |
||||
|
public class AbpDataProtectionAbstractionsModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class DataAccessFilterGroup |
||||
|
{ |
||||
|
public List<DataAccessFilterGroup> Groups { get; set; } |
||||
|
public List<DataAccessFilterRule> Rules { get; set; } |
||||
|
public DataAccessFilterLogic Logic { get; set; } |
||||
|
|
||||
|
public DataAccessFilterGroup() : this(DataAccessFilterLogic.And) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public DataAccessFilterGroup(DataAccessFilterLogic logic = DataAccessFilterLogic.And) |
||||
|
{ |
||||
|
Logic = logic; |
||||
|
Rules = new List<DataAccessFilterRule>(); |
||||
|
Groups = new List<DataAccessFilterGroup>(); |
||||
|
} |
||||
|
|
||||
|
public DataAccessFilterGroup AddRule(DataAccessFilterRule rule) |
||||
|
{ |
||||
|
if (Rules.All(m => !m.Equals(rule))) |
||||
|
{ |
||||
|
Rules.Add(rule); |
||||
|
} |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public DataAccessFilterGroup AddRule(string field, object value, DataAccessFilterOperate operate = DataAccessFilterOperate.Equal) |
||||
|
{ |
||||
|
return AddRule(new DataAccessFilterRule(field, value, operate)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using System.ComponentModel; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
/// <summary>
|
||||
|
/// 数据过滤连接方式
|
||||
|
/// </summary>
|
||||
|
public enum DataAccessFilterLogic |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 且
|
||||
|
/// </summary>
|
||||
|
[Description("且")] |
||||
|
And, |
||||
|
/// <summary>
|
||||
|
/// 或
|
||||
|
/// </summary>
|
||||
|
[Description("或")] |
||||
|
Or |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
using System.ComponentModel; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
/// <summary>
|
||||
|
/// 数据过滤操作
|
||||
|
/// </summary>
|
||||
|
public enum DataAccessFilterOperate |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 且
|
||||
|
/// </summary>
|
||||
|
[Description("且")] |
||||
|
And = 1, |
||||
|
/// <summary>
|
||||
|
/// 或
|
||||
|
/// </summary>
|
||||
|
[Description("或")] |
||||
|
Or = 2, |
||||
|
/// <summary>
|
||||
|
/// 等于
|
||||
|
/// </summary>
|
||||
|
[Description("等于")] |
||||
|
Equal = 3, |
||||
|
/// <summary>
|
||||
|
/// 不等于
|
||||
|
/// </summary>
|
||||
|
[Description("不等于")] |
||||
|
NotEqual = 4, |
||||
|
/// <summary>
|
||||
|
/// 小于
|
||||
|
/// </summary>
|
||||
|
[Description("小于")] |
||||
|
Less = 5, |
||||
|
/// <summary>
|
||||
|
/// 小于或等于
|
||||
|
/// </summary>
|
||||
|
[Description("小于等于")] |
||||
|
LessOrEqual = 6, |
||||
|
/// <summary>
|
||||
|
/// 大于
|
||||
|
/// </summary>
|
||||
|
[Description("大于")] |
||||
|
Greater = 7, |
||||
|
/// <summary>
|
||||
|
/// 大于或等于
|
||||
|
/// </summary>
|
||||
|
[Description("大于等于")] |
||||
|
GreaterOrEqual = 8, |
||||
|
/// <summary>
|
||||
|
/// 左包含
|
||||
|
/// </summary>
|
||||
|
[Description("左包含")] |
||||
|
StartsWith = 9, |
||||
|
/// <summary>
|
||||
|
/// 右包含
|
||||
|
/// </summary>
|
||||
|
[Description("右包含")] |
||||
|
EndsWith = 10, |
||||
|
/// <summary>
|
||||
|
/// 包含
|
||||
|
/// </summary>
|
||||
|
[Description("包含")] |
||||
|
Contains = 11, |
||||
|
/// <summary>
|
||||
|
/// 不包含
|
||||
|
/// </summary>
|
||||
|
[Description("不包含")] |
||||
|
NotContains = 12, |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class DataAccessFilterRule |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 字段名称
|
||||
|
/// </summary>
|
||||
|
public string Field { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 字段值
|
||||
|
/// </summary>
|
||||
|
public object Value { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 操作类型
|
||||
|
/// </summary>
|
||||
|
public DataAccessFilterOperate Operate { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 左侧条件
|
||||
|
/// </summary>
|
||||
|
public bool IsLeft { get; set; } |
||||
|
|
||||
|
public DataAccessFilterRule() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public DataAccessFilterRule(string field, object value, DataAccessFilterOperate operate = DataAccessFilterOperate.Equal, bool isLeft = false) |
||||
|
{ |
||||
|
Field = field; |
||||
|
Value = value; |
||||
|
Operate = operate; |
||||
|
IsLeft = isLeft; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
/// <summary>
|
||||
|
/// 系统保留关键字列表
|
||||
|
/// </summary>
|
||||
|
public static class DataAccessKeywords |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 授权角色
|
||||
|
/// </summary>
|
||||
|
public const string AUTH_ROLES = "AR"; |
||||
|
/// <summary>
|
||||
|
/// 授权组织机构
|
||||
|
/// </summary>
|
||||
|
public const string AUTH_ORGS = "AO"; |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System.ComponentModel; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
/// <summary>
|
||||
|
/// 数据操作
|
||||
|
/// </summary>
|
||||
|
public enum DataAccessOperation |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 查询
|
||||
|
/// </summary>
|
||||
|
[Description("查询")] |
||||
|
Read, |
||||
|
/// <summary>
|
||||
|
/// 更新
|
||||
|
/// </summary>
|
||||
|
[Description("更新")] |
||||
|
Write, |
||||
|
/// <summary>
|
||||
|
/// 删除
|
||||
|
/// </summary>
|
||||
|
[Description("删除")] |
||||
|
Delete |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class DataAccessResource |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 权限主体
|
||||
|
/// </summary>
|
||||
|
public string SubjectName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 权限主体标识
|
||||
|
/// </summary>
|
||||
|
public string SubjectId { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 实体类型全名
|
||||
|
/// </summary>
|
||||
|
public string EntityTypeFullName { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 数据权限操作
|
||||
|
/// </summary>
|
||||
|
public DataAccessOperation Operation { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取或设置 数据过滤规则
|
||||
|
/// </summary>
|
||||
|
public DataAccessFilterGroup FilterGroup { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 允许操作的属性列表
|
||||
|
/// </summary>
|
||||
|
public List<string> AllowProperties { get; set; } |
||||
|
|
||||
|
public DataAccessResource() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public DataAccessResource( |
||||
|
string subjectName, |
||||
|
string subjectId, |
||||
|
string entityTypeFullName, |
||||
|
DataAccessOperation operation, |
||||
|
DataAccessFilterGroup filterGroup = null) |
||||
|
{ |
||||
|
SubjectName = subjectName; |
||||
|
SubjectId = subjectId; |
||||
|
EntityTypeFullName = entityTypeFullName; |
||||
|
Operation = operation; |
||||
|
FilterGroup = filterGroup; |
||||
|
AllowProperties = new List<string>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] |
||||
|
public class DataProtectedAttribute : Attribute |
||||
|
{ |
||||
|
public DataAccessOperation Operation { get; } |
||||
|
public DataProtectedAttribute() : this(DataAccessOperation.Read) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public DataProtectedAttribute(DataAccessOperation operation) |
||||
|
{ |
||||
|
Operation = operation; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false)] |
||||
|
public class DisableDataProtectedAttribute : Attribute |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
public interface IDataProtected : IHasExtraProperties |
||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,4 @@ |
|||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public interface IDataProtectedEnabled |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Localization; |
||||
|
|
||||
|
[LocalizationResourceName("DataProtection")] |
||||
|
public class DataProtectionResource |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
using Microsoft.EntityFrameworkCore.Diagnostics; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Expressions; |
||||
|
using System.Reflection; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
|
public class AbpDataProtectedReadEntityInterceptor : IQueryExpressionInterceptor, ITransientDependency |
||||
|
{ |
||||
|
public IAbpLazyServiceProvider LazyServiceProvider { get; set; } = default!; |
||||
|
public IOptions<AbpDataProtectionOptions> DataProtectionOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDataProtectionOptions>>(); |
||||
|
public ICurrentUser CurrentUser => LazyServiceProvider.LazyGetRequiredService<ICurrentUser>(); |
||||
|
public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService<IDataFilter>(); |
||||
|
public IEntityTypeFilterBuilder EntityTypeFilterBuilder => LazyServiceProvider.LazyGetRequiredService<IEntityTypeFilterBuilder>(); |
||||
|
|
||||
|
private static readonly MethodInfo WhereMethodInfo = typeof(Queryable).GetMethods().First(m => m.Name == nameof(Queryable.Where)); |
||||
|
|
||||
|
public Expression QueryCompilationStarting(Expression queryExpression, QueryExpressionEventData eventData) |
||||
|
{ |
||||
|
if (DataFilter.IsEnabled<IDataProtected>() && queryExpression.Type.GenericTypeArguments.Length > 0) |
||||
|
{ |
||||
|
var entityType = queryExpression.Type.GenericTypeArguments[0]; |
||||
|
var exp = EntityTypeFilterBuilder.Build(entityType, DataAccessOperation.Read); |
||||
|
|
||||
|
return Expression.Call( |
||||
|
method: WhereMethodInfo.MakeGenericMethod(entityType), |
||||
|
arg0: queryExpression, |
||||
|
arg1: exp); |
||||
|
} |
||||
|
|
||||
|
return queryExpression; |
||||
|
} |
||||
|
|
||||
|
public class DataProtectedExpressionVisitor : ExpressionVisitor |
||||
|
{ |
||||
|
private readonly Type _entityType; |
||||
|
private readonly IEntityTypeFilterBuilder _entityTypeFilterBuilder; |
||||
|
|
||||
|
public DataProtectedExpressionVisitor(Type entityType, IEntityTypeFilterBuilder entityTypeFilterBuilder) |
||||
|
{ |
||||
|
_entityType = entityType; |
||||
|
_entityTypeFilterBuilder = entityTypeFilterBuilder; |
||||
|
} |
||||
|
|
||||
|
private static readonly MethodInfo WhereMethodInfo = typeof(Queryable).GetMethods().First(m => m.Name == nameof(Queryable.Where)); |
||||
|
|
||||
|
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) |
||||
|
{ |
||||
|
var method = WhereMethodInfo.MakeGenericMethod(_entityType); |
||||
|
var args0 = base.VisitMethodCall(methodCallExpression); |
||||
|
var args1 = _entityTypeFilterBuilder.Build(_entityType, DataAccessOperation.Read); |
||||
|
|
||||
|
return Expression.Call( |
||||
|
method: method, |
||||
|
arg0: args0, |
||||
|
arg1: args1); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,66 @@ |
|||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Diagnostics; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Authorization; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
|
public class AbpDataProtectedWriteEntityInterceptor : SaveChangesInterceptor, ITransientDependency |
||||
|
{ |
||||
|
public IAbpLazyServiceProvider LazyServiceProvider { get; set; } = default!; |
||||
|
public IOptions<AbpDataProtectionOptions> DataProtectionOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDataProtectionOptions>>(); |
||||
|
public ICurrentUser CurrentUser => LazyServiceProvider.LazyGetRequiredService<ICurrentUser>(); |
||||
|
public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService<IDataFilter>(); |
||||
|
public IDataAuthorizationService DataAuthorizationService => LazyServiceProvider.LazyGetRequiredService<IDataAuthorizationService>(); |
||||
|
|
||||
|
public async override ValueTask<InterceptionResult<int>> SavingChangesAsync( |
||||
|
DbContextEventData eventData, |
||||
|
InterceptionResult<int> result, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
if (DataFilter.IsEnabled<IDataProtected>() && eventData.Context != null) |
||||
|
{ |
||||
|
var updateEntites = eventData.Context.ChangeTracker.Entries() |
||||
|
.Where(entry => entry.State.IsIn(EntityState.Modified) && (entry.Entity is not ISoftDelete || entry.Entity is ISoftDelete delete && delete.IsDeleted == false)) |
||||
|
.Select(entry => entry.Entity as IEntity); |
||||
|
if (updateEntites.Any()) |
||||
|
{ |
||||
|
var updateGrant = await DataAuthorizationService.AuthorizeAsync(DataAccessOperation.Write, updateEntites); |
||||
|
if (!updateGrant.Succeeded) |
||||
|
{ |
||||
|
var entityKeys = updateEntites |
||||
|
.Select(entity => (entity is IEntity abpEntity ? abpEntity.GetKeys() : new string[1] { entity.ToString() }).ToString()) |
||||
|
.JoinAsString(";"); |
||||
|
throw new AbpAuthorizationException( |
||||
|
$"Delete data permission not granted to entity {updateEntites.First().GetType()} for data {entityKeys}!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var deleteEntites = eventData.Context.ChangeTracker.Entries() |
||||
|
.Where(entry => entry.State.IsIn(EntityState.Deleted) || entry.Entity is ISoftDelete delete && delete.IsDeleted == true) |
||||
|
.Select(entry => entry.Entity as IEntity); |
||||
|
if (deleteEntites.Any()) |
||||
|
{ |
||||
|
var deleteGrant = await DataAuthorizationService.AuthorizeAsync(DataAccessOperation.Delete, deleteEntites); |
||||
|
if (!deleteGrant.Succeeded) |
||||
|
{ |
||||
|
var entityKeys = deleteEntites |
||||
|
.Select(entity => (entity is IEntity abpEntity ? abpEntity.GetKeys() : new string[1] { entity.ToString() }).ToString()) |
||||
|
.JoinAsString(";"); |
||||
|
throw new AbpAuthorizationException( |
||||
|
$"Delete data permission not granted to entity {deleteEntites.First().GetType()} for data {entityKeys}!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return await base.SavingChangesAsync(eventData, result, cancellationToken); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Diagnostics; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
|
public class AbpDataProtectedWritePropertiesInterceptor : SaveChangesInterceptor, ITransientDependency |
||||
|
{ |
||||
|
public IAbpLazyServiceProvider LazyServiceProvider { get; set; } = default!; |
||||
|
public IOptions<AbpDataProtectionOptions> DataProtectionOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDataProtectionOptions>>(); |
||||
|
public ICurrentUser CurrentUser => LazyServiceProvider.LazyGetRequiredService<ICurrentUser>(); |
||||
|
public IDataFilter DataFilter => LazyServiceProvider.LazyGetRequiredService<IDataFilter>(); |
||||
|
|
||||
|
public async override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
if (DataFilter.IsEnabled<IDataProtected>() && eventData.Context != null) |
||||
|
{ |
||||
|
foreach (var entry in eventData.Context.ChangeTracker.Entries().ToList()) |
||||
|
{ |
||||
|
if (entry.State.IsIn(EntityState.Modified)) |
||||
|
{ |
||||
|
var allowProperties = new List<string>(); |
||||
|
var entity = entry.Entity; |
||||
|
var subjectContext = new DataAccessSubjectContributorContext(entity.GetType().FullName, DataAccessOperation.Write, LazyServiceProvider); |
||||
|
foreach (var contributor in DataProtectionOptions.Value.SubjectContributors) |
||||
|
{ |
||||
|
var properties = contributor.GetAllowProperties(subjectContext); |
||||
|
allowProperties.AddIfNotContains(properties); |
||||
|
} |
||||
|
|
||||
|
allowProperties.AddIfNotContains(DataProtectionOptions.Value.IgnoreAuditedProperties); |
||||
|
|
||||
|
foreach (var property in entry.Properties) |
||||
|
{ |
||||
|
if (!allowProperties.Contains(property.Metadata.Name)) |
||||
|
{ |
||||
|
property.IsModified = false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return await base.SavingChangesAsync(eventData, result, cancellationToken); |
||||
|
} |
||||
|
} |
||||
@ -1,145 +1,55 @@ |
|||||
using Microsoft.EntityFrameworkCore; |
using Microsoft.EntityFrameworkCore; |
||||
using Microsoft.EntityFrameworkCore.ChangeTracking; |
using Microsoft.EntityFrameworkCore.ChangeTracking; |
||||
using System; |
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System.Collections.Generic; |
||||
using System.Linq; |
using System.Linq; |
||||
using System.Linq.Expressions; |
using Volo.Abp.Data; |
||||
using System.Reflection; |
|
||||
using Volo.Abp.Domain.Entities; |
|
||||
using Volo.Abp.EntityFrameworkCore; |
using Volo.Abp.EntityFrameworkCore; |
||||
using Volo.Abp.MultiTenancy; |
|
||||
using Volo.Abp.Uow; |
|
||||
using Volo.Abp.Users; |
using Volo.Abp.Users; |
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore |
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
{ |
|
||||
public class AbpDataProtectionDbContext : AbpDbContext<AbpDataProtectionDbContext> |
|
||||
{ |
|
||||
protected ICurrentUser CurrentUser => LazyServiceProvider.LazyGetService<ICurrentUser>(); |
|
||||
|
|
||||
protected virtual bool IsDataAccessFilterEnabled => DataFilter?.IsEnabled<IHasDataAccess>() ?? false; |
|
||||
|
|
||||
public AbpDataProtectionDbContext( |
|
||||
DbContextOptions<AbpDataProtectionDbContext> options) : base(options) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder) |
|
||||
{ |
|
||||
base.OnModelCreating(modelBuilder); |
|
||||
|
|
||||
foreach (var entityType in modelBuilder.Model.GetEntityTypes()) |
|
||||
{ |
|
||||
if (typeof(IHasDataAccess).IsAssignableFrom(entityType.ClrType)) |
|
||||
{ |
|
||||
modelBuilder.Entity(entityType.ClrType) |
|
||||
.OwnsOne(entityType.ClrType.FullName, nameof(IHasDataAccess.Owner), ownedNavigationBuilder => |
|
||||
{ |
|
||||
ownedNavigationBuilder.ToJson(); |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected override void ApplyAbpConceptsForAddedEntity(EntityEntry entry) |
|
||||
{ |
|
||||
base.ApplyAbpConceptsForAddedEntity(entry); |
|
||||
if (CurrentUser.IsAuthenticated) |
|
||||
{ |
|
||||
if (entry is IHasDataAccess entity) |
|
||||
{ |
|
||||
ProtectedEntityHelper.TrySetOwner( |
|
||||
entity, |
|
||||
() => new DataAccessOwner( |
|
||||
CurrentUser.Id, |
|
||||
CurrentUser.Roles, |
|
||||
CurrentUser.FindOrganizationUnits().Select(ou => ou.ToString()).ToArray())); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected virtual DataAccessRuleInfo AccessRuleInfo => UnitOfWorkManager.Current.GetAccessRuleInfo(); |
public abstract class AbpDataProtectionDbContext<TDbContext> : AbpDbContext<TDbContext> |
||||
|
where TDbContext : DbContext |
||||
protected override void HandlePropertiesBeforeSave() |
{ |
||||
{ |
public IOptions<AbpDataProtectionOptions> DataProtectionOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDataProtectionOptions>>(); |
||||
foreach (var item in ChangeTracker.Entries().ToList()) |
public ICurrentUser CurrentUser => LazyServiceProvider.LazyGetRequiredService<ICurrentUser>(); |
||||
{ |
|
||||
HandleExtraPropertiesOnSave(item); |
|
||||
HandleCheckPropertiesOnSave(item); |
|
||||
if (item.State.IsIn(EntityState.Modified, EntityState.Deleted)) |
|
||||
{ |
|
||||
UpdateConcurrencyStamp(item); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected virtual void HandleCheckPropertiesOnSave(EntityEntry entry) |
public AbpDataProtectionDbContext( |
||||
{ |
DbContextOptions<TDbContext> options) : base(options) |
||||
// 仅当启用过滤器时检查
|
{ |
||||
if (IsDataAccessFilterEnabled) |
} |
||||
{ |
|
||||
var entityAccessRules = AccessRuleInfo?.Rules.Where(r => r.EntityTypeFullName == entry.Metadata.ClrType.FullName); |
|
||||
if (entityAccessRules != null) |
|
||||
{ |
|
||||
if (entry.State.IsIn(EntityState.Modified, EntityState.Added, EntityState.Deleted)) |
|
||||
{ |
|
||||
var entityAccessRule = entityAccessRules.FirstOrDefault(r => r.Operation.IsIn(DataAccessOperation.Write, DataAccessOperation.Delete)); |
|
||||
if (entityAccessRule != null) |
|
||||
{ |
|
||||
if (entityAccessRule.Fileds.Count != 0) |
|
||||
{ |
|
||||
var notAccessProps = entry.Properties.Where(p => !entityAccessRule.Fileds.Any(f => f.Field == p.Metadata.Name)); |
|
||||
if (notAccessProps != null) |
|
||||
{ |
|
||||
foreach (var property in notAccessProps) |
|
||||
{ |
|
||||
// 无字段权限不做变更
|
|
||||
property.CurrentValue = property.OriginalValue; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
// 无实体变更权限不做修改
|
|
||||
entry.State = EntityState.Unchanged; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>() |
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) |
||||
{ |
{ |
||||
var expression = base.CreateFilterExpression<TEntity>(); |
base.OnConfiguring(optionsBuilder); |
||||
|
|
||||
if (typeof(IHasDataAccess).IsAssignableFrom(typeof(TEntity))) |
// TODO: 需要优化表达式树
|
||||
{ |
// optionsBuilder.AddInterceptors(LazyServiceProvider.GetRequiredService<AbpDataProtectedReadEntityInterceptor>());
|
||||
Expression<Func<TEntity, bool>> expression2 = (TEntity e) => !IsDataAccessFilterEnabled || CreateFilterExpression(e, AccessRuleInfo); |
//optionsBuilder.AddInterceptors(LazyServiceProvider.GetRequiredService<AbpDataProtectedWriteEntityInterceptor>());
|
||||
expression = (Expression<Func<TEntity, bool>>)((expression == null) ? ((LambdaExpression)expression2) : ((LambdaExpression)QueryFilterExpressionHelper.CombineExpressions(expression, expression2))); |
optionsBuilder.AddInterceptors(LazyServiceProvider.GetRequiredService<AbpDataProtectedWritePropertiesInterceptor>()); |
||||
} |
} |
||||
|
|
||||
return expression; |
protected override void ApplyAbpConceptsForAddedEntity(EntityEntry entry) |
||||
} |
{ |
||||
|
base.ApplyAbpConceptsForAddedEntity(entry); |
||||
|
SetAuthorizationDataProperties(entry); |
||||
|
} |
||||
|
|
||||
protected static bool CreateFilterExpression<TEntity>(TEntity entity, DataAccessRuleInfo accessRuleInfo) |
protected virtual void SetAuthorizationDataProperties(EntityEntry entry) |
||||
|
{ |
||||
|
if (entry.Entity is IDataProtected data) |
||||
{ |
{ |
||||
if (accessRuleInfo == null) |
// TODO: 埋点, 以后可用EF.Functions查询
|
||||
|
if (data.GetProperty(DataAccessKeywords.AUTH_ROLES) == null) |
||||
{ |
{ |
||||
return true; |
data.SetProperty(DataAccessKeywords.AUTH_ROLES, CurrentUser.Roles.Select(role => $"[{role}]").JoinAsString(",")); |
||||
} |
} |
||||
|
if (data.GetProperty(DataAccessKeywords.AUTH_ORGS) == null) |
||||
if (!accessRuleInfo.Rules.Any(r => r.EntityTypeFullName == typeof(TEntity).FullName)) |
|
||||
{ |
{ |
||||
return false; |
data.SetProperty(DataAccessKeywords.AUTH_ORGS, CurrentUser.FindOrganizationUnits().Select(ou => $"[{ou}]").JoinAsString(",")); |
||||
} |
} |
||||
|
|
||||
if (entity is not IHasDataAccess accessEntity) |
|
||||
{ |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
// TODO: 需要完成详细的过滤条件
|
|
||||
return false; |
|
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,16 @@ |
|||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore |
||||
|
{ |
||||
|
public static class AbpDataProtectionDbContextModelBuilderExtensions |
||||
|
{ |
||||
|
public static void ConfigureLocalization( |
||||
|
this ModelBuilder builder, |
||||
|
Action<AbpDataProtectionModelBuilderConfigurationOptions> optionsAction = null) |
||||
|
{ |
||||
|
Check.NotNull(builder, nameof(builder)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,12 +1,11 @@ |
|||||
using Volo.Abp.EntityFrameworkCore; |
using Volo.Abp.EntityFrameworkCore; |
||||
using Volo.Abp.Modularity; |
using Volo.Abp.Modularity; |
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore |
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpDataProtectionModule), |
||||
|
typeof(AbpEntityFrameworkCoreModule))] |
||||
|
public class AbpDataProtectionEntityFrameworkCoreModule : AbpModule |
||||
{ |
{ |
||||
[DependsOn( |
|
||||
typeof(AbpDataProtectionModule), |
|
||||
typeof(AbpEntityFrameworkCoreModule))] |
|
||||
public class AbpDataProtectionEntityFrameworkCoreModule : AbpModule |
|
||||
{ |
|
||||
} |
|
||||
} |
} |
||||
|
|||||
@ -0,0 +1,18 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.EntityFrameworkCore.Modeling; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore |
||||
|
{ |
||||
|
public class AbpDataProtectionModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions |
||||
|
{ |
||||
|
public AbpDataProtectionModelBuilderConfigurationOptions( |
||||
|
[NotNull] string tablePrefix = "", |
||||
|
[CanBeNull] string schema = null) |
||||
|
: base( |
||||
|
tablePrefix, |
||||
|
schema) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,358 +0,0 @@ |
|||||
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); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,86 +0,0 @@ |
|||||
using Microsoft.EntityFrameworkCore; |
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics; |
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure; |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Linq.Expressions; |
|
||||
using System.Reflection; |
|
||||
using System.Reflection.Metadata; |
|
||||
using System.Text; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.Data; |
|
||||
using Volo.Abp.Domain.Entities; |
|
||||
using Volo.Abp.EntityFrameworkCore; |
|
||||
using Volo.Abp.Users; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
|
||||
public class DataProtectionQueryExpressionInterceptor : IQueryExpressionInterceptor |
|
||||
{ |
|
||||
public Expression QueryCompilationStarting(Expression queryExpression, QueryExpressionEventData eventData) |
|
||||
{ |
|
||||
var dataFilter = eventData.Context.GetService<IDataFilter>(); |
|
||||
var dbContextProvider = eventData.Context.GetService<IDbContextProvider<AbpDataProtectionDbContext>>(); |
|
||||
return new DataProtectionExpressionVisitor(dataFilter, dbContextProvider).Visit(queryExpression); |
|
||||
} |
|
||||
|
|
||||
public class DataProtectionExpressionVisitor : ExpressionVisitor |
|
||||
{ |
|
||||
private readonly static MethodInfo WhereMethodInfo = typeof(Queryable).GetMethod(nameof(Queryable.Where)); |
|
||||
|
|
||||
|
|
||||
private readonly IDataFilter _dataFilter; |
|
||||
private readonly ICurrentUser _currentUser; |
|
||||
private readonly IDbContextProvider<AbpDataProtectionDbContext> _dbContextProvider; |
|
||||
|
|
||||
public DataProtectionExpressionVisitor( |
|
||||
IDataFilter dataFilter, |
|
||||
IDbContextProvider<AbpDataProtectionDbContext> dbContextProvider) |
|
||||
{ |
|
||||
_dataFilter = dataFilter; |
|
||||
_dbContextProvider = dbContextProvider; |
|
||||
} |
|
||||
|
|
||||
protected override Expression VisitMethodCall(MethodCallExpression node) |
|
||||
{ |
|
||||
if (_dataFilter.IsEnabled<IHasDataAccess>()) |
|
||||
{ |
|
||||
var methodInfo = node!.Method; |
|
||||
if (methodInfo.DeclaringType == typeof(Queryable) |
|
||||
&& methodInfo.Name == nameof(Queryable.Select) |
|
||||
&& methodInfo.GetParameters().Length == 2) |
|
||||
{ |
|
||||
var sourceType = node.Type.GetGenericArguments()[0]; |
|
||||
var lambdaExpression = (LambdaExpression)((UnaryExpression)node.Arguments[1]).Operand; |
|
||||
var entityParameterExpression = lambdaExpression.Parameters[0]; |
|
||||
|
|
||||
var rules = _currentUser.Roles; |
|
||||
var ous = _currentUser.FindOrganizationUnits(); |
|
||||
|
|
||||
var ownerParamter = Expression.PropertyOrField(entityParameterExpression, nameof(IHasDataAccess.Owner)); |
|
||||
|
|
||||
|
|
||||
if (typeof(IEntity).IsAssignableFrom(sourceType)) |
|
||||
{ |
|
||||
// Join params[0]
|
|
||||
// node
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
var test = Expression.Call( |
|
||||
method: WhereMethodInfo.MakeGenericMethod(sourceType, typeof(bool)), |
|
||||
arg0: base.VisitMethodCall(node), |
|
||||
arg1: Expression.Lambda( |
|
||||
typeof(Func<,>).MakeGenericType(entityParameterExpression.Type, typeof(bool)), |
|
||||
Expression.Property(entityParameterExpression, nameof(IHasDataAccess.Owner)), |
|
||||
true)); |
|
||||
return test; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
return base.VisitMethodCall(node); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,41 +0,0 @@ |
|||||
using Microsoft.EntityFrameworkCore; |
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics; |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using System.Text; |
|
||||
using System.Threading; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.Auditing; |
|
||||
using Volo.Abp.Domain.Entities; |
|
||||
using Volo.Abp.EntityFrameworkCore; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
|
||||
public class DataProtectionSaveChangesInterceptor : SaveChangesInterceptor |
|
||||
{ |
|
||||
private readonly static EntityState[] _protectedStates = |
|
||||
[ |
|
||||
EntityState.Modified, |
|
||||
EntityState.Detached, |
|
||||
]; |
|
||||
public async override ValueTask<InterceptionResult<int>> SavingChangesAsync( |
|
||||
DbContextEventData eventData, |
|
||||
InterceptionResult<int> result, |
|
||||
CancellationToken cancellationToken = default) |
|
||||
{ |
|
||||
if (eventData.Context != null && eventData.Context is IAbpEfCoreDbContext) |
|
||||
{ |
|
||||
// 存在资源所属者的实体将被检查访问权限
|
|
||||
var changeEntires = eventData.Context.ChangeTracker.Entries<IMayHaveCreator>() |
|
||||
.Where(e => _protectedStates.Contains(e.State)) |
|
||||
.Where(e => e.Entity.CreatorId.HasValue); |
|
||||
|
|
||||
foreach (var changeEntity in changeEntires) |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
// return InterceptionResult<int>.SuppressWithResult(0);
|
|
||||
return await base.SavingChangesAsync(eventData, result, cancellationToken); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,156 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
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; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
|
|
||||
|
public abstract class EfCoreDataProtectionRepository<TDbContext, TEntity, TKey> : |
||||
|
EfCoreRepository<TDbContext, TEntity, TKey>, |
||||
|
IDataProtectionRepository<TEntity> |
||||
|
where TDbContext : IEfCoreDbContext |
||||
|
where TEntity : class, IEntity<TKey> |
||||
|
{ |
||||
|
private readonly IDataAuthorizationService _dataAuthorizationService; |
||||
|
private readonly IEntityTypeFilterBuilder _entityTypeFilterBuilder; |
||||
|
|
||||
|
protected EfCoreDataProtectionRepository( |
||||
|
[NotNull] IDbContextProvider<TDbContext> dbContextProvider, |
||||
|
[NotNull] IDataAuthorizationService dataAuthorizationService, |
||||
|
[NotNull] IEntityTypeFilterBuilder entityTypeFilterBuilder) |
||||
|
: base(dbContextProvider) |
||||
|
{ |
||||
|
_dataAuthorizationService = dataAuthorizationService; |
||||
|
_entityTypeFilterBuilder = entityTypeFilterBuilder; |
||||
|
} |
||||
|
|
||||
|
public async override Task<IQueryable<TEntity>> GetQueryableAsync() |
||||
|
{ |
||||
|
var queryable = await base.GetQueryableAsync(); |
||||
|
|
||||
|
var dataAccessFilterExp = _entityTypeFilterBuilder.Build<TEntity>(DataAccessOperation.Read); |
||||
|
queryable = queryable.Where(dataAccessFilterExp); |
||||
|
|
||||
|
return queryable; |
||||
|
} |
||||
|
|
||||
|
public async override Task DeleteDirectAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var dbContext = await GetDbContextAsync(); |
||||
|
var dbSet = dbContext.Set<TEntity>(); |
||||
|
var entities = await dbSet.Where(predicate).ToListAsync(); |
||||
|
|
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Delete, entities); |
||||
|
|
||||
|
await dbSet.Where(predicate).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); |
||||
|
} |
||||
|
|
||||
|
public async override Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Delete, new TEntity[1] { entity }); |
||||
|
|
||||
|
await base.DeleteAsync(entity, autoSave, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async override Task DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Delete, entities); |
||||
|
|
||||
|
await base.DeleteManyAsync(entities, autoSave, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async override Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Write, new TEntity[1] { entity }); |
||||
|
|
||||
|
return await base.UpdateAsync(entity, autoSave, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async override Task UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Write, entities); |
||||
|
|
||||
|
await base.UpdateManyAsync(entities, autoSave, cancellationToken); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public abstract class EfCoreDataProtectionRepository<TDbContext, TEntity> : EfCoreRepository<TDbContext, TEntity> |
||||
|
where TDbContext : IEfCoreDbContext |
||||
|
where TEntity : class, IEntity |
||||
|
{ |
||||
|
private readonly IDataAuthorizationService _dataAuthorizationService; |
||||
|
private readonly IEntityTypeFilterBuilder _entityTypeFilterBuilder; |
||||
|
|
||||
|
protected EfCoreDataProtectionRepository( |
||||
|
[NotNull] IDbContextProvider<TDbContext> dbContextProvider, |
||||
|
[NotNull] IDataAuthorizationService dataAuthorizationService, |
||||
|
[NotNull] IEntityTypeFilterBuilder entityTypeFilterBuilder) |
||||
|
: base(dbContextProvider) |
||||
|
{ |
||||
|
_dataAuthorizationService = dataAuthorizationService; |
||||
|
_entityTypeFilterBuilder = entityTypeFilterBuilder; |
||||
|
} |
||||
|
|
||||
|
public async override Task<IQueryable<TEntity>> GetQueryableAsync() |
||||
|
{ |
||||
|
var queryable = await base.GetQueryableAsync(); |
||||
|
|
||||
|
var dataAccessFilterExp = _entityTypeFilterBuilder.Build<TEntity>(DataAccessOperation.Read); |
||||
|
queryable = queryable.Where(dataAccessFilterExp); |
||||
|
|
||||
|
return queryable; |
||||
|
} |
||||
|
|
||||
|
public async override Task DeleteDirectAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
var dbContext = await GetDbContextAsync(); |
||||
|
var dbSet = dbContext.Set<TEntity>(); |
||||
|
var entities = await dbSet.Where(predicate).ToListAsync(); |
||||
|
|
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Delete, entities); |
||||
|
|
||||
|
await dbSet.Where(predicate).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); |
||||
|
} |
||||
|
|
||||
|
public async override Task DeleteAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Delete, new TEntity[1] { entity }); |
||||
|
|
||||
|
await base.DeleteAsync(entity, autoSave, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async override Task DeleteManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Delete, entities); |
||||
|
|
||||
|
await base.DeleteManyAsync(entities, autoSave, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async override Task<TEntity> UpdateAsync(TEntity entity, bool autoSave = false, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Write, new TEntity[1] { entity }); |
||||
|
|
||||
|
return await base.UpdateAsync(entity, autoSave, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async override Task UpdateManyAsync(IEnumerable<TEntity> entities, bool autoSave = false, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _dataAuthorizationService.CheckAsync(DataAccessOperation.Write, entities); |
||||
|
|
||||
|
await base.UpdateManyAsync(entities, autoSave, cancellationToken); |
||||
|
} |
||||
|
} |
||||
@ -1,19 +0,0 @@ |
|||||
using System; |
|
||||
using Volo.Abp; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore |
|
||||
{ |
|
||||
public static class ProtectedEntityHelper |
|
||||
{ |
|
||||
public static void TrySetOwner( |
|
||||
IHasDataAccess protectedEntity, |
|
||||
Func<DataAccessOwner> ownerFactory) |
|
||||
{ |
|
||||
ObjectHelper.TrySetProperty( |
|
||||
protectedEntity, |
|
||||
x => x.Owner, |
|
||||
ownerFactory, |
|
||||
new Type[] { }); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,104 @@ |
|||||
|
# LINGYUN.Abp.DataProtection.EntityFrameworkCore |
||||
|
|
||||
|
数据权限EF实现模块 |
||||
|
|
||||
|
## 接口描述 |
||||
|
|
||||
|
* DisableDataProtectedAttribute: 通过拦截器自动实现DataFilter.Disable<IDataProtected>(),数据过滤器在当前范围将被禁用 |
||||
|
|
||||
|
## 注意事项 |
||||
|
|
||||
|
* 使用仓储接口尽量避免直接使用 *await GetDbSetAsync()*, 而是使用 *await GetQueryableAsync()*, 因为 **DbSet** 设计模式原因,暂无法对其进行处理 |
||||
|
* 您的仓库接口应继承自 **EfCoreDataProtectionRepository**, 您的 *DbContext* 应继承自 **AbpDataProtectionDbContext** |
||||
|
|
||||
|
## 配置使用 |
||||
|
|
||||
|
```csharp |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpDataProtectionEntityFrameworkCoreModule) |
||||
|
)] |
||||
|
public class YouProjectModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<DataProtectionManagementOptions>(options => |
||||
|
{ |
||||
|
// 受保护的实体列表持久化 |
||||
|
options.AddEntities(typeof(YouResource), new Type[] |
||||
|
{ |
||||
|
typeof(YouProtectionObject), |
||||
|
}); |
||||
|
|
||||
|
// 如下格式 |
||||
|
// options.AddEntities(typeof(IdentityResource), new Type[] |
||||
|
// { |
||||
|
// typeof(IdentityUser), |
||||
|
// typeof(IdentityRole), |
||||
|
// typeof(OrganizationUnit), |
||||
|
// }); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class YouDbContext : AbpDataProtectionDbContext<YouDbContext> |
||||
|
{ |
||||
|
public DbSet<YouProtectionObject> ProtectionObjects { get; set; } |
||||
|
public YouDbContext( |
||||
|
DbContextOptions<YouDbContext> options) : base(options) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder) |
||||
|
{ |
||||
|
base.OnModelCreating(modelBuilder); |
||||
|
modelBuilder.Entity<YouProtectionObject>(b => |
||||
|
{ |
||||
|
// ... |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
public class EfCoreYouProtectionObjectRepository : |
||||
|
EfCoreDataProtectionRepository<YouDbContext, YouProtectionObject, int>, |
||||
|
IYouProtectionObjectRepository |
||||
|
{ |
||||
|
protected IDataFilter DataFilter { get; } |
||||
|
public EfCoreYouProtectionObjectRepository( |
||||
|
[NotNull] IDbContextProvider<YouDbContext> dbContextProvider, |
||||
|
[NotNull] IDataAuthorizationService dataAuthorizationService, |
||||
|
[NotNull] IEntityTypeFilterBuilder entityTypeFilterBuilder, |
||||
|
IDataFilter dataFilter) |
||||
|
: base(dbContextProvider, dataAuthorizationService, entityTypeFilterBuilder) |
||||
|
{ |
||||
|
DataFilter = dataFilter; |
||||
|
} |
||||
|
|
||||
|
// 获取受保护的数据列表 |
||||
|
public async virtual Task<List<YouProtectionObject>> GetProtectedListAsync() |
||||
|
{ |
||||
|
return await (await GetQueryableAsync()) |
||||
|
.ToListAsync(); |
||||
|
} |
||||
|
|
||||
|
// 标注 DisableDataProtected 获取全部数据列表, 通过拦截器自动处理 DataFilter.Disable<IDataProtected>() |
||||
|
[DisableDataProtected] |
||||
|
public async virtual Task<List<YouProtectionObject>> GetUnProtectedListAsync() |
||||
|
{ |
||||
|
return await (await GetQueryableAsync()) |
||||
|
.ToListAsync(); |
||||
|
} |
||||
|
|
||||
|
// 禁用 IDataProtected 过滤器获取全部数据列表(可在任意地方使用) |
||||
|
public async virtual Task<List<YouProtectionObject>> GetUnProtectedByFilterListAsync() |
||||
|
{ |
||||
|
using (DataFilter.Disable<IDataProtected>()) |
||||
|
{ |
||||
|
return await (await GetQueryableAsync()) |
||||
|
.ToListAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
@ -1,10 +1,49 @@ |
|||||
using Volo.Abp.Domain; |
using LINGYUN.Abp.DataProtection.Keywords; |
||||
|
using LINGYUN.Abp.DataProtection.Localization; |
||||
|
using LINGYUN.Abp.DataProtection.Operations; |
||||
|
using LINGYUN.Abp.DataProtection.Subjects; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Domain; |
||||
|
using Volo.Abp.Localization; |
||||
using Volo.Abp.Modularity; |
using Volo.Abp.Modularity; |
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection; |
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
[DependsOn( |
[DependsOn( |
||||
|
typeof(AbpDataProtectionAbstractionsModule), |
||||
typeof(AbpDddDomainModule))] |
typeof(AbpDddDomainModule))] |
||||
public class AbpDataProtectionModule : AbpModule |
public class AbpDataProtectionModule : AbpModule |
||||
{ |
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.OnRegistered(DataProtectedInterceptorRegistrar.RegisterIfNeeded); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpDataProtectionOptions>(options => |
||||
|
{ |
||||
|
options.KeywordContributors.Add(DataAccessCurrentUserContributor.Name, new DataAccessCurrentUserContributor()); |
||||
|
|
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.Equal, new DataAccessEqualContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.NotEqual, new DataAccessNotEqualContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.Less, new DataAccessLessContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.LessOrEqual, new DataAccessLessOrEqualContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.Greater, new DataAccessGreaterContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.GreaterOrEqual, new DataAccessGreaterOrEqualContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.StartsWith, new DataAccessStartsWithContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.EndsWith, new DataAccessEndsWithContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.Contains, new DataAccessContainsContributor()); |
||||
|
options.OperateContributors.Add(DataAccessFilterOperate.NotContains, new DataAccessNotContainsContributor()); |
||||
|
|
||||
|
options.SubjectContributors.Add(new DataAccessUserIdContributor()); |
||||
|
options.SubjectContributors.Add(new DataAccessRoleNameContributor()); |
||||
|
options.SubjectContributors.Add(new DataAccessOrganizationUnitContributor()); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources.Add<DataProtectionResource>(); |
||||
|
}); |
||||
|
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,55 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Auditing; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public class AbpDataProtectionOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 是否启用数据审计
|
||||
|
/// 默认: true
|
||||
|
/// </summary>
|
||||
|
public bool IsEnabled { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 权限主体
|
||||
|
/// </summary>
|
||||
|
public IList<IDataAccessSubjectContributor> SubjectContributors { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 过滤字段关键字
|
||||
|
/// </summary>
|
||||
|
public IDictionary<string, IDataAccessKeywordContributor> KeywordContributors { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 数据操作
|
||||
|
/// </summary>
|
||||
|
public IDictionary<DataAccessFilterOperate, IDataAccessOperateContributor> OperateContributors { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 忽略审计字段列表
|
||||
|
/// </summary>
|
||||
|
public IList<string> IgnoreAuditedProperties { get; set; } |
||||
|
public AbpDataProtectionOptions() |
||||
|
{ |
||||
|
IsEnabled = true; |
||||
|
SubjectContributors = new List<IDataAccessSubjectContributor>(); |
||||
|
KeywordContributors = new Dictionary<string, IDataAccessKeywordContributor>(); |
||||
|
OperateContributors = new Dictionary<DataAccessFilterOperate, IDataAccessOperateContributor>(); |
||||
|
|
||||
|
IgnoreAuditedProperties = new List<string> |
||||
|
{ |
||||
|
nameof(IEntity<Guid>.Id), |
||||
|
nameof(IAuditedObject.LastModifierId), |
||||
|
nameof(IAuditedObject.LastModificationTime), |
||||
|
nameof(IAuditedObject.CreatorId), |
||||
|
nameof(IAuditedObject.CreationTime), |
||||
|
nameof(IDeletionAuditedObject.IsDeleted), |
||||
|
nameof(IDeletionAuditedObject.DeleterId), |
||||
|
nameof(IDeletionAuditedObject.DeletionTime), |
||||
|
nameof(IMultiTenant.TenantId), |
||||
|
nameof(IHasEntityVersion.EntityVersion), |
||||
|
nameof(IHasConcurrencyStamp.ConcurrencyStamp), |
||||
|
nameof(IHasExtraProperties.ExtraProperties), |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -1,30 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
public class DataAccessCacheItem |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 实体类型全名
|
|
||||
/// </summary>
|
|
||||
public string EntityTypeFullName { get; set; } |
|
||||
/// <summary>
|
|
||||
/// 数据访问操作
|
|
||||
/// </summary>
|
|
||||
public DataAccessOperation Operation { get; set; } |
|
||||
/// <summary>
|
|
||||
/// 数据访问角色
|
|
||||
/// </summary>
|
|
||||
public DataAccessRole Role { get; set; } |
|
||||
/// <summary>
|
|
||||
/// 资源访问者
|
|
||||
/// </summary>
|
|
||||
public string Visitor { get; set; } |
|
||||
/// <summary>
|
|
||||
/// 字段访问控制
|
|
||||
/// </summary>
|
|
||||
public List<DataAccessFiledRule> Fileds { get; set; } |
|
||||
/// <summary>
|
|
||||
/// 自定义表达式
|
|
||||
/// </summary>
|
|
||||
public List<DataAccessExpressionRule> Expressions { get; set; } |
|
||||
} |
|
||||
@ -1,12 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Text; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
/// <summary>
|
|
||||
/// 数据访问实体控制
|
|
||||
/// </summary>
|
|
||||
public class DataAccessEntityRule |
|
||||
{ |
|
||||
|
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
/// <summary>
|
|
||||
/// 数据访问控制规则:自定义表达式
|
|
||||
/// </summary>
|
|
||||
public class DataAccessExpressionRule |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 表达式
|
|
||||
/// </summary>
|
|
||||
public virtual string Expression { get; protected set; } |
|
||||
} |
|
||||
@ -1,19 +0,0 @@ |
|||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
/// <summary>
|
|
||||
/// 数据访问控制规则:字段
|
|
||||
/// </summary>
|
|
||||
public class DataAccessFiledRule |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 字段名称
|
|
||||
/// </summary>
|
|
||||
public virtual string Field { get; protected set; } |
|
||||
public DataAccessFiledRule() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public DataAccessFiledRule(string field) |
|
||||
{ |
|
||||
Field = field; |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,11 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public class DataAccessKeywordContributorContext |
||||
|
{ |
||||
|
public IServiceProvider ServiceProvider { get; } |
||||
|
public DataAccessKeywordContributorContext(IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
ServiceProvider = serviceProvider; |
||||
|
} |
||||
|
} |
||||
@ -1,7 +0,0 @@ |
|||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
public enum DataAccessOperation |
|
||||
{ |
|
||||
Read, |
|
||||
Write, |
|
||||
Delete |
|
||||
} |
|
||||
@ -1,34 +0,0 @@ |
|||||
using System; |
|
||||
using System.Linq; |
|
||||
using Volo.Abp.Auditing; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
/// <summary>
|
|
||||
/// 数据拥有者
|
|
||||
/// </summary>
|
|
||||
public class DataAccessOwner : IMayHaveCreator |
|
||||
{ |
|
||||
public Guid? CreatorId { get; set; } |
|
||||
public string[] Roles { get; set; } |
|
||||
public string[] OrganizaztionUnits { get; set; } |
|
||||
protected DataAccessOwner() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public DataAccessOwner(Guid? creatorId, string[] roles, string[] organizaztionUnits) |
|
||||
{ |
|
||||
CreatorId = creatorId; |
|
||||
Roles = roles; |
|
||||
OrganizaztionUnits = organizaztionUnits; |
|
||||
} |
|
||||
|
|
||||
public bool IsInRole(string[] roles) |
|
||||
{ |
|
||||
return Roles != null && Roles.Any(r => roles.Contains(r)); |
|
||||
} |
|
||||
|
|
||||
public bool IsInOrganizaztionUnit(string[] organizaztionUnits) |
|
||||
{ |
|
||||
return OrganizaztionUnits != null && OrganizaztionUnits.Any(ou => organizaztionUnits.Contains(ou)); |
|
||||
} |
|
||||
} |
|
||||
@ -1,23 +0,0 @@ |
|||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
/// <summary>
|
|
||||
/// 数据访问角色
|
|
||||
/// </summary>
|
|
||||
public enum DataAccessRole |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 所有
|
|
||||
/// </summary>
|
|
||||
All = 0, |
|
||||
/// <summary>
|
|
||||
/// 用户
|
|
||||
/// </summary>
|
|
||||
User = 1, |
|
||||
/// <summary>
|
|
||||
/// 角色
|
|
||||
/// </summary>
|
|
||||
Role = 2, |
|
||||
/// <summary>
|
|
||||
/// 组织机构
|
|
||||
/// </summary>
|
|
||||
OrganizationUnit = 3, |
|
||||
} |
|
||||
@ -1,54 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
/// <summary>
|
|
||||
/// 数据访问控制规则
|
|
||||
/// </summary>
|
|
||||
public class DataAccessRule |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 实体类型全名
|
|
||||
/// </summary>
|
|
||||
public virtual string EntityTypeFullName { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 数据访问操作
|
|
||||
/// </summary>
|
|
||||
public virtual DataAccessOperation Operation { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 数据访问角色
|
|
||||
/// </summary>
|
|
||||
public virtual DataAccessRole Role { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 资源访问者
|
|
||||
/// </summary>
|
|
||||
public virtual string Visitor { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 字段访问控制
|
|
||||
/// </summary>
|
|
||||
public virtual List<DataAccessFiledRule> Fileds { get; protected set; } |
|
||||
/// <summary>
|
|
||||
/// 自定义表达式
|
|
||||
/// </summary>
|
|
||||
public virtual List<DataAccessExpressionRule> Expressions { get; protected set; } |
|
||||
protected DataAccessRule() |
|
||||
{ |
|
||||
Fileds = []; |
|
||||
Expressions = []; |
|
||||
} |
|
||||
|
|
||||
public DataAccessRule( |
|
||||
string entityTypeFullName, |
|
||||
DataAccessOperation operation = DataAccessOperation.Read, |
|
||||
DataAccessRole role = DataAccessRole.All, |
|
||||
string visitor = null, |
|
||||
List<DataAccessFiledRule> fileds = null, |
|
||||
List<DataAccessExpressionRule> expressions = null) |
|
||||
{ |
|
||||
EntityTypeFullName = entityTypeFullName; |
|
||||
Operation = operation; |
|
||||
Role = role; |
|
||||
Visitor = visitor; |
|
||||
Fileds = fileds ?? []; |
|
||||
Expressions = expressions ?? []; |
|
||||
} |
|
||||
} |
|
||||
@ -1,11 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
public class DataAccessRuleInfo |
|
||||
{ |
|
||||
public List<DataAccessRule> Rules { get; } |
|
||||
public DataAccessRuleInfo(List<DataAccessRule> rules) |
|
||||
{ |
|
||||
Rules = rules ?? new List<DataAccessRule>(); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,18 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public class DataAccessSubjectContributorContext |
||||
|
{ |
||||
|
public string EntityTypeFullName { get; } |
||||
|
public DataAccessOperation Operation { get; } |
||||
|
public IServiceProvider ServiceProvider { get; } |
||||
|
public DataAccessSubjectContributorContext( |
||||
|
string entityTypeFullName, |
||||
|
DataAccessOperation operation, |
||||
|
IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
EntityTypeFullName = entityTypeFullName; |
||||
|
Operation = operation; |
||||
|
ServiceProvider = serviceProvider; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
public class DataAuthorizationService : IDataAuthorizationService, ITransientDependency |
||||
|
{ |
||||
|
private readonly static MethodInfo AllMethod = typeof(Enumerable).GetMethod(nameof(Enumerable.All), BindingFlags.Public | BindingFlags.Static); |
||||
|
private readonly IEntityTypeFilterBuilder _entityTypeFilterBuilder; |
||||
|
|
||||
|
public DataAuthorizationService(IEntityTypeFilterBuilder entityTypeFilterBuilder) |
||||
|
{ |
||||
|
_entityTypeFilterBuilder = entityTypeFilterBuilder; |
||||
|
} |
||||
|
|
||||
|
public virtual Task<AuthorizationResult> AuthorizeAsync<TEntity>(DataAccessOperation operation, IEnumerable<TEntity> entities) |
||||
|
{ |
||||
|
if (!entities.Any()) |
||||
|
{ |
||||
|
return Task.FromResult(AuthorizationResult.Success()); |
||||
|
} |
||||
|
|
||||
|
var exp = _entityTypeFilterBuilder.Build<TEntity>(operation); |
||||
|
|
||||
|
return Task.FromResult(entities.All(exp.Compile()) ? AuthorizationResult.Success() : AuthorizationResult.Failed()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.DynamicProxy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public class DataProtectedInterceptor : AbpInterceptor, ITransientDependency |
||||
|
{ |
||||
|
private readonly IDataFilter _dataFilter; |
||||
|
private readonly AbpDataProtectionOptions _options; |
||||
|
|
||||
|
public DataProtectedInterceptor(IDataFilter dataFilter, IOptions<AbpDataProtectionOptions> options) |
||||
|
{ |
||||
|
_dataFilter = dataFilter; |
||||
|
_options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public async override Task InterceptAsync(IAbpMethodInvocation invocation) |
||||
|
{ |
||||
|
if (ShouldDisableDataProtected(invocation, _options)) |
||||
|
{ |
||||
|
using (_dataFilter.Disable<IDataProtected>()) |
||||
|
{ |
||||
|
await invocation.ProceedAsync(); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
await invocation.ProceedAsync(); |
||||
|
} |
||||
|
|
||||
|
protected virtual bool ShouldDisableDataProtected( |
||||
|
IAbpMethodInvocation invocation, |
||||
|
AbpDataProtectionOptions options) |
||||
|
{ |
||||
|
if (!options.IsEnabled) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (invocation.Method.IsDefined(typeof(DisableDataProtectedAttribute), true)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.DynamicProxy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public static class DataProtectedInterceptorRegistrar |
||||
|
{ |
||||
|
public static void RegisterIfNeeded(IOnServiceRegistredContext context) |
||||
|
{ |
||||
|
if (ShouldIntercept(context.ImplementationType)) |
||||
|
{ |
||||
|
context.Interceptors.TryAdd<DataProtectedInterceptor>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static bool ShouldIntercept(Type type) |
||||
|
{ |
||||
|
return !DynamicProxyIgnoreTypes.Contains(type) && |
||||
|
(typeof(IDataProtectedEnabled).IsAssignableFrom(type) || type.IsDefined(typeof(DataProtectedAttribute), true) || AnyMethodHasAuthorizeAttribute(type)); |
||||
|
} |
||||
|
|
||||
|
private static bool AnyMethodHasAuthorizeAttribute(Type implementationType) |
||||
|
{ |
||||
|
return implementationType |
||||
|
.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) |
||||
|
.Any(HasAuthorizeAttribute); |
||||
|
} |
||||
|
|
||||
|
private static bool HasAuthorizeAttribute(MemberInfo methodInfo) |
||||
|
{ |
||||
|
return methodInfo.IsDefined(typeof(DataProtectedAttribute), true); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,141 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Expressions; |
||||
|
using System.Reflection; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Auditing; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public class EntityPropertyResultBuilder : IEntityPropertyResultBuilder, ITransientDependency |
||||
|
{ |
||||
|
private readonly IDataFilter _dataFilter; |
||||
|
private readonly IServiceProvider _serviceProvider; |
||||
|
private readonly AbpDataProtectionOptions _options; |
||||
|
|
||||
|
public EntityPropertyResultBuilder( |
||||
|
IDataFilter dataFilter, |
||||
|
IServiceProvider serviceProvider, |
||||
|
IOptions<AbpDataProtectionOptions> options) |
||||
|
{ |
||||
|
_options = options.Value; |
||||
|
_dataFilter = dataFilter; |
||||
|
_serviceProvider = serviceProvider; |
||||
|
} |
||||
|
|
||||
|
public virtual LambdaExpression Build(Type entityType, DataAccessOperation operation) |
||||
|
{ |
||||
|
// Func<TEntity, TEntity>
|
||||
|
var func = typeof(Func<,>).MakeGenericType(entityType, entityType); |
||||
|
var param = Expression.Parameter(entityType, "e"); |
||||
|
LambdaExpression selector = Expression.Lambda(param, param); |
||||
|
if (!ShouldApplyFilter(entityType, operation)) |
||||
|
{ |
||||
|
return selector; |
||||
|
} |
||||
|
|
||||
|
var typeName = entityType.FullName; |
||||
|
var allowProperties = new List<string>(); |
||||
|
var subjectContext = new DataAccessSubjectContributorContext(typeName, operation, _serviceProvider); |
||||
|
foreach (var contributor in _options.SubjectContributors) |
||||
|
{ |
||||
|
var properties = contributor.GetAllowProperties(subjectContext); |
||||
|
allowProperties.AddIfNotContains(properties); |
||||
|
} |
||||
|
|
||||
|
// 默认实体相关标识需要带上, 否则无法返回查询结果
|
||||
|
allowProperties.AddIfNotContains(_options.IgnoreAuditedProperties); |
||||
|
|
||||
|
if (!allowProperties.Any()) |
||||
|
{ |
||||
|
return selector; |
||||
|
} |
||||
|
|
||||
|
var memberBindings = new List<MemberBinding>(); |
||||
|
foreach (var propertyName in allowProperties) |
||||
|
{ |
||||
|
var propertyInfo = entityType.GetProperty(propertyName); |
||||
|
if (propertyInfo != null) |
||||
|
{ |
||||
|
var propertyExpression = Expression.Property(param, propertyInfo); |
||||
|
memberBindings.Add(Expression.Bind(propertyInfo, propertyExpression)); |
||||
|
} |
||||
|
} |
||||
|
var newExpression = Expression.New(entityType); |
||||
|
var memberInitExpression = Expression.MemberInit(newExpression, memberBindings); |
||||
|
|
||||
|
return Expression.Lambda(func, memberInitExpression, param); |
||||
|
} |
||||
|
|
||||
|
public virtual Expression<Func<TEntity, TEntity>> Build<TEntity>(DataAccessOperation operation) |
||||
|
{ |
||||
|
var entityType = typeof(TEntity); |
||||
|
Expression<Func<TEntity, TEntity>> selector = e => e; |
||||
|
|
||||
|
if (!ShouldApplyFilter(entityType, operation)) |
||||
|
{ |
||||
|
return selector; |
||||
|
} |
||||
|
|
||||
|
var typeName = typeof(TEntity).FullName; |
||||
|
var allowProperties = new List<string>(); |
||||
|
var subjectContext = new DataAccessSubjectContributorContext(typeName, operation, _serviceProvider); |
||||
|
foreach (var contributor in _options.SubjectContributors) |
||||
|
{ |
||||
|
var properties = contributor.GetAllowProperties(subjectContext); |
||||
|
allowProperties.AddIfNotContains(properties); |
||||
|
} |
||||
|
|
||||
|
// 默认实体相关标识需要带上, 否则无法返回查询结果
|
||||
|
allowProperties.AddIfNotContains(_options.IgnoreAuditedProperties); |
||||
|
|
||||
|
if (!allowProperties.Any()) |
||||
|
{ |
||||
|
return selector; |
||||
|
} |
||||
|
|
||||
|
var param = Expression.Parameter(typeof(TEntity), "e"); |
||||
|
var memberBindings = new List<MemberBinding>(); |
||||
|
foreach (var propertyName in allowProperties) |
||||
|
{ |
||||
|
var propertyInfo = typeof(TEntity).GetProperty(propertyName); |
||||
|
if (propertyInfo != null) |
||||
|
{ |
||||
|
var propertyExpression = Expression.Property(param, propertyInfo); |
||||
|
memberBindings.Add(Expression.Bind(propertyInfo, propertyExpression)); |
||||
|
} |
||||
|
} |
||||
|
var newExpression = Expression.New(typeof(TEntity)); |
||||
|
var memberInitExpression = Expression.MemberInit(newExpression, memberBindings); |
||||
|
|
||||
|
return Expression.Lambda<Func<TEntity, TEntity>>(memberInitExpression, param); |
||||
|
} |
||||
|
|
||||
|
private bool ShouldApplyFilter(Type entityType, DataAccessOperation operation) |
||||
|
{ |
||||
|
if (!_dataFilter.IsEnabled<IDataProtected>()) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (entityType.IsDefined(typeof(DisableDataProtectedAttribute), true)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
var dataProtected = entityType.GetCustomAttribute<DataProtectedAttribute>(); |
||||
|
|
||||
|
if (dataProtected != null && dataProtected.Operation != operation) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,326 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel; |
||||
|
using System.Globalization; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Expressions; |
||||
|
using System.Reflection; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Nodes; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
public class EntityTypeFilterBuilder : IEntityTypeFilterBuilder, ITransientDependency |
||||
|
{ |
||||
|
private readonly IDataFilter _dataFilter; |
||||
|
private readonly IServiceProvider _serviceProvider; |
||||
|
private readonly AbpDataProtectionOptions _options; |
||||
|
|
||||
|
public EntityTypeFilterBuilder( |
||||
|
IDataFilter dataFilter, |
||||
|
IServiceProvider serviceProvider, |
||||
|
IOptions<AbpDataProtectionOptions> options) |
||||
|
{ |
||||
|
_options = options.Value; |
||||
|
_dataFilter = dataFilter; |
||||
|
_serviceProvider = serviceProvider; |
||||
|
} |
||||
|
|
||||
|
public virtual LambdaExpression Build(Type entityType, DataAccessOperation operation, DataAccessFilterGroup group = null) |
||||
|
{ |
||||
|
// Func<TEntity, bool>
|
||||
|
var func = typeof(Func<,>).MakeGenericType(entityType, typeof(bool)); |
||||
|
// e => e
|
||||
|
var param = Expression.Parameter(entityType, "e"); |
||||
|
// => true
|
||||
|
var trueExp = Expression.Constant(true); |
||||
|
// Expression<Func<TEntity, bool>> exp = e => true;
|
||||
|
var exp = Expression.Lambda(func, trueExp, param); |
||||
|
|
||||
|
if (!ShouldApplyFilter(entityType, operation)) |
||||
|
{ |
||||
|
return exp; |
||||
|
} |
||||
|
|
||||
|
if (group != null) |
||||
|
{ |
||||
|
exp = GetExpression(entityType, group); |
||||
|
} |
||||
|
|
||||
|
var typeName = entityType.FullName; |
||||
|
var subjectFilterGroups = new List<DataAccessFilterGroup>(); |
||||
|
var subjectContext = new DataAccessSubjectContributorContext(typeName, operation, _serviceProvider); |
||||
|
foreach (var contributor in _options.SubjectContributors) |
||||
|
{ |
||||
|
var subjectFilterGroup = contributor.GetFilterGroups(subjectContext); |
||||
|
subjectFilterGroups.AddRange(subjectFilterGroup); |
||||
|
} |
||||
|
|
||||
|
LambdaExpression subExp = null; |
||||
|
foreach (var subGroup in subjectFilterGroups) |
||||
|
{ |
||||
|
subExp = subExp == null ? GetExpression(entityType, subGroup) : subExp.OrElse(func, GetExpression(entityType, subGroup)); |
||||
|
} |
||||
|
|
||||
|
if (subExp == null) |
||||
|
{ |
||||
|
return exp; |
||||
|
} |
||||
|
|
||||
|
if (group == null) |
||||
|
{ |
||||
|
return subExp; |
||||
|
} |
||||
|
exp = subExp.AndAlso(func, exp); |
||||
|
|
||||
|
return exp; |
||||
|
} |
||||
|
|
||||
|
public virtual Expression<Func<TEntity, bool>> Build<TEntity>(DataAccessOperation operation, DataAccessFilterGroup group = null) |
||||
|
{ |
||||
|
var entityType = typeof(TEntity); |
||||
|
Expression<Func<TEntity, bool>> exp = _ => true; |
||||
|
|
||||
|
if (!ShouldApplyFilter(entityType, operation)) |
||||
|
{ |
||||
|
return exp; |
||||
|
} |
||||
|
|
||||
|
if (group != null) |
||||
|
{ |
||||
|
exp = GetExpression<TEntity>(group); |
||||
|
} |
||||
|
|
||||
|
var typeName = typeof(TEntity).FullName; |
||||
|
var subjectFilterGroups = new List<DataAccessFilterGroup>(); |
||||
|
var subjectContext = new DataAccessSubjectContributorContext(typeName, operation, _serviceProvider); |
||||
|
foreach (var contributor in _options.SubjectContributors) |
||||
|
{ |
||||
|
var subjectFilterGroup = contributor.GetFilterGroups(subjectContext); |
||||
|
subjectFilterGroups.AddRange(subjectFilterGroup); |
||||
|
} |
||||
|
|
||||
|
Expression<Func<TEntity, bool>> subExp = null; |
||||
|
foreach ( var subGroup in subjectFilterGroups) |
||||
|
{ |
||||
|
subExp = subExp == null ? GetExpression<TEntity>(subGroup) : subExp.Or(GetExpression<TEntity>(subGroup)); |
||||
|
} |
||||
|
|
||||
|
if (subExp == null) |
||||
|
{ |
||||
|
return exp; |
||||
|
} |
||||
|
|
||||
|
if (group == null) |
||||
|
{ |
||||
|
return subExp; |
||||
|
} |
||||
|
exp = subExp.And(exp); |
||||
|
|
||||
|
return exp; |
||||
|
} |
||||
|
|
||||
|
protected virtual Expression<Func<TEntity, bool>> GetExpression<TEntity>(DataAccessFilterGroup group) |
||||
|
{ |
||||
|
Check.NotNull(group, nameof(group)); |
||||
|
|
||||
|
var param = Expression.Parameter(typeof(TEntity), "e"); |
||||
|
var body = GetExpressionBody(param, group); |
||||
|
var expression = Expression.Lambda<Func<TEntity, bool>>(body, param); |
||||
|
return expression; |
||||
|
} |
||||
|
|
||||
|
protected virtual LambdaExpression GetExpression(Type entityType, DataAccessFilterGroup group) |
||||
|
{ |
||||
|
Check.NotNull(group, nameof(group)); |
||||
|
|
||||
|
var func = typeof(Func<,>).MakeGenericType(entityType, typeof(bool)); |
||||
|
var param = Expression.Parameter(entityType, "e"); |
||||
|
var body = GetExpressionBody(param, group); |
||||
|
var expression = Expression.Lambda(func, body, param); |
||||
|
return expression; |
||||
|
} |
||||
|
|
||||
|
protected virtual Expression<Func<TEntity, bool>> GetExpression<TEntity>(DataAccessFilterRule rule) |
||||
|
{ |
||||
|
Check.NotNull(rule, nameof(rule)); |
||||
|
|
||||
|
var param = Expression.Parameter(typeof(TEntity), "e"); |
||||
|
var body = GetExpressionBody(param, rule); |
||||
|
var expression = Expression.Lambda<Func<TEntity, bool>>(body, param); |
||||
|
return expression; |
||||
|
} |
||||
|
|
||||
|
protected virtual LambdaExpression GetExpression(Type entityType, DataAccessFilterRule rule) |
||||
|
{ |
||||
|
Check.NotNull(rule, nameof(rule)); |
||||
|
|
||||
|
var func = typeof(Func<,>).MakeGenericType(entityType, typeof(bool)); |
||||
|
var param = Expression.Parameter(entityType, "e"); |
||||
|
var body = GetExpressionBody(param, rule); |
||||
|
|
||||
|
var expression = Expression.Lambda(func, body, param); |
||||
|
return expression; |
||||
|
} |
||||
|
|
||||
|
private Expression GetExpressionBody(ParameterExpression param, DataAccessFilterGroup group) |
||||
|
{ |
||||
|
Check.NotNull(param, nameof(param)); |
||||
|
|
||||
|
if (group == null || (!group.Rules.Any() && !group.Groups.Any())) |
||||
|
{ |
||||
|
return Expression.Constant(true); |
||||
|
} |
||||
|
var bodies = new List<Expression>(); |
||||
|
bodies.AddRange(group.Rules.Select(rule => GetExpressionBody(param, rule))); |
||||
|
bodies.AddRange(group.Groups.Select(subGroup => GetExpressionBody(param, subGroup))); |
||||
|
|
||||
|
return group.Logic switch { |
||||
|
DataAccessFilterLogic.And => bodies.Aggregate(Expression.AndAlso), |
||||
|
DataAccessFilterLogic.Or => bodies.Aggregate(Expression.OrElse), |
||||
|
_ => throw new InvalidOperationException($"Not allowed filter logic: {group.Logic}") |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private Expression GetExpressionBody(ParameterExpression param, DataAccessFilterRule rule) |
||||
|
{ |
||||
|
if (!_options.OperateContributors.TryGetValue(rule.Operate, out var contributor)) |
||||
|
{ |
||||
|
throw new InvalidOperationException($"Invalid data permission operator {rule.Operate}"); |
||||
|
} |
||||
|
if (rule == null) |
||||
|
{ |
||||
|
return Expression.Constant(true); |
||||
|
} |
||||
|
var expression = GetPropertyLambdaExpression(param, rule); |
||||
|
if (expression == null) |
||||
|
{ |
||||
|
return Expression.Constant(true); |
||||
|
} |
||||
|
var constant = ChangeTypeToExpression(rule, expression.Body.Type); |
||||
|
|
||||
|
return rule.IsLeft ? contributor.BuildExpression(constant, expression.Body) : contributor.BuildExpression(expression.Body, constant); |
||||
|
} |
||||
|
|
||||
|
private static LambdaExpression GetPropertyLambdaExpression(ParameterExpression param, DataAccessFilterRule rule) |
||||
|
{ |
||||
|
var propertyNames = rule.Field.Split('.'); |
||||
|
Expression propertyAccess = param; |
||||
|
var type = param.Type; |
||||
|
for (var index = 0; index < propertyNames.Length; index++) |
||||
|
{ |
||||
|
var propertyName = propertyNames[index]; |
||||
|
|
||||
|
var property = type.GetProperty(propertyName); |
||||
|
if (property == null) |
||||
|
{ |
||||
|
throw new InvalidOperationException( |
||||
|
$"The specified property '{rule.Field}' does not exist in type '{type.FullName}'"); |
||||
|
} |
||||
|
|
||||
|
type = property.PropertyType; |
||||
|
if (index == propertyNames.Length - 1) |
||||
|
{ |
||||
|
if (!CheckFilterRule(type, rule)) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
propertyAccess = Expression.MakeMemberAccess(propertyAccess, property); |
||||
|
} |
||||
|
return Expression.Lambda(propertyAccess, param); |
||||
|
} |
||||
|
|
||||
|
private Expression ChangeTypeToExpression(DataAccessFilterRule rule, Type conversionType) |
||||
|
{ |
||||
|
if (_options.KeywordContributors.TryGetValue(rule.Value?.ToString() ?? "", out var contributor)) |
||||
|
{ |
||||
|
var context = new DataAccessKeywordContributorContext(_serviceProvider); |
||||
|
var keyValue = contributor.Contribute(context); |
||||
|
var value = CastTo(keyValue, conversionType); |
||||
|
return Expression.Constant(value, conversionType); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (rule.Value is JsonElement element) |
||||
|
{ |
||||
|
var valueArray = Array.CreateInstance(conversionType, element.GetArrayLength()); |
||||
|
var index = 0; |
||||
|
foreach (var node in element.EnumerateArray()) |
||||
|
{ |
||||
|
var value = CastTo(node.ToString(), conversionType); |
||||
|
valueArray.SetValue(value, index); |
||||
|
index++; |
||||
|
} |
||||
|
var arrayType = typeof(IEnumerable<>).MakeGenericType(conversionType); |
||||
|
|
||||
|
return Expression.Constant(valueArray, arrayType); |
||||
|
} |
||||
|
|
||||
|
var valueType = rule.Value.GetType(); |
||||
|
|
||||
|
if (valueType.IsArrayOrListType()) |
||||
|
{ |
||||
|
var arrayType = typeof(IEnumerable<>).MakeGenericType(conversionType); |
||||
|
return Expression.Constant(rule.Value, arrayType); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var value = CastTo(rule.Value, conversionType); |
||||
|
return Expression.Constant(value, conversionType); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private bool ShouldApplyFilter(Type entityType, DataAccessOperation operation) |
||||
|
{ |
||||
|
if (!_dataFilter.IsEnabled<IDataProtected>()) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (entityType.IsDefined(typeof(DisableDataProtectedAttribute), true)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
var dataProtected = entityType.GetCustomAttribute<DataProtectedAttribute>(); |
||||
|
|
||||
|
if (dataProtected != null && dataProtected.Operation != operation) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
private static bool CheckFilterRule(Type type, DataAccessFilterRule rule) |
||||
|
{ |
||||
|
if (rule.Value == null || rule.Value.ToString() == string.Empty) |
||||
|
{ |
||||
|
rule.Value = null; |
||||
|
} |
||||
|
|
||||
|
return rule.Value switch { |
||||
|
null when (type == typeof(string) || type.IsNullableType()) => |
||||
|
rule.Operate == DataAccessFilterOperate.Equal || rule.Operate == DataAccessFilterOperate.NotEqual, |
||||
|
null => !type.IsValueType, |
||||
|
_ => true |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private static object CastTo(object value, Type conversionType) |
||||
|
{ |
||||
|
if (conversionType == typeof(Guid) || conversionType == typeof(Guid?)) |
||||
|
{ |
||||
|
return TypeDescriptor.GetConverter(conversionType).ConvertFromInvariantString(value.ToString()!)!; |
||||
|
} |
||||
|
return Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture); |
||||
|
} |
||||
|
} |
||||
@ -1,8 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Text; |
|
||||
|
|
||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
public interface IDataAccessCache |
|
||||
{ |
|
||||
} |
|
||||
@ -0,0 +1,6 @@ |
|||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public interface IDataAccessKeywordContributor |
||||
|
{ |
||||
|
string Keyword { get; } |
||||
|
object Contribute(DataAccessKeywordContributorContext context); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public interface IDataAccessOperateContributor |
||||
|
{ |
||||
|
DataAccessFilterOperate Operate { get; } |
||||
|
Expression BuildExpression(Expression left, Expression right); |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public interface IDataAccessSubjectContributor |
||||
|
{ |
||||
|
string Name { get; } |
||||
|
List<DataAccessFilterGroup> GetFilterGroups(DataAccessSubjectContributorContext context); |
||||
|
List<string> GetAllowProperties(DataAccessSubjectContributorContext context); |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
/// <summary>
|
||||
|
/// 数据权限验证服务
|
||||
|
/// </summary>
|
||||
|
public interface IDataAuthorizationService |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 验证操作实体数据权限
|
||||
|
/// </summary>
|
||||
|
/// <param name="operation">数据权限操作</param>
|
||||
|
/// <param name="entities">检查实体列表</param>
|
||||
|
/// <typeparam name="TEntity">实体类型</typeparam>
|
||||
|
/// <returns></returns>
|
||||
|
Task<AuthorizationResult> AuthorizeAsync<TEntity>(DataAccessOperation operation, IEnumerable<TEntity> entities); |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Authorization; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public static class IDataAuthorizationServiceExtensions |
||||
|
{ |
||||
|
public static async Task CheckAsync<TEntity>(this IDataAuthorizationService dataAuthorizationService, DataAccessOperation operation, IEnumerable<TEntity> entities) |
||||
|
{ |
||||
|
var result = await dataAuthorizationService.AuthorizeAsync(operation, entities); |
||||
|
if (!result.Succeeded) |
||||
|
{ |
||||
|
var entityKeys = entities.Select(x => x.ToString()).JoinAsString(";"); |
||||
|
throw new AbpAuthorizationException( |
||||
|
$"The {operation} operation with entity type {typeof(Entity)} identified as {entityKeys} is not allowed!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public interface IDataProtectedResourceStore |
||||
|
{ |
||||
|
void Set(DataAccessResource resource); |
||||
|
|
||||
|
void Remove(DataAccessResource resource); |
||||
|
|
||||
|
DataAccessResource Get(string subjectName, string subjectId, string entityTypeFullName, DataAccessOperation operation); |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
public interface IDataProtectionRepository<TEntity> : IDataProtectedEnabled |
||||
|
{ |
||||
|
Task<IQueryable<TEntity>> GetQueryableAsync(); |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
/// <summary>
|
||||
|
/// 实体属性返回值构造器
|
||||
|
/// </summary>
|
||||
|
public interface IEntityPropertyResultBuilder |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 获取实体的属性返回值过滤表达式
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TEntity">实体类型</typeparam>
|
||||
|
/// <param name="operation">数据操作方式</param>
|
||||
|
/// <returns></returns>
|
||||
|
Expression<Func<TEntity, TEntity>> Build<TEntity>(DataAccessOperation operation); |
||||
|
/// <summary>
|
||||
|
/// 获取实体的属性返回值过滤表达式
|
||||
|
/// </summary>
|
||||
|
/// <param name="entityType">实体类型</param>
|
||||
|
/// <param name="operation">数据操作方式</param>
|
||||
|
/// <returns></returns>
|
||||
|
LambdaExpression Build(Type entityType, DataAccessOperation operation); |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
/// <summary>
|
||||
|
/// 实体过滤条件构造器
|
||||
|
/// </summary>
|
||||
|
public interface IEntityTypeFilterBuilder |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 获取实体的查询过滤表达式
|
||||
|
/// </summary>
|
||||
|
/// <param name="operation">数据权限操作</param>
|
||||
|
/// <param name="group">查询条件组</param>
|
||||
|
/// <typeparam name="TEntity">实体类型</typeparam>
|
||||
|
/// <returns></returns>
|
||||
|
Expression<Func<TEntity, bool>> Build<TEntity>(DataAccessOperation operation, DataAccessFilterGroup group = null); |
||||
|
|
||||
|
LambdaExpression Build(Type entityType, DataAccessOperation operation, DataAccessFilterGroup group = null); |
||||
|
} |
||||
@ -1,5 +0,0 @@ |
|||||
namespace LINGYUN.Abp.DataProtection; |
|
||||
public interface IHasDataAccess |
|
||||
{ |
|
||||
public DataAccessOwner Owner { get; } |
|
||||
} |
|
||||
@ -0,0 +1,37 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System.Collections.Concurrent; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection; |
||||
|
|
||||
|
[Dependency(ServiceLifetime.Singleton, TryRegister = true)] |
||||
|
public class InMemoryDataProtectedResourceStore : IDataProtectedResourceStore |
||||
|
{ |
||||
|
private readonly static ConcurrentDictionary<string, DataAccessResource> _cache = new ConcurrentDictionary<string, DataAccessResource>(); |
||||
|
public DataAccessResource Get(string subjectName, string subjectId, string entityTypeFullName, DataAccessOperation operation) |
||||
|
{ |
||||
|
var key = NormalizeKey(subjectName, subjectId, entityTypeFullName, operation); |
||||
|
if (_cache.TryGetValue(key, out var resource)) |
||||
|
{ |
||||
|
return resource; |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public void Remove(DataAccessResource resource) |
||||
|
{ |
||||
|
var key = NormalizeKey(resource.SubjectName, resource.SubjectId, resource.EntityTypeFullName, resource.Operation); |
||||
|
_cache.TryRemove(key, out var _); |
||||
|
} |
||||
|
|
||||
|
public void Set(DataAccessResource resource) |
||||
|
{ |
||||
|
var key = NormalizeKey(resource.SubjectName, resource.SubjectId, resource.EntityTypeFullName, resource.Operation); |
||||
|
_cache.TryAdd(key, resource); |
||||
|
} |
||||
|
|
||||
|
private static string NormalizeKey(string subjectName, string subjectId, string entityTypeFullName, DataAccessOperation operation) |
||||
|
{ |
||||
|
return $"{subjectName}_{subjectId}_{entityTypeFullName}_{operation}"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Keywords; |
||||
|
public class DataAccessCurrentUserContributor : IDataAccessKeywordContributor |
||||
|
{ |
||||
|
public const string Name = "@CurrentUser"; |
||||
|
public string Keyword => Name; |
||||
|
|
||||
|
public object Contribute(DataAccessKeywordContributorContext context) |
||||
|
{ |
||||
|
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>(); |
||||
|
return currentUser.Id; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessContainsContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.Contains; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
if (left.Type == typeof(string)) |
||||
|
{ |
||||
|
return Expression.Call(left, |
||||
|
typeof(string).GetMethod("Contains", new[] { typeof(string) }) |
||||
|
?? throw new InvalidOperationException("The method named \"Contains\" does not exist"), |
||||
|
right); |
||||
|
} |
||||
|
|
||||
|
if (left.Type.IsArrayOrListType()) |
||||
|
{ |
||||
|
var method = typeof(Enumerable).GetMethods().Where(x => x.Name == "Contains").FirstOrDefault(); |
||||
|
var methodType = method?.MakeGenericMethod(left.Type.GetGenericArguments()[0]); |
||||
|
return Expression.Call( |
||||
|
null, |
||||
|
methodType ?? throw new InvalidOperationException("The method named \"Contains\" does not exist"), |
||||
|
left, |
||||
|
right); |
||||
|
} |
||||
|
|
||||
|
throw new NotSupportedException("\"Contains\" only supports data of string or array type!"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessEndsWithContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.EndsWith; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
if (left.Type != typeof(string)) |
||||
|
{ |
||||
|
throw new NotSupportedException("\"EndsWith\" only supports data of string type!"); |
||||
|
} |
||||
|
return Expression.Call(left, |
||||
|
typeof(string).GetMethod("EndsWith", new[] { typeof(string) }) |
||||
|
?? throw new InvalidOperationException("The method named \"EndsWith\" does not exist!"), |
||||
|
right); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessEqualContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.Equal; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
return Expression.Equal(left, right); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessGreaterContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.Greater; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
return Expression.GreaterThan(left, right); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessGreaterOrEqualContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.GreaterOrEqual; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
return Expression.GreaterThanOrEqual(left, right); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessLessContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.Less; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
return Expression.LessThan(left, right); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessLessOrEqualContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.LessOrEqual; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
return Expression.LessThanOrEqual(left, right); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessNotContainsContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.NotContains; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
|
||||
|
if (left.Type == typeof(string)) |
||||
|
{ |
||||
|
// string.Contains(string);
|
||||
|
return Expression.Not(Expression.Call(left, |
||||
|
typeof(string).GetMethod("Contains", new[] { typeof(string) }) |
||||
|
?? throw new InvalidOperationException("The method named \"NotContains\" does not exist"), |
||||
|
right)); |
||||
|
} |
||||
|
|
||||
|
if (left.Type.IsArrayOrListType()) |
||||
|
{ |
||||
|
// IEnumerable<T>.Contains(T);
|
||||
|
var method = typeof(Enumerable).GetMethods().Where(x => x.Name == "Contains").FirstOrDefault(); |
||||
|
var methodType = method?.MakeGenericMethod(left.Type.GetGenericArguments()[0]); |
||||
|
return Expression.Not(Expression.Call( |
||||
|
null, |
||||
|
methodType ?? throw new InvalidOperationException("The method named \"NotContains\" does not exist"), |
||||
|
left, |
||||
|
right)); |
||||
|
} |
||||
|
|
||||
|
throw new NotSupportedException("\"NotContains\" only supports data of string or array type!"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessNotEqualContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.NotEqual; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
return Expression.NotEqual(left, right); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using System.Linq.Expressions; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Operations; |
||||
|
public class DataAccessStartsWithContributor : IDataAccessOperateContributor |
||||
|
{ |
||||
|
public DataAccessFilterOperate Operate => DataAccessFilterOperate.StartsWith; |
||||
|
|
||||
|
public Expression BuildExpression(Expression left, Expression right) |
||||
|
{ |
||||
|
if (left.Type != typeof(string)) |
||||
|
{ |
||||
|
throw new NotSupportedException("\"StartsWith\" only supports data of string type!"); |
||||
|
} |
||||
|
return Expression.Call(left, |
||||
|
typeof(string).GetMethod("StartsWith", new[] { typeof(string) }) |
||||
|
?? throw new InvalidOperationException("The method named \"StartsWith\" does not exist!"), |
||||
|
right); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
using LINGYUN.Abp.Authorization.Permissions; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Subjects; |
||||
|
|
||||
|
public class DataAccessOrganizationUnitContributor : IDataAccessSubjectContributor |
||||
|
{ |
||||
|
public string Name => OrganizationUnitPermissionValueProvider.ProviderName; |
||||
|
|
||||
|
public virtual List<DataAccessFilterGroup> GetFilterGroups(DataAccessSubjectContributorContext context) |
||||
|
{ |
||||
|
var groups = new List<DataAccessFilterGroup>(); |
||||
|
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>(); |
||||
|
if (currentUser.IsAuthenticated) |
||||
|
{ |
||||
|
var resourceStore = context.ServiceProvider.GetRequiredService<IDataProtectedResourceStore>(); |
||||
|
var orgCodes = currentUser.FindOrganizationUnits(); |
||||
|
foreach (var orgCode in orgCodes) |
||||
|
{ |
||||
|
var resource = resourceStore.Get(Name, orgCode, context.EntityTypeFullName, context.Operation); |
||||
|
if (resource?.FilterGroup != null) |
||||
|
{ |
||||
|
groups.Add(resource.FilterGroup); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return groups; |
||||
|
} |
||||
|
|
||||
|
public virtual List<string> GetAllowProperties(DataAccessSubjectContributorContext context) |
||||
|
{ |
||||
|
var allowProperties = new List<string>(); |
||||
|
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>(); |
||||
|
if (currentUser.IsAuthenticated) |
||||
|
{ |
||||
|
var resourceStore = context.ServiceProvider.GetRequiredService<IDataProtectedResourceStore>(); |
||||
|
var orgCodes = currentUser.FindOrganizationUnits(); |
||||
|
foreach (var orgCode in orgCodes) |
||||
|
{ |
||||
|
var resource = resourceStore.Get(Name, orgCode, context.EntityTypeFullName, context.Operation); |
||||
|
if (resource?.AllowProperties.Any() == true) |
||||
|
{ |
||||
|
allowProperties.AddIfNotContains(resource.AllowProperties); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return allowProperties; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Subjects; |
||||
|
|
||||
|
public class DataAccessRoleNameContributor : IDataAccessSubjectContributor |
||||
|
{ |
||||
|
public string Name => RolePermissionValueProvider.ProviderName; |
||||
|
|
||||
|
public virtual List<DataAccessFilterGroup> GetFilterGroups(DataAccessSubjectContributorContext context) |
||||
|
{ |
||||
|
var groups = new List<DataAccessFilterGroup>(); |
||||
|
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>(); |
||||
|
if (currentUser.IsAuthenticated) |
||||
|
{ |
||||
|
var resourceStore = context.ServiceProvider.GetRequiredService<IDataProtectedResourceStore>(); |
||||
|
var roles = currentUser.Roles; |
||||
|
foreach (var role in roles) |
||||
|
{ |
||||
|
var resource = resourceStore.Get(Name, role, context.EntityTypeFullName, context.Operation); |
||||
|
if (resource?.FilterGroup != null) |
||||
|
{ |
||||
|
groups.Add(resource.FilterGroup); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return groups; |
||||
|
} |
||||
|
|
||||
|
public virtual List<string> GetAllowProperties(DataAccessSubjectContributorContext context) |
||||
|
{ |
||||
|
var allowProperties = new List<string>(); |
||||
|
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>(); |
||||
|
if (currentUser.IsAuthenticated) |
||||
|
{ |
||||
|
var resourceStore = context.ServiceProvider.GetRequiredService<IDataProtectedResourceStore>(); |
||||
|
var roles = currentUser.Roles; |
||||
|
foreach (var role in roles) |
||||
|
{ |
||||
|
var resource = resourceStore.Get(Name, role, context.EntityTypeFullName, context.Operation); |
||||
|
if (resource?.AllowProperties.Any() == true) |
||||
|
{ |
||||
|
allowProperties.AddIfNotContains(resource.AllowProperties); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return allowProperties; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Users; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtection.Subjects; |
||||
|
|
||||
|
public class DataAccessUserIdContributor : IDataAccessSubjectContributor |
||||
|
{ |
||||
|
public string Name => UserPermissionValueProvider.ProviderName; |
||||
|
|
||||
|
public virtual List<DataAccessFilterGroup> GetFilterGroups(DataAccessSubjectContributorContext context) |
||||
|
{ |
||||
|
var groups = new List<DataAccessFilterGroup>(); |
||||
|
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>(); |
||||
|
if (currentUser.IsAuthenticated) |
||||
|
{ |
||||
|
var resourceStore = context.ServiceProvider.GetRequiredService<IDataProtectedResourceStore>(); |
||||
|
var resource = resourceStore.Get(Name, currentUser.Id.ToString(), context.EntityTypeFullName, context.Operation); |
||||
|
if (resource?.FilterGroup != null) |
||||
|
{ |
||||
|
groups.Add(resource.FilterGroup); |
||||
|
} |
||||
|
} |
||||
|
return groups; |
||||
|
} |
||||
|
|
||||
|
public virtual List<string> GetAllowProperties(DataAccessSubjectContributorContext context) |
||||
|
{ |
||||
|
var allowProperties = new List<string>(); |
||||
|
var currentUser = context.ServiceProvider.GetRequiredService<ICurrentUser>(); |
||||
|
if (currentUser.IsAuthenticated) |
||||
|
{ |
||||
|
var resourceStore = context.ServiceProvider.GetRequiredService<IDataProtectedResourceStore>(); |
||||
|
var resource = resourceStore.Get(Name, currentUser.Id.ToString(), context.EntityTypeFullName, context.Operation); |
||||
|
if (resource?.AllowProperties.Any() == true) |
||||
|
{ |
||||
|
allowProperties.AddIfNotContains(resource.AllowProperties); |
||||
|
} |
||||
|
} |
||||
|
return allowProperties; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
namespace System.Linq.Expressions; |
||||
|
internal static class ExpressionFuncExtender |
||||
|
{ |
||||
|
internal static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, |
||||
|
Func<Expression, Expression, Expression> merge) |
||||
|
{ |
||||
|
// build parameter map (from parameters of second to parameters of first)
|
||||
|
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }) |
||||
|
.ToDictionary(p => p.s, p => p.f); |
||||
|
|
||||
|
// replace parameters in the second lambda expression with parameters from the first
|
||||
|
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); |
||||
|
|
||||
|
// apply composition of lambda expression bodies to parameters from the first expression
|
||||
|
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters); |
||||
|
} |
||||
|
|
||||
|
internal static LambdaExpression Compose(this LambdaExpression first, |
||||
|
Type delegateType, |
||||
|
LambdaExpression second, |
||||
|
Func<Expression, Expression, Expression> merge) |
||||
|
{ |
||||
|
// build parameter map (from parameters of second to parameters of first)
|
||||
|
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }) |
||||
|
.ToDictionary(p => p.s, p => p.f); |
||||
|
|
||||
|
// replace parameters in the second lambda expression with parameters from the first
|
||||
|
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); |
||||
|
|
||||
|
// apply composition of lambda expression bodies to parameters from the first expression
|
||||
|
return Expression.Lambda(delegateType, merge(first.Body, secondBody), first.Parameters); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Combines two given expressions by using the AND semantics.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The type of the object.</typeparam>
|
||||
|
/// <param name="first">The first part of the expression.</param>
|
||||
|
/// <param name="second">The second part of the expression.</param>
|
||||
|
/// <returns>The combined expression.</returns>
|
||||
|
public static LambdaExpression AndAlso(this LambdaExpression first, |
||||
|
Type delegateType, |
||||
|
LambdaExpression second) |
||||
|
{ |
||||
|
return first.Compose(delegateType, second, Expression.AndAlso); |
||||
|
} |
||||
|
|
||||
|
public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> first, |
||||
|
Expression<Func<T, bool>> second) |
||||
|
{ |
||||
|
return first.Compose(second, Expression.AndAlso); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Combines two given expressions by using the OR semantics.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The type of the object.</typeparam>
|
||||
|
/// <param name="first">The first part of the expression.</param>
|
||||
|
/// <param name="second">The second part of the expression.</param>
|
||||
|
/// <returns>The combined expression.</returns>
|
||||
|
public static LambdaExpression OrElse(this LambdaExpression first, |
||||
|
Type delegateType, |
||||
|
LambdaExpression second) |
||||
|
{ |
||||
|
return first.Compose(delegateType, second, Expression.OrElse); |
||||
|
} |
||||
|
|
||||
|
public static Expression<Func<T, bool>> OrElse<T>(this Expression<Func<T, bool>> first, |
||||
|
Expression<Func<T, bool>> second) |
||||
|
{ |
||||
|
return first.Compose(second, Expression.OrElse); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
namespace System.Linq.Expressions; |
||||
|
|
||||
|
public static class ExpressionFuncExtensions |
||||
|
{ |
||||
|
public static Expression<Func<T, bool>> AndIf<T>( |
||||
|
this Expression<Func<T, bool>> first, |
||||
|
bool condition, |
||||
|
Expression<Func<T, bool>> second) |
||||
|
{ |
||||
|
if (condition) |
||||
|
{ |
||||
|
return ExpressionFuncExtender.AndAlso(first, second); |
||||
|
} |
||||
|
|
||||
|
return first; |
||||
|
} |
||||
|
|
||||
|
public static Expression<Func<T, bool>> OrIf<T>( |
||||
|
this Expression<Func<T, bool>> first, |
||||
|
bool condition, |
||||
|
Expression<Func<T, bool>> second) |
||||
|
{ |
||||
|
if (condition) |
||||
|
{ |
||||
|
return ExpressionFuncExtender.OrElse(first, second); |
||||
|
} |
||||
|
|
||||
|
return first; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace System.Linq.Expressions; |
||||
|
internal class ParameterRebinder : ExpressionVisitor |
||||
|
{ |
||||
|
private readonly Dictionary<ParameterExpression, ParameterExpression> _map; |
||||
|
|
||||
|
internal ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map) |
||||
|
{ |
||||
|
_map = map ?? new Dictionary<ParameterExpression, ParameterExpression>(); |
||||
|
} |
||||
|
|
||||
|
internal static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, |
||||
|
Expression exp) |
||||
|
{ |
||||
|
return new ParameterRebinder(map).Visit(exp); |
||||
|
} |
||||
|
|
||||
|
protected override Expression VisitParameter(ParameterExpression p) |
||||
|
{ |
||||
|
if (_map.TryGetValue(p, out var replacement)) |
||||
|
{ |
||||
|
p = replacement; |
||||
|
} |
||||
|
|
||||
|
return base.VisitParameter(p); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace System.Reflection; |
||||
|
|
||||
|
internal static class NullableTypeExtensions |
||||
|
{ |
||||
|
public static bool IsNullableType(this Type theType) |
||||
|
{ |
||||
|
return theType.IsGenericType(typeof(Nullable<>)); |
||||
|
} |
||||
|
|
||||
|
public static bool IsGenericType(this Type type, Type genericType) |
||||
|
{ |
||||
|
return type.IsGenericType && type.GetGenericTypeDefinition() == genericType; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using System.Collections; |
||||
|
|
||||
|
namespace System; |
||||
|
internal static class TypeExtensions |
||||
|
{ |
||||
|
public static bool IsArrayOrListType(this Type type) |
||||
|
{ |
||||
|
if (type.IsArray) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (type.IsGenericType) |
||||
|
{ |
||||
|
if (typeof(IList).IsAssignableFrom(type)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (typeof(IEnumerable).IsAssignableFrom(type)) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
@ -1,24 +0,0 @@ |
|||||
using LINGYUN.Abp.DataProtection; |
|
||||
|
|
||||
namespace Volo.Abp.Uow; |
|
||||
public static class IUnitOfWorkDataAccessExtensions |
|
||||
{ |
|
||||
private const string DataAccessRuleKey = "LINGYUN.Abp.DataProtection.DataAccess"; |
|
||||
|
|
||||
public static IUnitOfWork SetAccessRuleInfo( |
|
||||
this IUnitOfWork unitOfWork, |
|
||||
DataAccessRuleInfo dataAccessRuleInfo) |
|
||||
{ |
|
||||
unitOfWork.RemoveItem(DataAccessRuleKey); |
|
||||
unitOfWork.AddItem(DataAccessRuleKey, dataAccessRuleInfo); |
|
||||
|
|
||||
return unitOfWork; |
|
||||
} |
|
||||
|
|
||||
public static DataAccessRuleInfo GetAccessRuleInfo( |
|
||||
this IUnitOfWork unitOfWork) |
|
||||
{ |
|
||||
return unitOfWork.GetItemOrDefault<DataAccessRuleInfo>(DataAccessRuleKey) |
|
||||
?? new DataAccessRuleInfo(null); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,932 @@ |
|||||
|
// <auto-generated />
|
||||
|
using System; |
||||
|
using LY.MicroService.BackendAdmin.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Infrastructure; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
|
||||
|
#nullable disable |
||||
|
|
||||
|
namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations |
||||
|
{ |
||||
|
[DbContext(typeof(BackendAdminMigrationsDbContext))] |
||||
|
[Migration("20240515073346_Add-Data-Protected-Module")] |
||||
|
partial class AddDataProtectedModule |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder) |
||||
|
{ |
||||
|
#pragma warning disable 612, 618
|
||||
|
modelBuilder |
||||
|
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) |
||||
|
.HasAnnotation("ProductVersion", "8.0.0") |
||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)") |
||||
|
.HasColumnName("DisplayName"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)") |
||||
|
.HasColumnName("Name"); |
||||
|
|
||||
|
b.Property<string>("TypeFullName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)") |
||||
|
.HasColumnName("TypeFullName"); |
||||
|
|
||||
|
b.Property<Guid>("TypeInfoId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ValueRange") |
||||
|
.HasMaxLength(512) |
||||
|
.HasColumnType("varchar(512)") |
||||
|
.HasColumnName("ValueRange"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TypeInfoId", "TypeFullName"); |
||||
|
|
||||
|
b.ToTable("AbpAuthEntityProperties", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)") |
||||
|
.HasColumnName("DisplayName"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsAuditEnabled") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)") |
||||
|
.HasColumnName("Name"); |
||||
|
|
||||
|
b.Property<string>("TypeFullName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)") |
||||
|
.HasColumnName("TypeFullName"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TypeFullName"); |
||||
|
|
||||
|
b.ToTable("AbpAuthEntitites", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<string>("EntityTypeFullName") |
||||
|
.HasColumnType("longtext"); |
||||
|
|
||||
|
b.Property<Guid>("EntityTypeId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("FilterGroup") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("FilterGroup"); |
||||
|
|
||||
|
b.Property<bool>("IsEnabled") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<int>("Operation") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<string>("OrgCode") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)") |
||||
|
.HasColumnName("OrgCode"); |
||||
|
|
||||
|
b.Property<Guid>("OrgId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("TenantId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("EntityTypeId"); |
||||
|
|
||||
|
b.ToTable("AbpAuthOrganizationUnitEntityRules", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<string>("EntityTypeFullName") |
||||
|
.HasColumnType("longtext"); |
||||
|
|
||||
|
b.Property<Guid>("EntityTypeId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("FilterGroup") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("FilterGroup"); |
||||
|
|
||||
|
b.Property<bool>("IsEnabled") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<int>("Operation") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<Guid>("RoleId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("RoleName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)") |
||||
|
.HasColumnName("RoleName"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("TenantId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("EntityTypeId"); |
||||
|
|
||||
|
b.ToTable("AbpAuthRoleEntityRules", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Editions.Edition", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<Guid?>("DeleterId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("DeleterId"); |
||||
|
|
||||
|
b.Property<DateTime?>("DeletionTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("DeletionTime"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<int>("EntityVersion") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsDeleted") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("tinyint(1)") |
||||
|
.HasDefaultValue(false) |
||||
|
.HasColumnName("IsDeleted"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("DisplayName"); |
||||
|
|
||||
|
b.ToTable("AbpEditions", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<Guid?>("DeleterId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("DeleterId"); |
||||
|
|
||||
|
b.Property<DateTime?>("DeletionTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("DeletionTime"); |
||||
|
|
||||
|
b.Property<DateTime?>("DisableTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("EditionId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<DateTime?>("EnableTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<int>("EntityVersion") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsActive") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsDeleted") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("tinyint(1)") |
||||
|
.HasDefaultValue(false) |
||||
|
.HasColumnName("IsDeleted"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("NormalizedName") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("EditionId"); |
||||
|
|
||||
|
b.HasIndex("Name"); |
||||
|
|
||||
|
b.HasIndex("NormalizedName"); |
||||
|
|
||||
|
b.ToTable("AbpTenants", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => |
||||
|
{ |
||||
|
b.Property<Guid>("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("Value") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(1024) |
||||
|
.HasColumnType("varchar(1024)"); |
||||
|
|
||||
|
b.HasKey("TenantId", "Name"); |
||||
|
|
||||
|
b.ToTable("AbpTenantConnectionStrings", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplate", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Content") |
||||
|
.HasMaxLength(1048576) |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("Content"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<string>("Culture") |
||||
|
.HasMaxLength(30) |
||||
|
.HasColumnType("varchar(30)") |
||||
|
.HasColumnName("Culture"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(100) |
||||
|
.HasColumnType("varchar(100)") |
||||
|
.HasColumnName("DisplayName"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(100) |
||||
|
.HasColumnType("varchar(100)") |
||||
|
.HasColumnName("Name"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("TenantId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "Name") |
||||
|
.HasDatabaseName("IX_Tenant_Text_Template_Name"); |
||||
|
|
||||
|
b.ToTable("AbpTextTemplates", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplateDefinition", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<string>("DefaultCultureName") |
||||
|
.HasMaxLength(30) |
||||
|
.HasColumnType("varchar(30)") |
||||
|
.HasColumnName("DefaultCultureName"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(512) |
||||
|
.HasColumnType("varchar(512)") |
||||
|
.HasColumnName("DisplayName"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsInlineLocalized") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsLayout") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsStatic") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<string>("Layout") |
||||
|
.HasMaxLength(60) |
||||
|
.HasColumnType("varchar(60)") |
||||
|
.HasColumnName("Layout"); |
||||
|
|
||||
|
b.Property<string>("LocalizationResourceName") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)") |
||||
|
.HasColumnName("LocalizationResourceName"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)") |
||||
|
.HasColumnName("Name"); |
||||
|
|
||||
|
b.Property<string>("RenderEngine") |
||||
|
.HasMaxLength(30) |
||||
|
.HasColumnType("varchar(30)") |
||||
|
.HasColumnName("RenderEngine"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.ToTable("AbpTextTemplateDefinitions", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("AllowedProviders") |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("DefaultValue") |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("Description") |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("GroupName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<bool>("IsAvailableToHost") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsVisibleToClients") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ParentName") |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ValueType") |
||||
|
.HasMaxLength(2048) |
||||
|
.HasColumnType("varchar(2048)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("GroupName"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpFeatures", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpFeatureGroups", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ProviderKey") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("ProviderName") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("Value") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name", "ProviderName", "ProviderKey") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpFeatureValues", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("GroupName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<bool>("IsEnabled") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<byte>("MultiTenancySide") |
||||
|
.HasColumnType("tinyint unsigned"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ParentName") |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("Providers") |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("StateCheckers") |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("GroupName"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpPermissions", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ProviderKey") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("ProviderName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("TenantId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpPermissionGrants", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpPermissionGroups", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ProviderKey") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("ProviderName") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("Value") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(2048) |
||||
|
.HasColumnType("varchar(2048)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name", "ProviderName", "ProviderKey") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpSettings", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DefaultValue") |
||||
|
.HasMaxLength(2048) |
||||
|
.HasColumnType("varchar(2048)"); |
||||
|
|
||||
|
b.Property<string>("Description") |
||||
|
.HasMaxLength(512) |
||||
|
.HasColumnType("varchar(512)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsEncrypted") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsInherited") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsVisibleToClients") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("Providers") |
||||
|
.HasMaxLength(1024) |
||||
|
.HasColumnType("varchar(1024)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpSettingDefinitions", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "TypeInfo") |
||||
|
.WithMany("Properties") |
||||
|
.HasForeignKey("TypeInfoId") |
||||
|
.OnDelete(DeleteBehavior.Cascade) |
||||
|
.IsRequired(); |
||||
|
|
||||
|
b.Navigation("TypeInfo"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo") |
||||
|
.WithMany() |
||||
|
.HasForeignKey("EntityTypeId") |
||||
|
.OnDelete(DeleteBehavior.Cascade) |
||||
|
.IsRequired(); |
||||
|
|
||||
|
b.Navigation("EntityTypeInfo"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo") |
||||
|
.WithMany() |
||||
|
.HasForeignKey("EntityTypeId") |
||||
|
.OnDelete(DeleteBehavior.Cascade) |
||||
|
.IsRequired(); |
||||
|
|
||||
|
b.Navigation("EntityTypeInfo"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.Saas.Editions.Edition", "Edition") |
||||
|
.WithMany() |
||||
|
.HasForeignKey("EditionId"); |
||||
|
|
||||
|
b.Navigation("Edition"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.Saas.Tenants.Tenant", null) |
||||
|
.WithMany("ConnectionStrings") |
||||
|
.HasForeignKey("TenantId") |
||||
|
.OnDelete(DeleteBehavior.Cascade) |
||||
|
.IsRequired(); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b => |
||||
|
{ |
||||
|
b.Navigation("Properties"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => |
||||
|
{ |
||||
|
b.Navigation("ConnectionStrings"); |
||||
|
}); |
||||
|
#pragma warning restore 612, 618
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,179 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
#nullable disable |
||||
|
|
||||
|
namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public partial class AddDataProtectedModule : Migration |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AbpAuthEntitites", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
Name = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
DisplayName = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
TypeFullName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
IsAuditEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false), |
||||
|
ExtraProperties = table.Column<string>(type: "longtext", nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
||||
|
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci") |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AbpAuthEntitites", x => x.Id); |
||||
|
}) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AbpAuthEntityProperties", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
Name = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
DisplayName = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
TypeFullName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ValueRange = table.Column<string>(type: "varchar(512)", maxLength: 512, nullable: true) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
TypeInfoId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci") |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AbpAuthEntityProperties", x => x.Id); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_AbpAuthEntityProperties_AbpAuthEntitites_TypeInfoId", |
||||
|
column: x => x.TypeInfoId, |
||||
|
principalTable: "AbpAuthEntitites", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Cascade); |
||||
|
}) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AbpAuthOrganizationUnitEntityRules", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
OrgId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
OrgCode = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ExtraProperties = table.Column<string>(type: "longtext", nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
||||
|
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false), |
||||
|
Operation = table.Column<int>(type: "int", nullable: false), |
||||
|
FilterGroup = table.Column<string>(type: "longtext", nullable: true) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
EntityTypeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
EntityTypeFullName = table.Column<string>(type: "longtext", nullable: true) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4") |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AbpAuthOrganizationUnitEntityRules", x => x.Id); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_AbpAuthOrganizationUnitEntityRules_AbpAuthEntitites_EntityTy~", |
||||
|
column: x => x.EntityTypeId, |
||||
|
principalTable: "AbpAuthEntitites", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Cascade); |
||||
|
}) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "AbpAuthRoleEntityRules", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
RoleId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
RoleName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ExtraProperties = table.Column<string>(type: "longtext", nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
||||
|
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false), |
||||
|
Operation = table.Column<int>(type: "int", nullable: false), |
||||
|
FilterGroup = table.Column<string>(type: "longtext", nullable: true) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
EntityTypeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
EntityTypeFullName = table.Column<string>(type: "longtext", nullable: true) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4") |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_AbpAuthRoleEntityRules", x => x.Id); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_AbpAuthRoleEntityRules_AbpAuthEntitites_EntityTypeId", |
||||
|
column: x => x.EntityTypeId, |
||||
|
principalTable: "AbpAuthEntitites", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Cascade); |
||||
|
}) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AbpAuthEntitites_TypeFullName", |
||||
|
table: "AbpAuthEntitites", |
||||
|
column: "TypeFullName"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AbpAuthEntityProperties_TypeInfoId_TypeFullName", |
||||
|
table: "AbpAuthEntityProperties", |
||||
|
columns: new[] { "TypeInfoId", "TypeFullName" }); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AbpAuthOrganizationUnitEntityRules_EntityTypeId", |
||||
|
table: "AbpAuthOrganizationUnitEntityRules", |
||||
|
column: "EntityTypeId"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_AbpAuthRoleEntityRules_EntityTypeId", |
||||
|
table: "AbpAuthRoleEntityRules", |
||||
|
column: "EntityTypeId"); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AbpAuthEntityProperties"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AbpAuthOrganizationUnitEntityRules"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AbpAuthRoleEntityRules"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "AbpAuthEntitites"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,942 @@ |
|||||
|
// <auto-generated />
|
||||
|
using System; |
||||
|
using LY.MicroService.BackendAdmin.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore.Infrastructure; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
|
||||
|
#nullable disable |
||||
|
|
||||
|
namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations |
||||
|
{ |
||||
|
[DbContext(typeof(BackendAdminMigrationsDbContext))] |
||||
|
[Migration("20240515092715_Add-Allow-Properties")] |
||||
|
partial class AddAllowProperties |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder) |
||||
|
{ |
||||
|
#pragma warning disable 612, 618
|
||||
|
modelBuilder |
||||
|
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) |
||||
|
.HasAnnotation("ProductVersion", "8.0.0") |
||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)") |
||||
|
.HasColumnName("DisplayName"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)") |
||||
|
.HasColumnName("Name"); |
||||
|
|
||||
|
b.Property<string>("TypeFullName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)") |
||||
|
.HasColumnName("TypeFullName"); |
||||
|
|
||||
|
b.Property<Guid>("TypeInfoId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ValueRange") |
||||
|
.HasMaxLength(512) |
||||
|
.HasColumnType("varchar(512)") |
||||
|
.HasColumnName("ValueRange"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TypeInfoId", "TypeFullName"); |
||||
|
|
||||
|
b.ToTable("AbpAuthEntityProperties", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)") |
||||
|
.HasColumnName("DisplayName"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsAuditEnabled") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)") |
||||
|
.HasColumnName("Name"); |
||||
|
|
||||
|
b.Property<string>("TypeFullName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)") |
||||
|
.HasColumnName("TypeFullName"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TypeFullName"); |
||||
|
|
||||
|
b.ToTable("AbpAuthEntitites", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("AllowProperties") |
||||
|
.HasMaxLength(512) |
||||
|
.HasColumnType("varchar(512)") |
||||
|
.HasColumnName("AllowProperties"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<string>("EntityTypeFullName") |
||||
|
.HasColumnType("longtext"); |
||||
|
|
||||
|
b.Property<Guid>("EntityTypeId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("FilterGroup") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("FilterGroup"); |
||||
|
|
||||
|
b.Property<bool>("IsEnabled") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<int>("Operation") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<string>("OrgCode") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)") |
||||
|
.HasColumnName("OrgCode"); |
||||
|
|
||||
|
b.Property<Guid>("OrgId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("TenantId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("EntityTypeId"); |
||||
|
|
||||
|
b.ToTable("AbpAuthOrganizationUnitEntityRules", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("AllowProperties") |
||||
|
.HasMaxLength(512) |
||||
|
.HasColumnType("varchar(512)") |
||||
|
.HasColumnName("AllowProperties"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<string>("EntityTypeFullName") |
||||
|
.HasColumnType("longtext"); |
||||
|
|
||||
|
b.Property<Guid>("EntityTypeId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("FilterGroup") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("FilterGroup"); |
||||
|
|
||||
|
b.Property<bool>("IsEnabled") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<int>("Operation") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<Guid>("RoleId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("RoleName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)") |
||||
|
.HasColumnName("RoleName"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("TenantId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("EntityTypeId"); |
||||
|
|
||||
|
b.ToTable("AbpAuthRoleEntityRules", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Editions.Edition", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<Guid?>("DeleterId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("DeleterId"); |
||||
|
|
||||
|
b.Property<DateTime?>("DeletionTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("DeletionTime"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<int>("EntityVersion") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsDeleted") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("tinyint(1)") |
||||
|
.HasDefaultValue(false) |
||||
|
.HasColumnName("IsDeleted"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("DisplayName"); |
||||
|
|
||||
|
b.ToTable("AbpEditions", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<Guid?>("DeleterId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("DeleterId"); |
||||
|
|
||||
|
b.Property<DateTime?>("DeletionTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("DeletionTime"); |
||||
|
|
||||
|
b.Property<DateTime?>("DisableTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<Guid?>("EditionId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<DateTime?>("EnableTime") |
||||
|
.HasColumnType("datetime(6)"); |
||||
|
|
||||
|
b.Property<int>("EntityVersion") |
||||
|
.HasColumnType("int"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsActive") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsDeleted") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("tinyint(1)") |
||||
|
.HasDefaultValue(false) |
||||
|
.HasColumnName("IsDeleted"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("NormalizedName") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("EditionId"); |
||||
|
|
||||
|
b.HasIndex("Name"); |
||||
|
|
||||
|
b.HasIndex("NormalizedName"); |
||||
|
|
||||
|
b.ToTable("AbpTenants", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => |
||||
|
{ |
||||
|
b.Property<Guid>("TenantId") |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("Value") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(1024) |
||||
|
.HasColumnType("varchar(1024)"); |
||||
|
|
||||
|
b.HasKey("TenantId", "Name"); |
||||
|
|
||||
|
b.ToTable("AbpTenantConnectionStrings", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplate", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Content") |
||||
|
.HasMaxLength(1048576) |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("Content"); |
||||
|
|
||||
|
b.Property<DateTime>("CreationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("CreationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("CreatorId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("CreatorId"); |
||||
|
|
||||
|
b.Property<string>("Culture") |
||||
|
.HasMaxLength(30) |
||||
|
.HasColumnType("varchar(30)") |
||||
|
.HasColumnName("Culture"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(100) |
||||
|
.HasColumnType("varchar(100)") |
||||
|
.HasColumnName("DisplayName"); |
||||
|
|
||||
|
b.Property<DateTime?>("LastModificationTime") |
||||
|
.HasColumnType("datetime(6)") |
||||
|
.HasColumnName("LastModificationTime"); |
||||
|
|
||||
|
b.Property<Guid?>("LastModifierId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("LastModifierId"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(100) |
||||
|
.HasColumnType("varchar(100)") |
||||
|
.HasColumnName("Name"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("TenantId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "Name") |
||||
|
.HasDatabaseName("IX_Tenant_Text_Template_Name"); |
||||
|
|
||||
|
b.ToTable("AbpTextTemplates", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplateDefinition", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("ConcurrencyStamp") |
||||
|
.IsConcurrencyToken() |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(40) |
||||
|
.HasColumnType("varchar(40)") |
||||
|
.HasColumnName("ConcurrencyStamp"); |
||||
|
|
||||
|
b.Property<string>("DefaultCultureName") |
||||
|
.HasMaxLength(30) |
||||
|
.HasColumnType("varchar(30)") |
||||
|
.HasColumnName("DefaultCultureName"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(512) |
||||
|
.HasColumnType("varchar(512)") |
||||
|
.HasColumnName("DisplayName"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.IsRequired() |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsInlineLocalized") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsLayout") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsStatic") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<string>("Layout") |
||||
|
.HasMaxLength(60) |
||||
|
.HasColumnType("varchar(60)") |
||||
|
.HasColumnName("Layout"); |
||||
|
|
||||
|
b.Property<string>("LocalizationResourceName") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)") |
||||
|
.HasColumnName("LocalizationResourceName"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)") |
||||
|
.HasColumnName("Name"); |
||||
|
|
||||
|
b.Property<string>("RenderEngine") |
||||
|
.HasMaxLength(30) |
||||
|
.HasColumnType("varchar(30)") |
||||
|
.HasColumnName("RenderEngine"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.ToTable("AbpTextTemplateDefinitions", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("AllowedProviders") |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("DefaultValue") |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("Description") |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("GroupName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<bool>("IsAvailableToHost") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsVisibleToClients") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ParentName") |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ValueType") |
||||
|
.HasMaxLength(2048) |
||||
|
.HasColumnType("varchar(2048)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("GroupName"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpFeatures", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpFeatureGroups", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ProviderKey") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("ProviderName") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("Value") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name", "ProviderName", "ProviderKey") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpFeatureValues", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("GroupName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<bool>("IsEnabled") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<byte>("MultiTenancySide") |
||||
|
.HasColumnType("tinyint unsigned"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ParentName") |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("Providers") |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("StateCheckers") |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("GroupName"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpPermissions", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ProviderKey") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("ProviderName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<Guid?>("TenantId") |
||||
|
.HasColumnType("char(36)") |
||||
|
.HasColumnName("TenantId"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpPermissionGrants", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpPermissionGroups", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("ProviderKey") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("ProviderName") |
||||
|
.HasMaxLength(64) |
||||
|
.HasColumnType("varchar(64)"); |
||||
|
|
||||
|
b.Property<string>("Value") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(2048) |
||||
|
.HasColumnType("varchar(2048)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name", "ProviderName", "ProviderKey") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpSettings", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("Volo.Abp.SettingManagement.SettingDefinitionRecord", b => |
||||
|
{ |
||||
|
b.Property<Guid>("Id") |
||||
|
.ValueGeneratedOnAdd() |
||||
|
.HasColumnType("char(36)"); |
||||
|
|
||||
|
b.Property<string>("DefaultValue") |
||||
|
.HasMaxLength(2048) |
||||
|
.HasColumnType("varchar(2048)"); |
||||
|
|
||||
|
b.Property<string>("Description") |
||||
|
.HasMaxLength(512) |
||||
|
.HasColumnType("varchar(512)"); |
||||
|
|
||||
|
b.Property<string>("DisplayName") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(256) |
||||
|
.HasColumnType("varchar(256)"); |
||||
|
|
||||
|
b.Property<string>("ExtraProperties") |
||||
|
.HasColumnType("longtext") |
||||
|
.HasColumnName("ExtraProperties"); |
||||
|
|
||||
|
b.Property<bool>("IsEncrypted") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsInherited") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<bool>("IsVisibleToClients") |
||||
|
.HasColumnType("tinyint(1)"); |
||||
|
|
||||
|
b.Property<string>("Name") |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(128) |
||||
|
.HasColumnType("varchar(128)"); |
||||
|
|
||||
|
b.Property<string>("Providers") |
||||
|
.HasMaxLength(1024) |
||||
|
.HasColumnType("varchar(1024)"); |
||||
|
|
||||
|
b.HasKey("Id"); |
||||
|
|
||||
|
b.HasIndex("Name") |
||||
|
.IsUnique(); |
||||
|
|
||||
|
b.ToTable("AbpSettingDefinitions", (string)null); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityPropertyInfo", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "TypeInfo") |
||||
|
.WithMany("Properties") |
||||
|
.HasForeignKey("TypeInfoId") |
||||
|
.OnDelete(DeleteBehavior.Cascade) |
||||
|
.IsRequired(); |
||||
|
|
||||
|
b.Navigation("TypeInfo"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.OrganizationUnitEntityRule", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo") |
||||
|
.WithMany() |
||||
|
.HasForeignKey("EntityTypeId") |
||||
|
.OnDelete(DeleteBehavior.Cascade) |
||||
|
.IsRequired(); |
||||
|
|
||||
|
b.Navigation("EntityTypeInfo"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.RoleEntityRule", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", "EntityTypeInfo") |
||||
|
.WithMany() |
||||
|
.HasForeignKey("EntityTypeId") |
||||
|
.OnDelete(DeleteBehavior.Cascade) |
||||
|
.IsRequired(); |
||||
|
|
||||
|
b.Navigation("EntityTypeInfo"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.Saas.Editions.Edition", "Edition") |
||||
|
.WithMany() |
||||
|
.HasForeignKey("EditionId"); |
||||
|
|
||||
|
b.Navigation("Edition"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => |
||||
|
{ |
||||
|
b.HasOne("LINGYUN.Abp.Saas.Tenants.Tenant", null) |
||||
|
.WithMany("ConnectionStrings") |
||||
|
.HasForeignKey("TenantId") |
||||
|
.OnDelete(DeleteBehavior.Cascade) |
||||
|
.IsRequired(); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.DataProtectionManagement.EntityTypeInfo", b => |
||||
|
{ |
||||
|
b.Navigation("Properties"); |
||||
|
}); |
||||
|
|
||||
|
modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => |
||||
|
{ |
||||
|
b.Navigation("ConnectionStrings"); |
||||
|
}); |
||||
|
#pragma warning restore 612, 618
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
#nullable disable |
||||
|
|
||||
|
namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public partial class AddAllowProperties : Migration |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.AddColumn<string>( |
||||
|
name: "AllowProperties", |
||||
|
table: "AbpAuthRoleEntityRules", |
||||
|
type: "varchar(512)", |
||||
|
maxLength: 512, |
||||
|
nullable: true) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
|
||||
|
migrationBuilder.AddColumn<string>( |
||||
|
name: "AllowProperties", |
||||
|
table: "AbpAuthOrganizationUnitEntityRules", |
||||
|
type: "varchar(512)", |
||||
|
maxLength: 512, |
||||
|
nullable: true) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "AllowProperties", |
||||
|
table: "AbpAuthRoleEntityRules"); |
||||
|
|
||||
|
migrationBuilder.DropColumn( |
||||
|
name: "AllowProperties", |
||||
|
table: "AbpAuthOrganizationUnitEntityRules"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Authorization.Abstractions" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.DataProtectionManagement.Domain.Shared\LINGYUN.Abp.DataProtectionManagement.Domain.Shared.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.Application; |
||||
|
using Volo.Abp.Authorization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.DataProtectionManagement; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpAuthorizationAbstractionsModule), |
||||
|
typeof(AbpDddApplicationContractsModule), |
||||
|
typeof(AbpDataProtectionManagementDomainSharedModule))] |
||||
|
public class AbpDataProtectionManagementApplicationContractsModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue