Initial_commit_SecMPS_v2
This commit is contained in:
74
api_sqlsugar/VolPro.Core/Tenancy/TenancyDefault.cs
Normal file
74
api_sqlsugar/VolPro.Core/Tenancy/TenancyDefault.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.Configuration;
|
||||
using VolPro.Core.Extensions;
|
||||
using VolPro.Core.ManageUser;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using static Dapper.SqlMapper;
|
||||
|
||||
namespace VolPro.Core.Tenancy
|
||||
{
|
||||
|
||||
public static class TenancyDefault
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户不分库时设置表的租户字段值
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
public static T SetTenancyValue<T>(this T entity) where T : class
|
||||
{
|
||||
PropertyInfo property = GetTenancyProperty<T>();
|
||||
if (property != null)
|
||||
{
|
||||
property.SetValue(entity, UserContext.CurrentServiceId.ToString());
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static List<T> SetTenancyValue<T>(this List<T> list) where T : class
|
||||
{
|
||||
PropertyInfo property = GetTenancyProperty<T>();
|
||||
if (property != null)
|
||||
{
|
||||
var tenancyId = UserContext.CurrentServiceId.ToString();
|
||||
foreach (var entity in list)
|
||||
{
|
||||
property.SetValue(entity, tenancyId);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/// <summary>
|
||||
/// 租户不分库时统一过滤当前租户表的数据
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
public static ISugarQueryable<T> FilterTenancy<T>(this ISugarQueryable<T> query) where T : class
|
||||
{
|
||||
PropertyInfo property = GetTenancyProperty<T>();
|
||||
if (property != null)
|
||||
{
|
||||
var where = property.Name.CreateExpression<T>(UserContext.CurrentServiceId.ToString(), Enums.LinqExpressionType.Equal);
|
||||
return query.Where(where);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
private static PropertyInfo GetTenancyProperty<T>()
|
||||
{
|
||||
if (AppSetting.TenancyField == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return typeof(T).GetProperty(AppSetting.TenancyField);
|
||||
}
|
||||
}
|
||||
}
|
||||
339
api_sqlsugar/VolPro.Core/Tenancy/TenancyExpression.cs
Normal file
339
api_sqlsugar/VolPro.Core/Tenancy/TenancyExpression.cs
Normal file
@@ -0,0 +1,339 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using VolPro.Core.Configuration;
|
||||
using VolPro.Core.Const;
|
||||
using VolPro.Core.DBManager;
|
||||
using VolPro.Core.Enums;
|
||||
using VolPro.Core.Extensions;
|
||||
using VolPro.Core.ManageUser;
|
||||
using VolPro.Core.UserManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
using VolPro.Entity.SystemModels;
|
||||
|
||||
namespace VolPro.Core.Tenancy
|
||||
{
|
||||
public static class TenancyExpression
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取数据权限sql
|
||||
/// 调用方式:DBServerProvider.DbContext.Set<表>().CreateTenancyFilterSql();
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
public static string CreateTenancyFilterSql<T>(this ISugarQueryable<T> query) where T : class
|
||||
{
|
||||
return query.CreateTenancyFilter<T>().ToSqlString();
|
||||
}
|
||||
/// <summary>
|
||||
/// 注意:数据库表中必须包括appsettings.json配置文件UserIdField的字段才会进行数据隔离。如果表没有这些字段,请在上面单独写过滤逻辑
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
public static ISugarQueryable<T> CreateTenancyFilter<T>(this ISugarQueryable<T> query)
|
||||
{
|
||||
//2023.12.10实现租户字段过滤
|
||||
//if (AppSetting.TenancyField != null
|
||||
// && typeof(T).GetProperty(AppSetting.TenancyField) != null
|
||||
// && !string.IsNullOrEmpty(UserContext.Current.UserInfo.TenancyValue))
|
||||
//{
|
||||
// query = query.Where(AppSetting.TenancyField.CreateExpression<T>(UserContext.Current.UserInfo.TenancyValue, LinqExpressionType.Equal));
|
||||
//}
|
||||
|
||||
//是否用户表
|
||||
bool isUserTable = typeof(T) == typeof(Sys_User);
|
||||
|
||||
//默认通过创建人id过滤数据
|
||||
string filterCreateId = null;
|
||||
//用户表通过user_id过滤数据
|
||||
if (isUserTable)
|
||||
{
|
||||
filterCreateId = "User_Id";
|
||||
}
|
||||
else
|
||||
{
|
||||
//获取表的创建人id字段,在配置appsettings文件中UserIdField值
|
||||
var properties = typeof(T).GetProperties();
|
||||
//使用创建人id过滤数据
|
||||
filterCreateId = properties.Where(x => x.Name == AppSetting.CreateMember.UserIdField).FirstOrDefault()?.Name;
|
||||
if (filterCreateId == null)
|
||||
{
|
||||
filterCreateId = properties.Where(x => x.Name == "CreateId").FirstOrDefault()?.Name;
|
||||
}
|
||||
}
|
||||
|
||||
string tableName = typeof(T).Name;
|
||||
//使用用户数据权限(用户管理界面配置的指定看到某些用户创建的数据库)
|
||||
if (AppSetting.UserAuth)
|
||||
{
|
||||
int[] userIds = UserContext.Current.GetCurrentUserAuthUserIds(tableName);
|
||||
//设置查看指定用户的数据
|
||||
if (userIds != null && userIds.Length > 0)
|
||||
{
|
||||
//没有配置创建人id的表不执行数据权限过滤
|
||||
if (filterCreateId == null)
|
||||
{
|
||||
return query;
|
||||
}
|
||||
return query.Where(filterCreateId.CreateExpression<T>(userIds, LinqExpressionType.In));
|
||||
}
|
||||
}
|
||||
var roleIds = UserContext.Current.RoleIds;
|
||||
//2024.08.11增加菜单数据权限(优先级高级角色数据权限)
|
||||
//2024.08.11增加菜单数据权限(优先级高级角色数据权限)
|
||||
List<int> authDataTypes = null;
|
||||
string authMenuData = null;
|
||||
var permission = UserContext.Current.GetPermissions(tableName.ToLower())??new Permissions() { };
|
||||
//自定义数据权限
|
||||
if (permission.CustomAuth != null)
|
||||
{
|
||||
return QueryCustom(query, permission.CustomAuth);
|
||||
}
|
||||
//没有配置创建人id的表不执行数据权限过滤
|
||||
if (filterCreateId == null)
|
||||
{
|
||||
return query;
|
||||
}
|
||||
authMenuData = permission.AuthMenuData;
|
||||
// string authMenuData = UserContext.Current.GetPermissions(tableName.ToLower())?.AuthMenuData;
|
||||
if (!string.IsNullOrEmpty(authMenuData))
|
||||
{
|
||||
authDataTypes = new List<int>() { authMenuData.GetInt() };
|
||||
}
|
||||
else
|
||||
{
|
||||
authDataTypes = RoleContext.GetRoles(x => roleIds.Contains(x.Id))
|
||||
.Where(x => x.AuthData > 0)
|
||||
.Select(s => s.AuthData).ToList();
|
||||
}
|
||||
|
||||
if (!isUserTable)
|
||||
{
|
||||
if (authDataTypes.Count == 0)
|
||||
{
|
||||
return query;
|
||||
}
|
||||
}
|
||||
//!!不要给超级管理员设置部门,否则可能会被组织权限共享显示出来
|
||||
if (!isUserTable && (authDataTypes.Contains((int)AuthData.本组织及下数据) || authDataTypes.Contains((int)AuthData.本组织数据)))
|
||||
{
|
||||
var deptIds = UserContext.Current.DeptIds;
|
||||
var userDeptQuery = DBServerProvider.DbContext.Set<Sys_UserDepartment>().Where(x => x.Enable == 1);
|
||||
if (authDataTypes.Contains((int)AuthData.本组织及下数据))
|
||||
{
|
||||
deptIds = DepartmentContext.GetAllChildrenIds(deptIds);
|
||||
}
|
||||
|
||||
//分库
|
||||
if (CheckDb<T>())
|
||||
{
|
||||
userDeptQuery = userDeptQuery.Where(x => deptIds.Contains(x.DepartmentId));
|
||||
var userIds = userDeptQuery.Select(s => s.UserId).Distinct();
|
||||
query = query.QueryTenancyDynamicShareDBFilter<T>(filterCreateId, userIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.QueryTenancyFilter<T, Sys_UserDepartment>(filterCreateId, "UserId", deptIds: deptIds);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
//如果角色没有配置数据权限,当前页面是isUserTable=true用户表时,默认显示当前角色下的数据
|
||||
if (isUserTable || authDataTypes.Contains((int)AuthData.本角色以及下数据) || authDataTypes.Contains((int)AuthData.本角色数据))
|
||||
{
|
||||
var userRoleQuery = DBServerProvider.DbContext.Set<Sys_UserRole>().Where(x => x.Enable == 1 && x.RoleId > 1);
|
||||
if (isUserTable || authDataTypes.Contains((int)AuthData.本角色以及下数据))
|
||||
{
|
||||
//获取所有子角色
|
||||
roleIds = RoleContext.GetAllChildrenIds(roleIds).ToArray();
|
||||
|
||||
}
|
||||
//分库
|
||||
if (CheckDb<T>())
|
||||
{
|
||||
userRoleQuery = userRoleQuery.Where(x => roleIds.Contains(x.RoleId));
|
||||
var userIds = userRoleQuery.Select(s => s.UserId).Distinct();
|
||||
query = query.QueryTenancyDynamicShareDBFilter<T>(filterCreateId, userIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.QueryTenancyFilter<T, Sys_UserRole>(filterCreateId, "UserId", roleIds);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
if (authDataTypes.Contains((int)AuthData.仅自己数据))
|
||||
{
|
||||
return query.Where(filterCreateId.CreateExpression<T>(UserContext.Current.UserId, LinqExpressionType.Equal));
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
private static bool CheckDb<T>()
|
||||
{
|
||||
//是否使用分库
|
||||
return AppSetting.UseDynamicShareDB || typeof(T).BaseType.Name != typeof(SysEntity).Name;
|
||||
}
|
||||
private static ISugarQueryable<T1> QueryTenancyDynamicShareDBFilter<T1>(this ISugarQueryable<T1> query, string createIdField, ISugarQueryable<int> userIds)
|
||||
{
|
||||
return query.Where(createIdField.CreateExpression<T1>(userIds.Take(5000).ToArray(), LinqExpressionType.In));
|
||||
}
|
||||
|
||||
private static bool isPgSql = DBType.Name == DbCurrentType.PgSql.ToString() || DBType.Name == DbCurrentType.Kdbndp.ToString();
|
||||
private static ISugarQueryable<T1> QueryTenancyFilter<T1, T2>(this ISugarQueryable<T1> query, string createIdField,
|
||||
string userIdField, int[] roleIds = null, List<Guid> deptIds = null) where T2 : class, new()
|
||||
{
|
||||
|
||||
if (isPgSql)
|
||||
{
|
||||
createIdField = "it.\"" + createIdField + "\"";
|
||||
userIdField = "s.\"" + userIdField + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
createIdField = "it." + createIdField;
|
||||
userIdField = "s." + userIdField;
|
||||
}
|
||||
|
||||
|
||||
if (typeof(T2) == typeof(Sys_UserDepartment))
|
||||
{
|
||||
query = query.Where(it => SqlSugar.SqlFunc.Subqueryable<Sys_UserDepartment>()
|
||||
.Where(s => s.Enable == 1 && deptIds.Contains(s.DepartmentId) && SqlFunc.MappingColumn<string>(createIdField) == SqlFunc.MappingColumn<string>(userIdField)).Any());
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.Where(it => SqlSugar.SqlFunc.Subqueryable<Sys_UserRole>()
|
||||
.Where(s => s.Enable == 1 && roleIds.Contains(s.RoleId) && SqlFunc.MappingColumn<string>(createIdField) == SqlFunc.MappingColumn<string>(userIdField)).Any());
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 自定义数据权限
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
private static ISugarQueryable<T> QueryCustom<T>(this ISugarQueryable<T> query, List<Dictionary<string, string>> list)
|
||||
{
|
||||
var properties = typeof(T).GetProperties();
|
||||
//Expression<Func<T, bool>> orFilter = null;
|
||||
Expression<Func<T, bool>> expression = x => true;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (item.TryGetValue("field", out string field))
|
||||
{
|
||||
if (string.IsNullOrEmpty(field))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!properties.Any(x => x.Name == field))
|
||||
{
|
||||
Console.WriteLine($"表【{typeof(T).GetEntityTableName(false)}】不存在字段【{field}】");
|
||||
continue;
|
||||
}
|
||||
if (item.TryGetValue("value", out string value))
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
value = value.Trim();
|
||||
item.TryGetValue("filterType", out string filterType);
|
||||
LinqExpressionType type = LinqExpressionType.Equal;
|
||||
switch (filterType)
|
||||
{
|
||||
case "!=":
|
||||
type = LinqExpressionType.NotEqual;
|
||||
break;
|
||||
case ">":
|
||||
type = LinqExpressionType.GreaterThan;
|
||||
break;
|
||||
case ">=":
|
||||
type = LinqExpressionType.ThanOrEqual;
|
||||
break;
|
||||
case "小于":
|
||||
case "<":
|
||||
type = LinqExpressionType.LessThan;
|
||||
break;
|
||||
case "<=":
|
||||
type = LinqExpressionType.LessThanOrEqual;
|
||||
break;
|
||||
case "in":
|
||||
type = LinqExpressionType.In;
|
||||
break;
|
||||
case "like":
|
||||
type = LinqExpressionType.Like;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// //值的类型,0自定义,1当前用户,2当前角色,3当前部门
|
||||
item.TryGetValue("valueType", out string valueType);
|
||||
if (!string.IsNullOrEmpty(valueType) && valueType == "1")
|
||||
{
|
||||
|
||||
switch (value)
|
||||
{
|
||||
//1当前用户
|
||||
case "User_Id":
|
||||
object userVal = UserContext.Current.UserId.ChangeType(properties.Where(x => x.Name == field).FirstOrDefault().PropertyType);
|
||||
expression = expression.And(field.CreateExpression<T>(userVal, LinqExpressionType.Equal));
|
||||
break;
|
||||
//2当前角色
|
||||
case "RoleIds":
|
||||
expression = expression.And(field.CreateExpression<T>(UserContext.Current.RoleIds, LinqExpressionType.In));
|
||||
break;
|
||||
//3当前部门
|
||||
case "DeptIds":
|
||||
expression = expression.And(field.CreateExpression<T>(UserContext.Current.DeptIds, LinqExpressionType.In));
|
||||
break;
|
||||
;
|
||||
default:
|
||||
//其他自定义字段(UserInfo里面定义的其他字段目前只能是int\string\guid,其他list字段还未支持)
|
||||
var userInfo = UserContext.Current.UserInfo;
|
||||
var property = typeof(UserInfo).GetProperty(value);
|
||||
if (property == null)
|
||||
{
|
||||
Console.WriteLine($"UserInfo未找到字段:{value}");
|
||||
break;
|
||||
}
|
||||
var userInfoVal = property.GetValue(userInfo);
|
||||
if (userInfoVal == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
expression = expression.And(field.CreateExpression<T>(userInfoVal.ChangeType(properties.Where(x => x.Name == field).FirstOrDefault().PropertyType), type));
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (type == LinqExpressionType.In || type == LinqExpressionType.NotEqual || value.Contains(','))
|
||||
{
|
||||
if (type != LinqExpressionType.In)
|
||||
{
|
||||
type = LinqExpressionType.NotIn;
|
||||
}
|
||||
var values = value.Split(",").Where(s => s != "").Select(s => s.Trim());
|
||||
if (values.Count() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
expression = expression.And(field.CreateExpression<T>(values, type));
|
||||
continue;
|
||||
}
|
||||
expression = expression.And(field.CreateExpression<T>(value.ChangeType(properties.Where(x => x.Name == field).FirstOrDefault().PropertyType), type));
|
||||
}
|
||||
return query.Where(expression);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
116
api_sqlsugar/VolPro.Core/Tenancy/TenancyManager.cs
Normal file
116
api_sqlsugar/VolPro.Core/Tenancy/TenancyManager.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using VolPro.Core.Const;
|
||||
using VolPro.Core.DBManager;
|
||||
using VolPro.Core.Enums;
|
||||
using VolPro.Core.ManageUser;
|
||||
using VolPro.Core.UserManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace VolPro.Core.Tenancy
|
||||
{
|
||||
public static class TenancyManager<T> where T : class
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据隔离操作(2023.08.16优化增加了queryable参数可以写EF查询,及增加了返回参数)
|
||||
/// 注意(必看):数据库表字段必须包括appsettings.json配置文件中的CreateMember->UserIdField创建人id字段才会进行数据隔离。
|
||||
/// 如果表没有这些字段,请在下面 switch (tableName)单独写过滤逻辑
|
||||
/// </summary>
|
||||
/// <param name="tableName">数据库表名</param>
|
||||
/// <returns></returns>
|
||||
public static (string sql, ISugarQueryable<T> query) GetSearchQueryable(string multiTenancyString, string tableName, ISugarQueryable<T> queryable)
|
||||
{
|
||||
|
||||
//超级管理员不限制(这里可以根据tableName表名自己判断要不要限制超级管理员)
|
||||
if (UserContext.Current.IsSuperAdmin)
|
||||
{
|
||||
return (multiTenancyString, queryable);
|
||||
}
|
||||
|
||||
switch (tableName)
|
||||
{
|
||||
//例如:指定用户表指定查询条件
|
||||
//case nameof(Sys_User):
|
||||
// break;
|
||||
case nameof(Sys_Role):
|
||||
break;
|
||||
case nameof(Sys_Group):
|
||||
break;
|
||||
case nameof(Sys_Department):
|
||||
// case nameof(Demo_Order):
|
||||
////例:订单管理只看自己角色及子角色对应用户创建的数据
|
||||
////注:下面的Sys_UserRole表存的是每个角色对应有哪些用户,Sys_UserRole不包括超级管理员RoleId=1的用户
|
||||
|
||||
/*************************方式一:用EF查询***********************************/
|
||||
////1、 获取当前登录帐的角色及子角色
|
||||
//var roleIds = RoleContext.GetAllChildrenIds(UserContext.Current.RoleIds);
|
||||
////2、查询这些角色对应的用户
|
||||
//var userIdsQuery = DBServerProvider.DbContext.Set<Sys_UserRole>().Where(x => roleIds.Contains(x.RoleId) && x.Enable == 1).Select(s => s.UserId);
|
||||
|
||||
////上面1、2的操作可以简化, RoleContext.GetCurrentAllChildUser()已经封装了获取当前登录帐号角色下的所有用户id方法
|
||||
////userIdsQuery = RoleContext.GetCurrentAllChildUser();
|
||||
|
||||
////3、进行子查询
|
||||
//queryable = (ISugarQueryable<T>)(queryable as ISugarQueryable<Demo_Order>).Where(c => userIdsQuery.Any(uid => uid == c.CreateID));
|
||||
|
||||
////4、queryable.ToQueryString()可以查看实际生成的sql
|
||||
////Console.WriteLine(queryable.ToQueryString());
|
||||
///
|
||||
|
||||
/*************************方式二:写原生sql查询***********************************/
|
||||
//multiTenancyString = $" select * from {tableName} where CreateID in (select UserId from Sys_UserRole where RoleId in ({string.Join(",", roleIds)}))";
|
||||
|
||||
|
||||
/********注:上面的两种方式,如果熟悉表达式语法,尽量采用第一种方式;也可以采用第二种方式写原生sql,数据过滤的规则由自己定义********/
|
||||
|
||||
//*************************方式三:写原生sql查询,某些表只能查看自己的数据***********************************/
|
||||
// multiTenancyString += $" select * from {tableName} where CreateID='{UserContext.Current.UserId}'";
|
||||
|
||||
|
||||
break;
|
||||
default:
|
||||
//1、其他表默认执行数据隔离,隔离方式与角色管理页面的[数据权限]:
|
||||
//2、注:角色设置数据权限后就会进行数据隔离,如果不需要隔离的数据,见上面switch (tableName)说明
|
||||
//3、隔离方式:本组织(部门)及下数据、本组织(部门)数据、本角色以及下数据、本角色数据、仅自己数据
|
||||
|
||||
|
||||
//统一执行数据隔离
|
||||
// 注意(必看):数据库表字段必须包括appsettings.json配置文件中的CreateMember->UserIdField创建人id字段才会进行数据隔离。
|
||||
// 如果表没有这些字段,请在上面 switch (tableName)单独写过滤逻辑
|
||||
queryable = queryable.CreateTenancyFilter<T>();
|
||||
break;
|
||||
}
|
||||
return (multiTenancyString, queryable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="tableName">数据库表名</param>
|
||||
/// <param name="ids">当前操作的所有id</param>
|
||||
/// <param name="tableKey">主键字段</param>
|
||||
/// <returns></returns>
|
||||
public static string GetMultiTenancySql(string tableName, string ids, string tableKey)
|
||||
{
|
||||
//使用方法同上
|
||||
string multiTenancyString;
|
||||
switch (tableName)
|
||||
{
|
||||
default:
|
||||
multiTenancyString = $"select count(*) FROM {tableName} " +
|
||||
$" where CreateID='{UserContext.Current.UserId}'" +
|
||||
$" and { tableKey} in ({ids}) ";
|
||||
break;
|
||||
}
|
||||
return multiTenancyString;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
273
api_sqlsugar/VolPro.Core/Tenancy/TenancySqlExpression.cs
Normal file
273
api_sqlsugar/VolPro.Core/Tenancy/TenancySqlExpression.cs
Normal file
@@ -0,0 +1,273 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using VolPro.Core.Configuration;
|
||||
using VolPro.Core.DBManager;
|
||||
using VolPro.Core.Enums;
|
||||
using VolPro.Core.Extensions;
|
||||
using VolPro.Core.ManageUser;
|
||||
using VolPro.Core.UserManager;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace VolPro.Core.Tenancy
|
||||
{
|
||||
public static class TenancySqlExpression
|
||||
{
|
||||
/// <summary>
|
||||
/// 注意:数据库表中必须包括appsettings.json配置文件UserIdField的字段才会进行数据隔离。如果表没有这些字段,请在上面单独写过滤逻辑
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="checkAdmin">是否对管理员帐号也做验证</param>
|
||||
/// <returns></returns>
|
||||
public static string CreateTenancySqlFilter(this string tableName, string selectSql,
|
||||
List<SearchParameters> filters, List<SugarParameter> parameters, string leftQuote = "", string rightQuote = "")
|
||||
{
|
||||
filters ??= new List<SearchParameters>();
|
||||
|
||||
// 统一到菜单表名,避免传入真实表名(TableTrueName)时权限匹配失败
|
||||
string permissionTableName = ResolvePermissionTableName(tableName);
|
||||
bool isUserTable = permissionTableName.Equals(nameof(Sys_User), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
string filterCreateId = isUserTable ? "User_Id" : AppSetting.CreateMember?.UserIdField;
|
||||
if (string.IsNullOrWhiteSpace(filterCreateId))
|
||||
{
|
||||
filterCreateId = "CreateId";
|
||||
}
|
||||
|
||||
if (AppSetting.UserAuth)
|
||||
{
|
||||
int[] userIds = UserContext.Current.GetCurrentUserAuthUserIds(permissionTableName);
|
||||
if (userIds?.Length > 0)
|
||||
{
|
||||
// 对应 QueryTenancyDynamicShareDBFilter:直接写入 filters 供 BuildWhere 生成 IN
|
||||
AddInFilter(filters, filterCreateId, userIds);
|
||||
return selectSql;
|
||||
}
|
||||
}
|
||||
|
||||
var roleIds = UserContext.Current.RoleIds ?? Array.Empty<int>();
|
||||
var permission = UserContext.Current.GetPermissions(permissionTableName.ToLower()) ?? new Permissions();
|
||||
|
||||
// 自定义数据权限:对应 QueryCustom,转换成 SearchParameters 直接放入 filters
|
||||
if (permission.CustomAuth != null)
|
||||
{
|
||||
AddCustomFilters(filters, permission.CustomAuth);
|
||||
return selectSql;
|
||||
}
|
||||
|
||||
List<int> authDataTypes;
|
||||
if (!string.IsNullOrEmpty(permission.AuthMenuData))
|
||||
{
|
||||
authDataTypes = new List<int> { permission.AuthMenuData.GetInt() };
|
||||
}
|
||||
else
|
||||
{
|
||||
authDataTypes = RoleContext.GetRoles(x => roleIds.Contains(x.Id))
|
||||
.Where(x => x.AuthData > 0)
|
||||
.Select(s => s.AuthData)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
if (!isUserTable && authDataTypes.Count == 0)
|
||||
{
|
||||
return selectSql;
|
||||
}
|
||||
|
||||
if (!isUserTable &&
|
||||
(authDataTypes.Contains((int)AuthData.本组织及下数据) || authDataTypes.Contains((int)AuthData.本组织数据)))
|
||||
{
|
||||
var deptIds = UserContext.Current.DeptIds;
|
||||
var userDeptQuery = DBServerProvider.DbContext.Set<Sys_UserDepartment>().Where(x => x.Enable == 1);
|
||||
if (authDataTypes.Contains((int)AuthData.本组织及下数据))
|
||||
{
|
||||
var childDeptIds = DepartmentContext.GetAllChildrenIds(deptIds);
|
||||
userDeptQuery = userDeptQuery.Where(x => childDeptIds.Contains(x.DepartmentId));
|
||||
}
|
||||
else
|
||||
{
|
||||
userDeptQuery = userDeptQuery.Where(x => deptIds.Contains(x.DepartmentId));
|
||||
}
|
||||
|
||||
var deptUserIds = userDeptQuery.Select(s => s.UserId).Distinct().Take(5000).ToArray();
|
||||
AddInFilter(filters, filterCreateId, deptUserIds);
|
||||
return selectSql;
|
||||
}
|
||||
|
||||
if (isUserTable ||
|
||||
authDataTypes.Contains((int)AuthData.本角色以及下数据) ||
|
||||
authDataTypes.Contains((int)AuthData.本角色数据))
|
||||
{
|
||||
var userRoleQuery = DBServerProvider.DbContext.Set<Sys_UserRole>()
|
||||
.Where(x => x.Enable == 1 && x.RoleId > 1);
|
||||
|
||||
if (isUserTable || authDataTypes.Contains((int)AuthData.本角色以及下数据))
|
||||
{
|
||||
var childRoleIds = RoleContext.GetAllChildrenIds(roleIds);
|
||||
userRoleQuery = userRoleQuery.Where(x => childRoleIds.Contains(x.RoleId));
|
||||
}
|
||||
else
|
||||
{
|
||||
userRoleQuery = userRoleQuery.Where(x => roleIds.Contains(x.RoleId));
|
||||
}
|
||||
|
||||
var roleUserIds = userRoleQuery.Select(s => s.UserId).Distinct().Take(5000).ToArray();
|
||||
AddInFilter(filters, filterCreateId, roleUserIds);
|
||||
return selectSql;
|
||||
}
|
||||
|
||||
if (authDataTypes.Contains((int)AuthData.仅自己数据))
|
||||
{
|
||||
filters.Add(new SearchParameters
|
||||
{
|
||||
Name = filterCreateId,
|
||||
Value = UserContext.Current.UserId.ToString(),
|
||||
DisplayType = "="
|
||||
});
|
||||
}
|
||||
|
||||
return selectSql;
|
||||
}
|
||||
|
||||
private static string ResolvePermissionTableName(string tableName)
|
||||
{
|
||||
//var tableInfo = TableColumnContext.TableInfo.FirstOrDefault(x =>
|
||||
// string.Equals(x.TableName, tableName, StringComparison.OrdinalIgnoreCase)
|
||||
// || string.Equals(x.TableTrueName, tableName, StringComparison.OrdinalIgnoreCase));
|
||||
//return tableInfo?.TableName ?? tableName;
|
||||
return tableName;
|
||||
}
|
||||
|
||||
private static void AddInFilter(List<SearchParameters> filters, string fieldName, IEnumerable<int> userIds)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fieldName) || userIds == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var ids = userIds.Distinct().ToArray();
|
||||
if (ids.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
filters.Add(new SearchParameters
|
||||
{
|
||||
Name = fieldName,
|
||||
Value = string.Join(",", ids),
|
||||
DisplayType = "in"
|
||||
});
|
||||
}
|
||||
|
||||
private static void AddCustomFilters(List<SearchParameters> filters, List<Dictionary<string, string>> list)
|
||||
{
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (!item.TryGetValue("field", out var field) || string.IsNullOrWhiteSpace(field))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!item.TryGetValue("value", out var value) || string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
value = value.Trim();
|
||||
item.TryGetValue("filterType", out var filterType);
|
||||
item.TryGetValue("valueType", out var valueType);
|
||||
|
||||
// valueType=1: 当前用户上下文字段替换
|
||||
if (valueType == "1")
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case "User_Id":
|
||||
filters.Add(new SearchParameters { Name = field, Value = UserContext.Current.UserId.ToString(), DisplayType = "eq" });
|
||||
break;
|
||||
case "RoleIds":
|
||||
AddInStringFilter(filters, field, UserContext.Current.RoleIds.Select(s => s.ToString()));
|
||||
break;
|
||||
case "DeptIds":
|
||||
AddInStringFilter(filters, field, UserContext.Current.DeptIds.Select(s => s.ToString()));
|
||||
break;
|
||||
default:
|
||||
var property = typeof(UserInfo).GetProperty(value);
|
||||
var userInfoVal = property?.GetValue(UserContext.Current.UserInfo);
|
||||
if (userInfoVal != null)
|
||||
{
|
||||
filters.Add(new SearchParameters
|
||||
{
|
||||
Name = field,
|
||||
Value = userInfoVal.ToString(),
|
||||
DisplayType = MapDisplayType(filterType, false)
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isListValue = value.Contains(",");
|
||||
bool isIn = string.Equals(filterType, "in", StringComparison.OrdinalIgnoreCase);
|
||||
bool isNotEqual = string.Equals(filterType, "!=", StringComparison.OrdinalIgnoreCase);
|
||||
if (isIn || isNotEqual || isListValue)
|
||||
{
|
||||
var vals = value.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToArray();
|
||||
if (vals.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
filters.Add(new SearchParameters
|
||||
{
|
||||
Name = field,
|
||||
Value = string.Join(",", vals),
|
||||
DisplayType = isIn ? "in" : "notin"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
filters.Add(new SearchParameters
|
||||
{
|
||||
Name = field,
|
||||
Value = value,
|
||||
DisplayType = MapDisplayType(filterType, false)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddInStringFilter(List<SearchParameters> filters, string field, IEnumerable<string> values)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(field) || values == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var list = values.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToArray();
|
||||
if (list.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
filters.Add(new SearchParameters
|
||||
{
|
||||
Name = field,
|
||||
Value = string.Join(",", list),
|
||||
DisplayType = "in"
|
||||
});
|
||||
}
|
||||
|
||||
private static string MapDisplayType(string filterType, bool defaultLike)
|
||||
{
|
||||
switch (filterType)
|
||||
{
|
||||
case "小于":
|
||||
filterType = "<";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return filterType;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
api_sqlsugar/VolPro.Core/Tenancy/TenancySqlManager.cs
Normal file
41
api_sqlsugar/VolPro.Core/Tenancy/TenancySqlManager.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using SqlSugar;
|
||||
using System.Collections.Generic;
|
||||
using VolPro.Core.ManageUser;
|
||||
using VolPro.Entity.DomainModels;
|
||||
|
||||
namespace VolPro.Core.Tenancy
|
||||
{
|
||||
public static class TenancySqlManager
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 自定义主表查询
|
||||
/// </summary>
|
||||
/// <param name="tableName">查询的表名</param>
|
||||
/// <param name="selectSql">查询的sql(框架生成的,可以直接用也可以单独写)</param>
|
||||
/// <param name="filters">查询条件</param>
|
||||
/// <returns></returns>
|
||||
public static string GetSearchSqlQuery(this string tableName, string selectSql, List<SearchParameters> filters, List<SugarParameter> parameters)
|
||||
{
|
||||
//超级管理员不限制(这里可以根据tableName表名自己判断要不要限制超级管理员)
|
||||
if (UserContext.Current.IsSuperAdmin)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
switch (tableName.ToLower())
|
||||
{
|
||||
//根据不同的表名设置不同的查询,查询条件在filters中
|
||||
case "sys_user":
|
||||
/* 重新生杨sql
|
||||
* selectSql = $"select * from {tableName} where xx=@xx";
|
||||
* 添加自定义参数
|
||||
* parameters.Add("@xx", "value");
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return selectSql;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user