274 lines
11 KiB
C#
274 lines
11 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|