committed by
GitHub
233 changed files with 7993 additions and 1195 deletions
@ -1,6 +1,16 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<packageSources> |
|||
<clear /> |
|||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> |
|||
<add key="local" value="./aspnet-core/LocalNuget" /> |
|||
</packageSources> |
|||
<packageSourceMapping> |
|||
<packageSource key="nuget.org"> |
|||
<package pattern="*" /> |
|||
</packageSource> |
|||
<packageSource key="local"> |
|||
<package pattern="LINGYUN.*" /> |
|||
</packageSource> |
|||
</packageSourceMapping> |
|||
</configuration> |
|||
@ -1,7 +1,6 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<configuration> |
|||
<packageSources> |
|||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> |
|||
<!--<add key="LocalNuget" value="./LocalNuget" />--> |
|||
</packageSources> |
|||
<packageSources> |
|||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" /> |
|||
</packageSources> |
|||
</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.ChangeTracking; |
|||
using System; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Linq.Expressions; |
|||
using System.Reflection; |
|||
using Volo.Abp.Domain.Entities; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Uow; |
|||
using Volo.Abp.Users; |
|||
|
|||
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())); |
|||
} |
|||
} |
|||
} |
|||
namespace LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
|||
|
|||
protected virtual DataAccessRuleInfo AccessRuleInfo => UnitOfWorkManager.Current.GetAccessRuleInfo(); |
|||
|
|||
protected override void HandlePropertiesBeforeSave() |
|||
{ |
|||
foreach (var item in ChangeTracker.Entries().ToList()) |
|||
{ |
|||
HandleExtraPropertiesOnSave(item); |
|||
HandleCheckPropertiesOnSave(item); |
|||
if (item.State.IsIn(EntityState.Modified, EntityState.Deleted)) |
|||
{ |
|||
UpdateConcurrencyStamp(item); |
|||
} |
|||
} |
|||
} |
|||
public abstract class AbpDataProtectionDbContext<TDbContext> : AbpDbContext<TDbContext> |
|||
where TDbContext : DbContext |
|||
{ |
|||
public IOptions<AbpDataProtectionOptions> DataProtectionOptions => LazyServiceProvider.LazyGetRequiredService<IOptions<AbpDataProtectionOptions>>(); |
|||
public ICurrentUser CurrentUser => LazyServiceProvider.LazyGetRequiredService<ICurrentUser>(); |
|||
|
|||
protected virtual void HandleCheckPropertiesOnSave(EntityEntry entry) |
|||
{ |
|||
// 仅当启用过滤器时检查
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
public AbpDataProtectionDbContext( |
|||
DbContextOptions<TDbContext> options) : base(options) |
|||
{ |
|||
} |
|||
|
|||
protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>() |
|||
{ |
|||
var expression = base.CreateFilterExpression<TEntity>(); |
|||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) |
|||
{ |
|||
base.OnConfiguring(optionsBuilder); |
|||
|
|||
if (typeof(IHasDataAccess).IsAssignableFrom(typeof(TEntity))) |
|||
{ |
|||
Expression<Func<TEntity, bool>> expression2 = (TEntity e) => !IsDataAccessFilterEnabled || CreateFilterExpression(e, AccessRuleInfo); |
|||
expression = (Expression<Func<TEntity, bool>>)((expression == null) ? ((LambdaExpression)expression2) : ((LambdaExpression)QueryFilterExpressionHelper.CombineExpressions(expression, expression2))); |
|||
} |
|||
// TODO: 需要优化表达式树
|
|||
// optionsBuilder.AddInterceptors(LazyServiceProvider.GetRequiredService<AbpDataProtectedReadEntityInterceptor>());
|
|||
//optionsBuilder.AddInterceptors(LazyServiceProvider.GetRequiredService<AbpDataProtectedWriteEntityInterceptor>());
|
|||
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 (!accessRuleInfo.Rules.Any(r => r.EntityTypeFullName == typeof(TEntity).FullName)) |
|||
if (data.GetProperty(DataAccessKeywords.AUTH_ORGS) == null) |
|||
{ |
|||
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.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; |
|||
|
|||
namespace LINGYUN.Abp.DataProtection; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpDataProtectionAbstractionsModule), |
|||
typeof(AbpDddDomainModule))] |
|||
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"); |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue