Merge pull request 'BUG_Md5模式无法登陆' (#182) from koy07555/Admin.NET.Pro:BUG_Md5模式无法登陆 into main

Reviewed-on: http://101.43.53.74:3000/Admin.NET/Admin.NET.Pro/pulls/182
This commit is contained in:
zuohuaijun 2024-11-27 14:06:47 +08:00
commit 61b89ae963
4 changed files with 183 additions and 88 deletions

View File

@ -1,4 +1,4 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
@ -14,8 +14,8 @@ namespace Admin.NET.Core;
public class EnumToDictJob : IJob
{
private readonly IServiceScopeFactory _scopeFactory;
private const string DefaultTagType = null;
private const int OrderOffset = 10;
private const string DefaultTagType = "info";
public EnumToDictJob(IServiceScopeFactory scopeFactory)
{
@ -24,46 +24,58 @@ public class EnumToDictJob : IJob
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken)
{
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
using var serviceScope = _scopeFactory.CreateScope();
var sysEnumService = serviceScope.ServiceProvider.GetRequiredService<SysEnumService>();
// 获取数据库连接
var db = serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew();
var sysEnumService = serviceScope.ServiceProvider.GetRequiredService<SysEnumService>();
var sysDictTypeList = GetDictByEnumType(sysEnumService.GetEnumTypeList());
// 获取枚举类型列表
var enumTypeList = sysEnumService.GetEnumTypeList();
var enumCodeList = enumTypeList.Select(u => u.TypeName);
// 查询数据库中已存在的枚举类型代码
//var exp = Expressionable.Create<SysDictType, SingleColumnEntity<string>>().And((t1, t2) => t1.Code == t2.ColumnName).ToExpression();
//var sysDictTypeList = await db.Queryable<SysDictType>().Includes(t1 => t1.Children).BulkListQuery(exp, enumCodeList, stoppingToken);
var sysDictTypeList = await db.Queryable<SysDictType>().Includes(u => u.Children)
.Where(u => enumCodeList.Contains(u.Code)).ToListAsync(stoppingToken);
// 更新的枚举转换字典
var updatedEnumCodes = sysDictTypeList.Select(u => u.Code);
var updatedEnumType = enumTypeList.Where(u => updatedEnumCodes.Contains(u.TypeName)).ToList();
var sysDictTypeDict = sysDictTypeList.ToDictionary(u => u.Code, u => u);
var (updatedDictTypes, updatedDictDatas, newSysDictDatas) = GetUpdatedDicts(updatedEnumType, sysDictTypeDict);
// 校验枚举类命名规范,字典相关功能中需要通过后缀判断是否为枚举类型
Console.ForegroundColor = ConsoleColor.Red;
foreach (var dictType in sysDictTypeList.Where(x => !x.Code.EndsWith("Enum")))
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典的枚举类名称必须以Enum结尾: {dictType.Code} ({dictType.Name})");
sysDictTypeList = sysDictTypeList.Where(x => x.Code.EndsWith("Enum")).ToList();
// 新增的枚举转换字典
var newEnumType = enumTypeList.Where(u => !updatedEnumCodes.Contains(u.TypeName)).ToList();
var (newDictTypes, newDictDatas) = GetNewSysDicts(newEnumType);
await SyncEnumToDictInfoAsync(db, sysDictTypeList);
Console.ForegroundColor = ConsoleColor.Yellow;
// 执行数据库操作
try
{
await db.BeginTranAsync();
var storageable1 = await db.Storageable(sysDictTypeList)
.SplitUpdate(it => it.Any())
.SplitInsert(_ => true)
.ToStorageAsync();
await storageable1.BulkCopyAsync();
await storageable1.BulkUpdateAsync();
Console.WriteLine($"【{DateTime.Now}】系统枚举类转字典类型数据: 插入{storageable1.InsertList.Count}条, 更新{storageable1.UpdateList.Count}条, 共{storageable1.TotalList.Count}条。");
if (updatedDictTypes.Count > 0)
await db.Updateable(updatedDictTypes).ExecuteCommandAsync(stoppingToken);
var storageable2 = await db.Storageable(sysDictTypeList.SelectMany(u => u.Children).ToList())
.WhereColumns(u => new { u.DictTypeId, u.Code })
.SplitUpdate(u => u.Any())
.SplitInsert(_ => true)
.ToStorageAsync();
await storageable2.BulkCopyAsync();
await storageable2.BulkUpdateAsync(nameof(SysDictData.Value), nameof(SysDictData.Code), nameof(SysDictData.Name));
if (updatedDictDatas.Count > 0)
await db.Updateable(updatedDictDatas).ExecuteCommandAsync(stoppingToken);
Console.WriteLine($"【{DateTime.Now}】系统枚举项转字典值数据: 插入{storageable2.InsertList.Count}条, 更新{storageable2.UpdateList.Count}条, 共{storageable2.TotalList.Count}条。");
if (newSysDictDatas.Count > 0)
{
//达梦 下用db.Insertable(newDictTypes).ExecuteCommandAsync(stoppingToken);插入400条以上会内容溢出错误所以改用逐条插入
//达梦 下不支持storageable2.BulkUpdateAsync 功能,注意使用
foreach (var dd in newSysDictDatas)
await db.Insertable(dd).ExecuteCommandAsync(stoppingToken);
}
if (newDictTypes.Count > 0)
await db.Insertable(newDictTypes).ExecuteCommandAsync(stoppingToken);
if (newDictDatas.Count > 0)
{
//达梦 下用db.Insertable(newDictTypes).ExecuteCommandAsync(stoppingToken);插入400条以上会内容溢出错误所以改用逐条插入
//达梦 下不支持storageable2.BulkUpdateAsync 功能,注意使用
foreach (var dd in newDictDatas)
await db.Insertable(dd).ExecuteCommandAsync(stoppingToken);
}
await db.CommitTranAsync();
}
@ -73,63 +85,131 @@ public class EnumToDictJob : IJob
Log.Error($"系统枚举转换字典操作错误:{error.Message}\n堆栈跟踪{error.StackTrace}", error);
throw;
}
finally
{
Console.ForegroundColor = originColor;
}
var originColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
Console.ForegroundColor = originColor;
}
/// <summary>
/// 用于同步枚举转字典旧数据(后期可删除)
/// 获取需要新增的字典列表
/// </summary>
/// <param name="db"></param>
/// <param name="list"></param>
//[Obsolete]
private static async Task SyncEnumToDictInfoAsync(SqlSugarClient db, List<SysDictType> list)
/// <param name="addEnumType"></param>
/// <returns>
/// 一个元组,包含以下元素:
/// <list type="table">
/// <item><term>SysDictTypes</term><description>字典类型列表</description></item>
/// <item><term>SysDictDatas</term><description>字典数据列表</description></item>
/// </list>
/// </returns>
private (List<SysDictType>, List<SysDictData>) GetNewSysDicts(List<EnumTypeOutput> addEnumType)
{
var codeList = list.Select(u => u.Code).ToList();
foreach (var dbDictType in await db.Queryable<SysDictType>().Where(x => codeList.Contains(x.Code)).ToListAsync() ?? new())
{
var enumDictType = list.First(u => u.Code == dbDictType.Code);
if (enumDictType.Id == dbDictType.Id) continue;
var newDictType = new List<SysDictType>();
var newDictData = new List<SysDictData>();
if (addEnumType.Count <= 0)
return (newDictType, newDictData);
// 数据不一致则删除
_ = db.Deleteable<SysDictData>().Where(u => u.DictTypeId == dbDictType.Id).ExecuteCommandAsync();
_ = db.Deleteable<SysDictType>().Where(u => u.Id == dbDictType.Id).ExecuteCommandAsync();
Console.WriteLine($"【{DateTime.Now}】删除字典数据: {dbDictType.Name}-{dbDictType.Code}");
}
}
/// <summary>
/// 枚举信息转字典
/// </summary>
/// <param name="enumTypeList"></param>
/// <returns></returns>
private List<SysDictType> GetDictByEnumType(List<EnumTypeOutput> enumTypeList)
{
var orderNo = 1;
var list = new List<SysDictType>();
foreach (var type in enumTypeList)
// 新增字典类型
newDictType = addEnumType.Select(u => new SysDictType
{
var dictType = new SysDictType
Id = YitIdHelper.NextId(),
Code = u.TypeName,
Name = u.TypeDescribe,
Remark = u.TypeRemark,
Status = StatusEnum.Enable
}).ToList();
// 新增字典数据
newDictData = addEnumType.Join(newDictType, t1 => t1.TypeName, t2 => t2.Code, (t1, t2) => new
{
Data = t1.EnumEntities.Select(u => new SysDictData
{
Id = 900000000000 + CommonUtil.GetFixedHashCode(type.TypeName),
Code = type.TypeName,
Name = type.TypeDescribe,
Remark = type.TypeRemark
};
dictType.Children = type.EnumEntities.Select(u => new SysDictData
{
Id = dictType.Id + orderNo++,
DictTypeId = dictType.Id,
Name = u.Name,
Value = u.Describe,
Code = u.Value.ToString(),
Id = YitIdHelper.NextId(),
DictTypeId = t2.Id,
Name = u.Describe,
Value = u.Value.ToString(),
Code = u.Name,
Remark = t2.Remark,
OrderNo = u.Value + OrderOffset,
TagType = u.Theme != "" ? u.Theme : DefaultTagType,
}).ToList();
list.Add(dictType);
}).ToList()
}).SelectMany(x => x.Data).ToList();
return (newDictType, newDictData);
}
/// <summary>
/// 获取需要更新的字典列表
/// </summary>
/// <param name="updatedEnumType"></param>
/// <param name="sysDictTypeDict"></param>
/// <returns>
/// 一个元组,包含以下元素:
/// <list type="table">
/// <item><term>SysDictTypes</term><description>更新字典类型列表</description>
/// </item>
/// <item><term>SysDictDatas</term><description>更新字典数据列表</description>
/// </item>
/// <item><term>SysDictDatas</term><description>新增字典数据列表</description>
/// </item>
/// </list>
/// </returns>
private (List<SysDictType>, List<SysDictData>, List<SysDictData>) GetUpdatedDicts(List<EnumTypeOutput> updatedEnumType, Dictionary<string, SysDictType> sysDictTypeDict)
{
var updatedSysDictTypes = new List<SysDictType>();
var updatedSysDictData = new List<SysDictData>();
var newSysDictData = new List<SysDictData>();
foreach (var e in updatedEnumType)
{
if (!sysDictTypeDict.TryGetValue(e.TypeName, out var value))
continue;
var updatedDictType = value;
updatedDictType.Name = e.TypeDescribe;
updatedDictType.Remark = e.TypeRemark;
updatedSysDictTypes.Add(updatedDictType);
var updatedDictData = updatedDictType.Children.Where(u => u.DictTypeId == updatedDictType.Id).ToList();
// 遍历需要更新的字典数据
foreach (var dictData in updatedDictData)
{
var enumData = e.EnumEntities.FirstOrDefault(u => dictData.Code == u.Name);
if (enumData != null)
{
dictData.Value = enumData.Value.ToString();
dictData.OrderNo = enumData.Value + OrderOffset;
dictData.Name = enumData.Describe;
dictData.TagType = enumData.Theme != "" ? enumData.Theme : dictData.TagType != "" ? dictData.TagType : DefaultTagType;
updatedSysDictData.Add(dictData);
}
}
// 新增的枚举值名称列表
var newEnumDataNameList = e.EnumEntities.Select(u => u.Name).Except(updatedDictData.Select(u => u.Code));
foreach (var newEnumDataName in newEnumDataNameList)
{
var enumData = e.EnumEntities.FirstOrDefault(u => newEnumDataName == u.Name);
if (enumData != null)
{
var dictData = new SysDictData
{
Id = YitIdHelper.NextId(),
DictTypeId = updatedDictType.Id,
Name = enumData.Describe,
Value = enumData.Value.ToString(),
Code = enumData.Name,
Remark = updatedDictType.Remark,
OrderNo = enumData.Value + OrderOffset,
TagType = enumData.Theme != "" ? enumData.Theme : DefaultTagType,
};
dictData.TagType = enumData.Theme != "" ? enumData.Theme : dictData.TagType != "" ? dictData.TagType : DefaultTagType;
newSysDictData.Add(dictData);
}
}
// 删除的情况暂不处理
}
return list;
return (updatedSysDictTypes, updatedSysDictData, newSysDictData);
}
}

