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 文件。 // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
// //
@ -14,8 +14,8 @@ namespace Admin.NET.Core;
public class EnumToDictJob : IJob public class EnumToDictJob : IJob
{ {
private readonly IServiceScopeFactory _scopeFactory; private readonly IServiceScopeFactory _scopeFactory;
private const string DefaultTagType = null;
private const int OrderOffset = 10; private const int OrderOffset = 10;
private const string DefaultTagType = "info";
public EnumToDictJob(IServiceScopeFactory scopeFactory) public EnumToDictJob(IServiceScopeFactory scopeFactory)
{ {
@ -24,46 +24,58 @@ public class EnumToDictJob : IJob
public async Task ExecuteAsync(JobExecutingContext context, CancellationToken stoppingToken) 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(); using var serviceScope = _scopeFactory.CreateScope();
var sysEnumService = serviceScope.ServiceProvider.GetRequiredService<SysEnumService>();
// 获取数据库连接
var db = serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>().CopyNew(); 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; var newEnumType = enumTypeList.Where(u => !updatedEnumCodes.Contains(u.TypeName)).ToList();
foreach (var dictType in sysDictTypeList.Where(x => !x.Code.EndsWith("Enum"))) var (newDictTypes, newDictDatas) = GetNewSysDicts(newEnumType);
Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典的枚举类名称必须以Enum结尾: {dictType.Code} ({dictType.Name})");
sysDictTypeList = sysDictTypeList.Where(x => x.Code.EndsWith("Enum")).ToList();
await SyncEnumToDictInfoAsync(db, sysDictTypeList); // 执行数据库操作
Console.ForegroundColor = ConsoleColor.Yellow;
try try
{ {
await db.BeginTranAsync(); 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()) if (updatedDictDatas.Count > 0)
.WhereColumns(u => new { u.DictTypeId, u.Code }) await db.Updateable(updatedDictDatas).ExecuteCommandAsync(stoppingToken);
.SplitUpdate(u => u.Any())
.SplitInsert(_ => true)
.ToStorageAsync();
await storageable2.BulkCopyAsync();
await storageable2.BulkUpdateAsync(nameof(SysDictData.Value), nameof(SysDictData.Code), nameof(SysDictData.Name));
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(); await db.CommitTranAsync();
} }
@ -73,63 +85,131 @@ public class EnumToDictJob : IJob
Log.Error($"系统枚举转换字典操作错误:{error.Message}\n堆栈跟踪{error.StackTrace}", error); Log.Error($"系统枚举转换字典操作错误:{error.Message}\n堆栈跟踪{error.StackTrace}", error);
throw; throw;
} }
finally var originColor = Console.ForegroundColor;
{ Console.ForegroundColor = ConsoleColor.Green;
Console.ForegroundColor = originColor; Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典");
} Console.ForegroundColor = originColor;
} }
/// <summary> /// <summary>
/// 用于同步枚举转字典旧数据(后期可删除) /// 获取需要新增的字典列表
/// </summary> /// </summary>
/// <param name="db"></param> /// <param name="addEnumType"></param>
/// <param name="list"></param> /// <returns>
//[Obsolete] /// 一个元组,包含以下元素:
private static async Task SyncEnumToDictInfoAsync(SqlSugarClient db, List<SysDictType> list) /// <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(); var newDictType = new List<SysDictType>();
foreach (var dbDictType in await db.Queryable<SysDictType>().Where(x => codeList.Contains(x.Code)).ToListAsync() ?? new()) var newDictData = new List<SysDictData>();
{ if (addEnumType.Count <= 0)
var enumDictType = list.First(u => u.Code == dbDictType.Code); return (newDictType, newDictData);
if (enumDictType.Id == dbDictType.Id) continue;
// 数据不一致则删除 // 新增字典类型
_ = db.Deleteable<SysDictData>().Where(u => u.DictTypeId == dbDictType.Id).ExecuteCommandAsync(); newDictType = addEnumType.Select(u => new SysDictType
_ = 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)
{ {
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), Id = YitIdHelper.NextId(),
Code = type.TypeName, DictTypeId = t2.Id,
Name = type.TypeDescribe, Name = u.Describe,
Remark = type.TypeRemark Value = u.Value.ToString(),
}; Code = u.Name,
dictType.Children = type.EnumEntities.Select(u => new SysDictData Remark = t2.Remark,
{
Id = dictType.Id + orderNo++,
DictTypeId = dictType.Id,
Name = u.Name,
Value = u.Describe,
Code = u.Value.ToString(),
OrderNo = u.Value + OrderOffset, OrderNo = u.Value + OrderOffset,
TagType = u.Theme != "" ? u.Theme : DefaultTagType, TagType = u.Theme != "" ? u.Theme : DefaultTagType,
}).ToList(); }).ToList()
list.Add(dictType); }).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 文件。 // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
// //
@ -155,6 +155,15 @@ public class SysAuthService : IDynamicApiController, ITransient
{ {
if (CryptogramUtil.CryptoType == CryptogramEnum.MD5.ToString()) 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; if (user.Password.Equals(MD5Encryption.Encrypt(password))) return;
_sysCacheService.Set(keyPasswordErrorTimes, ++passwordErrorTimes, TimeSpan.FromMinutes(30)); _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 文件。 // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
// //
@ -127,6 +127,13 @@ public static class SqlSugarSetup
db.Ado.CommandTimeOut = 30; db.Ado.CommandTimeOut = 30;
// 打印SQL语句 // 打印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) if (enableConsoleSql)
{ {
db.Aop.OnLogExecuting = (sql, pars) => db.Aop.OnLogExecuting = (sql, pars) =>
@ -151,13 +158,6 @@ public static class SqlSugarSetup
Console.ForegroundColor = originColor; Console.ForegroundColor = originColor;
App.PrintToMiniProfiler("SqlSugar", "Info", log); 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) => db.Aop.OnLogExecuted = (sql, pars) =>
{ {
//// 若参数值超过100个字符则进行截取 //// 若参数值超过100个字符则进行截取

View File

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