Procházet zdrojové kódy

数据权限调整:通过Attribute标记数权属性

yorkove před 1 rokem
rodič
revize
511005ea95

+ 17 - 0
Admin.NET/Admin.NET.Core/Attribute/OwnerOrgAttribute.cs

@@ -0,0 +1,17 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+
+namespace Admin.NET.Core;
+
+/// <summary>
+/// 所属机构数据权限
+/// </summary>
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
+public class OwnerOrgAttribute:Attribute
+{
+}

+ 16 - 0
Admin.NET/Admin.NET.Core/Attribute/OwnerUserAttribute.cs

@@ -0,0 +1,16 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+/// <summary>
+/// 所属用户数据权限
+/// </summary>
+[SuppressSniffer]
+[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
+public class OwnerUserAttribute:Attribute
+{
+}

+ 6 - 4
Admin.NET/Admin.NET.Core/Entity/EntityBase.cs

@@ -39,8 +39,9 @@ public abstract class EntityBase : EntityBaseId, IDeletedFilter
     /// <summary>
     /// 创建者Id
     /// </summary>
+    [OwnerUser]
     [SugarColumn(ColumnDescription = "创建者Id", IsOnlyIgnoreUpdate = true)]
-    public virtual long? CreateUserId { get; set; }
+    public virtual long CreateUserId { get; set; }
 
     ///// <summary>
     ///// 创建者
@@ -54,7 +55,7 @@ public abstract class EntityBase : EntityBaseId, IDeletedFilter
     /// 创建者姓名
     /// </summary>
     [SugarColumn(ColumnDescription = "创建者姓名", Length = 64, IsOnlyIgnoreUpdate = true)]
-    public virtual string? CreateUserName { get; set; }
+    public virtual string CreateUserName { get; set; }
 
     /// <summary>
     /// 修改者Id
@@ -91,8 +92,9 @@ public abstract class EntityBaseData : EntityBase, IOrgIdFilter
     /// <summary>
     /// 创建者部门Id
     /// </summary>
+    [OwnerOrg]
     [SugarColumn(ColumnDescription = "创建者部门Id", IsOnlyIgnoreUpdate = true)]
-    public virtual long? CreateOrgId { get; set; }
+    public virtual long CreateOrgId { get; set; }
 
     /// <summary>
     /// 创建者部门
@@ -106,7 +108,7 @@ public abstract class EntityBaseData : EntityBase, IOrgIdFilter
     /// 创建者部门名称
     /// </summary>
     [SugarColumn(ColumnDescription = "创建者部门名称", Length = 64, IsOnlyIgnoreUpdate = true)]
-    public virtual string? CreateOrgName { get; set; }
+    public virtual string CreateOrgName { get; set; }
 }
 
 /// <summary>

+ 1 - 1
Admin.NET/Admin.NET.Core/Entity/IEntityFilter.cs

@@ -36,5 +36,5 @@ internal interface IOrgIdFilter
     /// <summary>
     /// 创建者部门Id
     /// </summary>
-    long? CreateOrgId { get; set; }
+    long CreateOrgId { get; set; }
 }

+ 122 - 0
Admin.NET/Admin.NET.Core/Extension/TypeExtension.cs

