using System.Text; using Infrastructure; using OpenAuth.App.Base; using OpenAuth.App.BaseApp.Base; using OpenAuth.App.Interface; using OpenAuth.App.Permission.Request; using OpenAuth.Repository; using OpenAuth.Repository.Domain; using SqlSugar; namespace OpenAuth.App.Permission; /// /// 数据权限业务类 /// public class BaseDataAuthorizeApp : SqlSugarBaseApp { /// /// 构造函数 /// /// /// /// public BaseDataAuthorizeApp(ISugarUnitOfWork unitWork, ISimpleClient repository, IAuth auth) : base(unitWork, repository, auth) { } #region 获取数据 /// /// 获取数据权限对应关系数据列表 /// /// 编码 /// 用户或角色主键 /// public Task> GetList(string code, string[] objectIds) { return Repository.AsQueryable() .Where(t => t.Code.Equals(code) && (objectIds.Contains(t.ObjectId) || t.ObjectType == 3) ).ToListAsync(); } /// /// 获取数据权限列表(分页) /// public async Task>>> GetPageList(BaseDataAuthListReq req) { RefAsync totalCount = 0; // 实现查询及分页 var result = await Repository.AsQueryable() .WhereIF(req.Type != null, t => t.Type == req.Type) .WhereIF(!string.IsNullOrEmpty(req.ObjectId), t => t.ObjectId == req.ObjectId) .WhereIF(!string.IsNullOrEmpty(req.key), t => t.Name.Contains(req.key) || t.Code.Contains(req.key)) .ToPageListAsync(req.page, req.limit, totalCount); return new Response>> { Result = new PageInfo> { Items = result, Total = totalCount } }; } /// /// 获取实体 /// /// 主键 /// public Task GetEntity(string keyValue) { return Repository.GetByIdAsync(keyValue); } #endregion #region 提交数据 /// /// 删除实体数据 /// /// 主键 /// public async Task DeleteEntity(string keyValue) { await Repository.DeleteByIdAsync(keyValue); } /// /// 保存实体数据(新增、修改) /// /// 主键 /// 实体 /// public async Task SaveEntity(string keyValue, BaseDataAuthReq record) { var user = _auth.GetCurrentUser(); var entity = record.MapTo(); entity.Formula = record.Formula.ToJson(); if (string.IsNullOrEmpty(keyValue)) { entity.Id = Guid.NewGuid().ToString(); entity.CreateDate = DateTime.Now; entity.CreateUserId = user.User.Id.ToString(); entity.CreateUserName = user.User.Name; } else { entity.Id = keyValue; entity.ModifyDate = DateTime.Now; entity.ModifyUserId = user.User.Id.ToString(); entity.ModifyUserName = user.User.Name; } // 全部值都更新了 await Repository.InsertOrUpdateAsync(entity); } #endregion #region 扩展方法 /// /// 获取自定义表单数据权限查询条件 /// /// 自定义表单功能主键 /// /// todo 可以优化,使代码逻辑清晰,减少代码量,比如有无公式,可以合并部分逻辑 /// 逻辑:1. 超级用户不做过滤 2. 先看有无公式(默认条件使用and连接),再看有无分组公式(分组公式使用and连接) public async Task GetWhereSql(string code) { // 取得当前用户信息 var userInfo = _auth.GetCurrentUser(); // 超级用户不做过滤 todo 暂时注释 /*if (userInfo.User.Id.Equals(-1)) { return ""; }*/ // 26个字母干嘛用的?别名? var numIndex = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; // 获取数据权限配置信息 // 查询当前用户所拥有的角色或者岗位 var roleIds = userInfo.Roles.Select(t => t.Id).MapToList(); var objectIds = new List { userInfo.User.Id + "", }; objectIds.AddRange(roleIds); // code 自定义表单功能主键 查询当前用户或者用户所属角色是否有设置的权限规则 var baseDataAuths = await GetList(code, objectIds.ToArray()); // 保存拼接的sql var whereSqlSb = new StringBuilder(); var sqlNum = 0; foreach (var auth in baseDataAuths) { //{"formula":"A and B", //"conditions":[ //{"f_FieldId":"F_text0","f_Symbol":1,"f_FieldValueType":1,"f_FieldValue":"xxx","group":"","type":"","table":"","cfield":"","field":"","relationField":""}], //"formulas":[1 or 2]} // 判断是否是开头 // 先运行这里 // 不同数据权限规则使用or ,很可能只有一条吧 whereSqlSb.Append(sqlNum > 0 ? " AND ( " : " ( "); var strSql = ""; // 反序列化数据权限公式 var itemFormula = auth.Formula.ToObject(); // formula 不存在时,直接使用and连接 if (string.IsNullOrEmpty(itemFormula.Formula)) { // Conditions // 默认公式 for (var i = 1; i < itemFormula.Conditions.Count + 1; i++) { var conditionItem = itemFormula.Conditions[i - 1]; conditionItem.index = i; // 赋值索引,后面应该会用到,从1开始 // 这里的Group是字符串,大概是字母 A B 之类 ,如何没有Group,条件之间用 and 连接 if (!string.IsNullOrEmpty(conditionItem.Group)) { continue; } if (strSql != "") { strSql += " AND "; } strSql += " {@hopetry" + i + "hopetry@} "; } // 公式为空,分组公式不为空 if (itemFormula.Formulas != null && itemFormula.Formulas.Count > 0) { // 假设分组公式只有1个 【{“value”: "1 or 2"}】 多个分组公式之间,使用and连接 for (var i = 0; i < itemFormula.Formulas.Count; i++) { if (itemFormula.Conditions.FindIndex(t => t.Group == numIndex[i]) != -1) { if (strSql != "") { strSql += " AND "; } strSql += " {@hopetry" + numIndex[i] + "hopetry@} "; } } } } // 存在公式 else { // 当分组公式存在时,公式含有分组信息,如: A and B strSql = itemFormula.Formula; // 为什么从1开头 for (var i = 1; i < itemFormula.Conditions.Count + 1; i++) { var conditionItem = itemFormula.Conditions[i - 1]; // 取了条件没有使用 conditionItem.index = i; strSql = strSql.Replace("" + i, "{@hopetry" + i + "hopetry@}"); } if (itemFormula.Formulas != null && itemFormula.Formulas.Count > 0) { for (var i = 0; i < itemFormula.Formulas.Count; i++) { strSql = strSql.Replace(numIndex[i], "{@hopetry" + numIndex[i] + "hopetry@}"); } } } // 针对公组公式存在,再做部分处理,todo 暂时可以忽略,不实现分组 if (itemFormula.Formulas != null && itemFormula.Formulas.Count > 0) { // 分组公式 for (var i = 0; i < itemFormula.Formulas.Count; i++) { var groupSql = new StringBuilder(); var groupList = itemFormula.Conditions.FindAll(t => t.Group == numIndex[i]); if (groupList.Count > 0) { groupSql.Append( // relationField 关联字段(外键) 这里的Table应该是子表吧 $" {groupList[0].RelationField} in ( SELECT {groupList[0].Field} FROM {groupList[0].Table} WHERE "); // 初始化分组公式 var groupSqlWhere = ""; if (string.IsNullOrEmpty(itemFormula.Formulas[i].Value)) { foreach (var groupItem in groupList) { if (groupSqlWhere != "") { groupSqlWhere += " AND "; } groupSqlWhere += " {@hopetry" + groupItem.index + "hopetry@} "; } } else { groupSqlWhere = itemFormula.Formulas[i].Value; foreach (var groupItem in groupList) { groupSqlWhere = groupSqlWhere.Replace("" + groupItem.index, "{@hopetry" + groupItem.index + "hopetry@}"); } } foreach (var groupItem in groupList) { var strone = new StringBuilder(); if (groupItem.F_Symbol.Equals("8")) { strone.Append($" ({groupItem.Cfield} "); } else { strone.Append($" {groupItem.Cfield} "); } var value = await GetValue(int.Parse(groupItem.F_FieldValueType), groupItem.F_FieldValue); switch (int.Parse(groupItem.F_Symbol)) { case 1: // 等于 strone.Append($" = {value}"); break; case 2: // 大于 strone.Append($" > {value}"); break; case 3: // 大于等于 strone.Append($" >= {value}"); break; case 4: // 小于 strone.Append($" < {value}"); break; case 5: // 小于等于 strone.Append($" <= {value}"); break; case 6: // 包含 value = value.Replace("'", ""); strone.Append($" like '%{value}%'"); break; case 7: // 包含于 value = value.Replace(",", "','"); strone.Append($" in ({value})"); break; case 8: // 不等于 strone.Append($" != {value} or {groupItem.Cfield} is null ) "); break; case 9: // 不包含 value = value.Replace("'", ""); strone.Append($" not like '%{value}%'"); break; case 10: // 不包含于 value = value.Replace(",", "','"); strone.Append($" not in ({value})"); break; default: break; } groupSqlWhere = groupSqlWhere.Replace("{@hopetry" + groupItem.index + "hopetry@}", strone.ToString()); } groupSql.Append(groupSqlWhere); groupSql.Append(" ) "); strSql = strSql.Replace("{@hopetry" + numIndex[i] + "hopetry@}", groupSql.ToString()); } } } // 填充占位符,生成实际wheresql var num = 1; foreach (var conditionItem in itemFormula.Conditions) { // 这里的group应该是 A B C 之类的字母 if (string.IsNullOrEmpty(conditionItem.Group)) { var strone = new StringBuilder(); if (conditionItem.Type == "glbd") // 未使用 { strone.Append( $" {conditionItem.RelationField} in ( SELECT {conditionItem.Field} FROM {conditionItem.Table} WHERE {conditionItem.Cfield} "); } else { // 8 不等于 if (conditionItem.F_Symbol.Equals("8")) { strone.Append($" ( {conditionItem.F_FieldId}"); } else { strone.Append($" {conditionItem.F_FieldId}"); } } var value = await GetValue(int.Parse(conditionItem.F_FieldValueType), conditionItem.F_FieldValue); // 如果 value 值是 userId switch (int.Parse(conditionItem.F_Symbol)) { case 1: // 等于 strone.Append($" = {value}"); break; case 2: // 大于 strone.Append($" > {value}"); break; case 3: // 大于等于 strone.Append($" >= {value}"); break; case 4: // 小于 strone.Append($" < {value}"); break; case 5: // 小于等于 strone.Append($" <= {value}"); break; case 6: // 包含 value = value.Replace("'", ""); strone.Append($" like '%{value}%'"); break; case 7: // 包含于 value = value.Replace(",", "','"); value = value.Replace("#", ","); strone.Append($" in ({value})"); break; case 8: // 不等于 strone.Append($" != {value}"); if (conditionItem.Type == "glbd") { strone.Append($" or {conditionItem.Cfield} is null "); } else { strone.Append($" or {conditionItem.F_FieldId} is null ) "); } break; case 9: // 不包含 value = value.Replace("'", ""); strone.Append($" not like '%{value}%'"); break; case 10: // 不包含于 value = value.Replace(",", "','"); strone.Append($" not in ({value})"); break; default: break; } strone.Append(conditionItem.Type == "glbd" ? " ) " : " "); strSql = strSql.Replace("{@hopetry" + num + "hopetry@}", strone.ToString()); } num++; } whereSqlSb.Append(strSql); whereSqlSb.Append(" ) "); sqlNum++; } Console.WriteLine("strRes:" + whereSqlSb.ToString()); return whereSqlSb.ToString(); } /// /// 获取数据 where 值部分 /// /// 数据类型 /// 数据值 /// /// // todo 扩展改造 private async Task GetValue(int? type, string value) { var userInfo = _auth.GetCurrentUser(); //1.文本(string) 2.登录者ID 3.登录者账号 4.登录者部门 5. 登录者部门及下属部门 6.登录者岗位 7.登录者角色 10. 文本(int) string text; switch (type) { case 1: // 文本(string) text = $"'{value}'"; break; case 10: // 文本(int) text = value; break; case 2: // 登录者ID(本地创建数据) text = userInfo.User.Id + ""; break; case 3: // 登录者账号 text = $"'{userInfo.User.Account}'"; break; // todo 扩展实现 case 4: // 本部门 text = $"( SELECT CAST ( \"OrgId\" AS VARCHAR ) AS \"OrgId\" FROM sys_userorg WHERE \"UserId\" = '{userInfo.User.Id}' )"; break; case 5: // 本部门及子部门 text = $"select CAST(\"Id\" AS VARCHAR) from sys_org where string_to_array(\"CascadeId\"#'.') && ARRAY['{string.Join(",", userInfo.Orgs.Select(t => t.Id).MapToList())}']"; break; case 6: text = ""; break; case 7: text = $"'{string.Join(",", userInfo.Roles.Select(t => t.Id).MapToList())}'"; break; default: text = $"'{value}'"; break; } return text; } #endregion public async Task> GetEntityByCode(string code) { var formModuleEntity = await Repository .ChangeRepository>() .GetFirstAsync(r => r.Id == code); if (formModuleEntity != null) { var formScheme = await base.Repository.ChangeRepository>() .GetFirstAsync(r => r.Id == formModuleEntity.FormVerison); return new Response() { Result = formScheme, Message = "查询成功" }; } throw new Exception("code无效"); } }