View File

@ -1,4 +1,4 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
@ -155,6 +155,15 @@ public class SysAuthService : IDynamicApiController, ITransient
{
if (CryptogramUtil.CryptoType == CryptogramEnum.MD5.ToString())
{
// 国密SM2解密前端密码传输SM2加密后的
try
{
password = CryptogramUtil.SM2Decrypt(password);
}
catch
{
throw Oops.Oh(ErrorCodeEnum.D0010);
}
if (user.Password.Equals(MD5Encryption.Encrypt(password))) return;
_sysCacheService.Set(keyPasswordErrorTimes, ++passwordErrorTimes, TimeSpan.FromMinutes(30));

View File

@ -1,4 +1,4 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
@ -127,6 +127,13 @@ public static class SqlSugarSetup
db.Ado.CommandTimeOut = 30;
// 打印SQL语句
db.Aop.OnError = ex =>
{
if (ex.Parametres == null) return;
var log = $"【{DateTime.Now}——错误SQL】\r\n{UtilMethods.GetNativeSql(ex.Sql, (SugarParameter[])ex.Parametres)}\r\n";
Log.Error(log, ex);
App.PrintToMiniProfiler("SqlSugar", "Error", log);
};
if (enableConsoleSql)
{
db.Aop.OnLogExecuting = (sql, pars) =>
@ -151,13 +158,6 @@ public static class SqlSugarSetup
Console.ForegroundColor = originColor;
App.PrintToMiniProfiler("SqlSugar", "Info", log);
};
db.Aop.OnError = ex =>
{
if (ex.Parametres == null) return;
var log = $"【{DateTime.Now}——错误SQL】\r\n{UtilMethods.GetNativeSql(ex.Sql, (SugarParameter[])ex.Parametres)}\r\n";
Log.Error(log, ex);
App.PrintToMiniProfiler("SqlSugar", "Error", log);
};
db.Aop.OnLogExecuted = (sql, pars) =>
{
//// 若参数值超过100个字符则进行截取

View File

@ -1,4 +1,4 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
@ -56,12 +56,18 @@ public static class CodeGenUtil
var dataType = dbType switch
{
DbType.Oracle => ConvertDataType_OracleSQL(string.IsNullOrEmpty(dbColumnInfo.OracleDataType) ? dbColumnInfo.DataType : dbColumnInfo.OracleDataType, dbColumnInfo.Length, dbColumnInfo.Scale),
DbType.Dm => ConvertDataType_Dm(string.IsNullOrEmpty(dbColumnInfo.OracleDataType) ? dbColumnInfo.DataType : dbColumnInfo.OracleDataType, dbColumnInfo.Length, dbColumnInfo.Scale),
DbType.PostgreSQL => ConvertDataType_PostgreSQL(dbColumnInfo.DataType),
_ => ConvertDataType_Default(dbColumnInfo.DataType),
};
return dataType + (dbColumnInfo.IsNullable ? "?" : "");
}
// 达梦(DM)数据类型对应的字段类型
public static string ConvertDataType_Dm(string dataType, int? length, int? scale)
{
return ConvertDataType_OracleSQL(dataType, length, scale); //达梦兼容Oracle目前先这样实现
}
// OracleSQL数据类型对应的字段类型
public static string ConvertDataType_OracleSQL(string dataType, int? length, int? scale)
{