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
{
///
/// 获取数据权限sql
/// 调用方式:DBServerProvider.DbContext.Set<表>().CreateTenancyFilterSql();
///
///
///
///
public static string CreateTenancyFilterSql(this ISugarQueryable query) where T : class
{
return query.CreateTenancyFilter().ToSqlString();
}
///
/// 注意:数据库表中必须包括appsettings.json配置文件UserIdField的字段才会进行数据隔离。如果表没有这些字段,请在上面单独写过滤逻辑
///
///
///
///
public static ISugarQueryable CreateTenancyFilter(this ISugarQueryable 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(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(userIds, LinqExpressionType.In));
}
}
var roleIds = UserContext.Current.RoleIds;
//2024.08.11增加菜单数据权限(优先级高级角色数据权限)
//2024.08.11增加菜单数据权限(优先级高级角色数据权限)
List 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() { 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().Where(x => x.Enable == 1);
if (authDataTypes.Contains((int)AuthData.本组织及下数据))
{
deptIds = DepartmentContext.GetAllChildrenIds(deptIds);
}
//分库
if (CheckDb())
{
userDeptQuery = userDeptQuery.Where(x => deptIds.Contains(x.DepartmentId));
var userIds = userDeptQuery.Select(s => s.UserId).Distinct();
query = query.QueryTenancyDynamicShareDBFilter(filterCreateId, userIds);
}
else
{
query = query.QueryTenancyFilter(filterCreateId, "UserId", deptIds: deptIds);
}
return query;
}
//如果角色没有配置数据权限,当前页面是isUserTable=true用户表时,默认显示当前角色下的数据
if (isUserTable || authDataTypes.Contains((int)AuthData.本角色以及下数据) || authDataTypes.Contains((int)AuthData.本角色数据))
{
var userRoleQuery = DBServerProvider.DbContext.Set().Where(x => x.Enable == 1 && x.RoleId > 1);
if (isUserTable || authDataTypes.Contains((int)AuthData.本角色以及下数据))
{
//获取所有子角色
roleIds = RoleContext.GetAllChildrenIds(roleIds).ToArray();
}
//分库
if (CheckDb())
{
userRoleQuery = userRoleQuery.Where(x => roleIds.Contains(x.RoleId));
var userIds = userRoleQuery.Select(s => s.UserId).Distinct();
query = query.QueryTenancyDynamicShareDBFilter(filterCreateId, userIds);
}
else
{
query = query.QueryTenancyFilter(filterCreateId, "UserId", roleIds);
}
return query;
}
if (authDataTypes.Contains((int)AuthData.仅自己数据))
{
return query.Where(filterCreateId.CreateExpression(UserContext.Current.UserId, LinqExpressionType.Equal));
}
return query;
}
private static bool CheckDb()
{
//是否使用分库
return AppSetting.UseDynamicShareDB || typeof(T).BaseType.Name != typeof(SysEntity).Name;
}
private static ISugarQueryable QueryTenancyDynamicShareDBFilter(this ISugarQueryable query, string createIdField, ISugarQueryable userIds)
{
return query.Where(createIdField.CreateExpression(userIds.Take(5000).ToArray(), LinqExpressionType.In));
}
private static bool isPgSql = DBType.Name == DbCurrentType.PgSql.ToString() || DBType.Name == DbCurrentType.Kdbndp.ToString();
private static ISugarQueryable QueryTenancyFilter(this ISugarQueryable query, string createIdField,
string userIdField, int[] roleIds = null, List 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()
.Where(s => s.Enable == 1 && deptIds.Contains(s.DepartmentId) && SqlFunc.MappingColumn(createIdField) == SqlFunc.MappingColumn(userIdField)).Any());
}
else
{
query = query.Where(it => SqlSugar.SqlFunc.Subqueryable()
.Where(s => s.Enable == 1 && roleIds.Contains(s.RoleId) && SqlFunc.MappingColumn(createIdField) == SqlFunc.MappingColumn(userIdField)).Any());
}
return query;
}
///
/// 自定义数据权限
///
///
///
private static ISugarQueryable QueryCustom(this ISugarQueryable query, List> list)
{
var properties = typeof(T).GetProperties();
//Expression> orFilter = null;
Expression> 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(userVal, LinqExpressionType.Equal));
break;
//2当前角色
case "RoleIds":
expression = expression.And(field.CreateExpression(UserContext.Current.RoleIds, LinqExpressionType.In));
break;
//3当前部门
case "DeptIds":
expression = expression.And(field.CreateExpression(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(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(values, type));
continue;
}
expression = expression.And(field.CreateExpression(value.ChangeType(properties.Where(x => x.Name == field).FirstOrDefault().PropertyType), type));
}
return query.Where(expression);
}
}
}