@@ -0,0 +1,122 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+/// <summary>
+/// Type 扩展
+/// </summary>
+public  static class TypeExtension
+{
+    /// <summary>
+    /// 根据指定Attribute获取属性
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="type"></param>
+    /// <returns></returns>
+    public static List<string> GetPropertyNames<T>(this Type type)
+        where T : Attribute
+    {
+        var allProperties = type.GetProperties();
+
+        var properties = allProperties.Where(x => x.CustomAttributes.Any(a => a.AttributeType == typeof(T)));
+
+        return properties.Select(x => x.Name).ToList() ;
+    }
+
+    /// <summary>
+    /// 获取查询表达式
+    /// </summary>
+    /// <param name="type"></param>
+    /// <param name="options"></param>
+    /// <param name="fieldName"></param>
+    /// <returns></returns>
+    public static LambdaExpression GetConditionExpression<T>(this Type type, List<T> options, string fieldName)
+    {
+        ParameterExpression parameter = Expression.Parameter(type, "c");
+        Expression right = Expression.Constant(false);
+        options.ForEach(option =>
+        {
+            Expression left = Expression.Equal(
+                 Expression.Property(parameter, type.GetProperty(fieldName)),
+                 Expression.Constant(option)
+            );
+            right = Expression.Or(left, right);
+        });
+        var finalExpression = Expression.Lambda(right, new ParameterExpression[] { parameter });
+        return finalExpression;
+    }
+
+    /// <summary>
+    /// 获取查询表达式
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="type"></param>
+    /// <param name="option"></param>
+    /// <param name="fieldName"></param>
+    /// <returns></returns>
+    public static LambdaExpression GetConditionExpression<T>(this Type type, T option, string fieldName)
+    {
+        ParameterExpression parameter = Expression.Parameter(type, "c");
+        Expression expression = Expression.Equal(
+                 Expression.Property(parameter, type.GetProperty(fieldName)),
+                 Expression.Constant(option)
+        );
+        var finalExpression = Expression.Lambda(expression, new ParameterExpression[] { parameter });
+        return finalExpression;
+    }
+
+    /// <summary>
+    /// 获取查询表达式
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="type"></param>
+    /// <param name="options"></param>
+    /// <param name="fieldNames"></param>
+    /// <returns></returns>
+    public static LambdaExpression GetConditionExpression<T>(this Type type,List<T> options,List<string> fieldNames)
+    {
+        ParameterExpression parameter = Expression.Parameter(type, "c");
+        Expression right = Expression.Constant(false);
+        fieldNames.ForEach(filedName =>
+        {
+            options.ForEach(option =>
+            {
+                Expression left = Expression.Equal(
+                     Expression.Property(parameter, type.GetProperty(filedName)),
+                     Expression.Constant(option)
+                );
+                right = Expression.Or(left, right);
+            });
+        });
+        var finalExpression = Expression.Lambda(right, new ParameterExpression[] { parameter });
+        return finalExpression;
+    }
+
+    /// <summary>
+    /// 获取查询表达式
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="type"></param>
+    /// <param name="option"></param>
+    /// <param name="fieldNames"></param>
+    /// <returns></returns>
+    public static LambdaExpression GetConditionExpression<T>(this Type type,T option,List<string> fieldNames)
+    {
+        ParameterExpression parameter = Expression.Parameter(type, "c");
+        Expression right = Expression.Constant(false);
+        fieldNames.ForEach(filedName =>
+        {
+            Expression left = Expression.Equal(
+                 Expression.Property(parameter, type.GetProperty(filedName)),
+                 Expression.Constant(option)
+            );
+            right = Expression.Or(left, right);
+        });
+        var finalExpression = Expression.Lambda(right, new ParameterExpression[] { parameter });
+        return finalExpression;
+    }
+}

+ 21 - 13
Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs

@@ -53,23 +53,27 @@ public static class SqlSugarFilter
                 var services = scope.ServiceProvider;
                 orgIds = services.GetService<SysOrgService>().GetUserOrgIdList().GetAwaiter().GetResult();
             });
-            if (orgIds == null || orgIds.Count == 0) return;
+            if (orgIds.IsNullOrEmpty()) return;
 
             // 获取业务实体数据表
             var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
                 && u.IsSubclassOf(typeof(EntityBaseData)));
-            if (!entityTypes.Any()) return;
-
+            if (!entityTypes.Any()) return;
+
+            List<string> properties;
             orgFilter = new ConcurrentDictionary<Type, LambdaExpression>();
             foreach (var entityType in entityTypes)
             {
                 // 排除非当前数据库实体
                 var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
                 if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString()))
-                    continue;
-
-                var lambda = DynamicExpressionParser.ParseLambda(new[] {
-                    Expression.Parameter(entityType, "u") }, typeof(bool), $"@0.Contains(u.{nameof(EntityBaseData.CreateOrgId)}??{default(long)})", orgIds);
+                    continue;
+
+                properties = entityType.GetPropertyNames<OwnerOrgAttribute>();
+                if (properties.IsNullOrEmpty()) continue;
+
+                var lambda = entityType.GetConditionExpression(orgIds, properties);
+
                 db.QueryFilter.AddTableFilter(entityType, lambda);
                 orgFilter.TryAdd(entityType, lambda);
             }
@@ -104,18 +108,22 @@ public static class SqlSugarFilter
             // 获取业务实体数据表
             var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
                 && u.IsSubclassOf(typeof(EntityBaseData)));
-            if (!entityTypes.Any()) return maxDataScope;
-
+            if (!entityTypes.Any()) return maxDataScope;
+
+            List<string> properties;
             dataScopeFilter = new ConcurrentDictionary<Type, LambdaExpression>();
             foreach (var entityType in entityTypes)
             {
                 // 排除非当前数据库实体
                 var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
                 if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString()))
-                    continue;
-
-                var lambda = DynamicExpressionParser.ParseLambda(new[] {
-                    Expression.Parameter(entityType, "u") }, typeof(bool), $"u.{nameof(EntityBaseData.CreateUserId)}=@0", userId);
+                    continue;
+
+                properties = entityType.GetPropertyNames<OwnerUserAttribute>();
+                if (properties.IsNullOrEmpty()) continue;
+
+                var lambda = entityType.GetConditionExpression(userId, properties);
+
                 db.QueryFilter.AddTableFilter(entityType, lambda);
                 dataScopeFilter.TryAdd(entityType, lambda);
             }