Files
SecMPS/api_sqlsugar/VolPro.Core/Tenancy/TenancySqlExpression.cs
2026-05-15 23:22:48 +08:00

274 lines
11 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}
}