IRC_NewDev
he 2023-07-05 10:30:50 +08:00
commit 4a6dfc9a2a
8 changed files with 299 additions and 28 deletions

View File

@ -0,0 +1,57 @@
//--------------------------------------------------------------------
// 此代码由T4模板自动生成 byzhouhang 20210918
// 生成时间 2023-07-04 16:10:46
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using System;
using IRaCIS.Core.Domain.Share;
using System.Collections.Generic;
namespace IRaCIS.Core.Application.ViewModel
{
/// <summary> UserLogView 列表视图模型 </summary>
public class UserLogView: UserLogAddOrEdit
{
public string UserRealName { get; set; }
public string UserName { get; set; }
public UserType UserTypeEnum { get; set; }
public bool IsSuccess { get; set; }
}
///<summary>UserLogQuery 列表查询参数模型</summary>
public class UserLogQuery : PageInput
{
public Guid? TrialId { get; set; }
public UserOptType? OptType { get; set; }
public string? IP { get; set; }
public string? LoginName { get; set; }
public DateTime? BeginDate { get; set; }
public DateTime? EndDate { get; set; }
}
///<summary> UserLogAddOrEdit 列表查询参数模型</summary>
public class UserLogAddOrEdit
{
public Guid? Id { get; set; }
public string IP { get; set; }
public string LoginName { get; set; }
public int OptType { get; set; }
public string LoginPassword { get; set; }
}
}

View File

@ -0,0 +1,24 @@
//--------------------------------------------------------------------
// 此代码由T4模板自动生成 byzhouhang 20210918
// 生成时间 2023-07-04 16:10:34
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using IRaCIS.Core.Application.ViewModel;
namespace IRaCIS.Core.Application.Interfaces
{
/// <summary>
/// IUserLogService
/// </summary>
public interface IUserLogService
{
Task<PageOutput<UserLogView>> GetUserLogList(UserLogQuery inQuery);
//Task<IResponseOutput> AddOrUpdateUserLog(UserLogAddOrEdit addOrEditUserLog);
//Task<IResponseOutput> DeleteUserLog(Guid userLogId);
}
}

View File

@ -0,0 +1,71 @@
//--------------------------------------------------------------------
// 此代码由T4模板自动生成 byzhouhang 20210918
// 生成时间 2023-07-04 16:10:37
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
//--------------------------------------------------------------------
using IRaCIS.Core.Domain.Models;
using Microsoft.AspNetCore.Mvc;
using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.ViewModel;
namespace IRaCIS.Core.Application.Service
{
/// <summary>
/// UserLogService
/// </summary>
[ApiExplorerSettings(GroupName = "Test")]
public class UserLogService : BaseService, IUserLogService
{
private readonly IRepository<UserLog> _userLogRepository;
private readonly IRepository<TrialUser> _trialUserRepository;
public UserLogService(IRepository<UserLog> userLogRepository, IRepository<TrialUser> trialUserRepository)
{
_userLogRepository = userLogRepository;
_trialUserRepository = trialUserRepository;
}
public async Task<PageOutput<UserLogView>> GetUserLogList(UserLogQuery inQuery)
{
var userLogQueryable =
_userLogRepository
.WhereIf(inQuery.TrialId != null, t => t.CreateUser.UserTrials.Any(c => c.TrialId == inQuery.TrialId && c.UserId == t.CreateUserId))
.WhereIf(inQuery.OptType!=null ,t=>t.OptType==inQuery.OptType)
.WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate)
.WhereIf(inQuery.EndDate != null, t => t.CreateTime <= inQuery.EndDate)
.WhereIf(!string.IsNullOrEmpty(inQuery.LoginName) , t => t.LoginName.Contains(inQuery.LoginName) )
.WhereIf(!string.IsNullOrEmpty(inQuery.IP), t => t.IP.Contains(inQuery.IP))
.WhereIf(!string.IsNullOrEmpty(inQuery.LoginName), t => t.LoginName.Contains(inQuery.LoginName))
.ProjectTo<UserLogView>(_mapper.ConfigurationProvider);
var pageList = await userLogQueryable.ToPagedListAsync(inQuery.PageIndex, inQuery.PageSize, string.IsNullOrWhiteSpace(inQuery.SortField) ? "Id" : inQuery.SortField,inQuery.Asc);
return pageList;
}
//public async Task<IResponseOutput> AddOrUpdateUserLog(UserLogAddOrEdit addOrEditUserLog)
//{
// // 在此处拷贝automapper 映射
// var entity = await _userLogRepository.InsertOrUpdateAsync(addOrEditUserLog, true);
// return ResponseOutput.Ok(entity.Id.ToString());
//}
//[HttpDelete("{userLogId:guid}")]
//public async Task<IResponseOutput> DeleteUserLog(Guid userLogId)
//{
// var success = await _userLogRepository.DeleteFromQueryAsync(t => t.Id == userLogId, true);
// return ResponseOutput.Ok();
//}
}
}

View File

@ -27,6 +27,7 @@ namespace IRaCIS.Application.Services
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
private readonly IRepository<UserLog> _userLogRepository;
public UserService(IRepository<User> userRepository,
@ -36,7 +37,8 @@ namespace IRaCIS.Application.Services
IMemoryCache cache,
IRepository<TrialUser> userTrialRepository,
IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig
,
IRepository<UserLog> userLogRepository
)
{
_verifyConfig = verifyConfig;
@ -46,6 +48,7 @@ namespace IRaCIS.Application.Services
_verificationCodeRepository = verificationCodeRepository;
_doctorRepository = doctorRepository;
_userTrialRepository = userTrialRepository;
_userLogRepository = userLogRepository;
}
@ -292,6 +295,8 @@ namespace IRaCIS.Application.Services
IsFirstAdd = true
});
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = _userInfo.Id, LoginName = _userInfo.UserName, IsSuccess = true, OptType = UserOptType.AdminResetPassword }, true);
return ResponseOutput.Ok();
}
@ -402,6 +407,8 @@ namespace IRaCIS.Application.Services
IsFirstAdd = false
});
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = _userInfo.Id, LoginName =string.Empty,LoginPassword=newPwd, IsSuccess = true, OptType = UserOptType.ModifyPassword }, true);
return ResponseOutput.Result(success);
}
@ -436,6 +443,7 @@ namespace IRaCIS.Application.Services
IsFirstAdd = false
});
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = _userInfo.Id, LoginName = _userInfo.UserName, IsSuccess = true, OptType = UserOptType.ModifyPassword }, true);
return ResponseOutput.Result(success);
@ -639,6 +647,8 @@ namespace IRaCIS.Application.Services
if (failCount >= maxFailures)
{
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName,LoginPassword=password, IsSuccess = false, OptType = UserOptType.AccountLocked }, true);
throw new BusinessValidationFailedException($"密码连续错误{maxFailures}次,当前账号已被限制登录,请等待 {lockoutMinutes} 分钟后再试。");
}
@ -672,6 +682,8 @@ namespace IRaCIS.Application.Services
failCount++;
_cache.Set(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes));
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = Guid.Empty, LoginName = userName, LoginPassword = password, IsSuccess = false, OptType = UserOptType.AccountOrPasswordError }, true);
return ResponseOutput.NotOk(_localizer["User_CheckNameOrPw"], new LoginReturnDTO());
@ -688,7 +700,7 @@ namespace IRaCIS.Application.Services
//登录成功 清除缓存
_cache.Set(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes));
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = loginUser.Id, LoginName = userName, IsSuccess = true, OptType = UserOptType.Login }, true);
userLoginReturnModel.BasicInfo = loginUser;
@ -701,32 +713,12 @@ namespace IRaCIS.Application.Services
//private bool loginIsLocked(string userName)
//{
public async Task<IResponseOutput> LoginOut(Guid userId,string loginName)
{
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, CreateUserId = userId, LoginName = loginName, IsSuccess = true, OptType = UserOptType.LoginOut },true);
// //if (failCount == null)
// //{
// // failCount = 0;
// //}
// //else
// //{
// // failCount++;
// //}
// //// 更新缓存中的登录失败次数
// //_cache.Set(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes));
// //if (failCount >= maxFailures)
// //{
// // // 如果登录失败次数达到了 3 次,则锁定用户
// // _cache.Set(cacheKey + ":locked", true, TimeSpan.FromMinutes(lockoutMinutes));
// //}
// //return isLocked;
//}
return ResponseOutput.Ok();
}
}
}

View File

@ -119,7 +119,8 @@ namespace IRaCIS.Core.Application.Service
.ForMember(d => d.UserTypeId, c => c.MapFrom(t => t));
CreateMap<UserLog, UserLogView>();
CreateMap<UserLog, UserLogAddOrEdit>().ReverseMap();
}
}

View File

@ -0,0 +1,78 @@
//--------------------------------------------------------------------
// 此代码由T4模板自动生成 byzhouhang 20210918
// 生成时间 2023-07-04 16:10:43
// 对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,这些更改将会丢失。
using System;
using IRaCIS.Core.Domain.Share;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace IRaCIS.Core.Domain.Models
{
///<summary>
///UserLog
///</summary>
[Table("UserLog")]
public class UserLog : Entity, IAuditAdd
{
public string IP { get; set; }
public DateTime CreateTime { get; set; }
public Guid CreateUserId { get; set; }
public string LoginName { get; set; }
public UserOptType OptType { get; set; }
public string LoginPassword { get; set; }
public bool IsSuccess { get; set; }
[JsonIgnore]
public User CreateUser { get; set; }
}
/// <summary>
/// 登录或者登出 锁定类型
/// </summary>
public enum UserOptType
{
/// <summary>
/// 用户登录
/// </summary>
Login = 1,
/// <summary>
/// 用户登出
/// </summary>
LoginOut = 2,
/// <summary>
///账号或者密码错误
/// </summary>
AccountOrPasswordError = 3,
/// <summary>
/// 账号锁定
/// </summary>
AccountLocked = 4,
ModifyPassword=5,
AdminResetPassword=6
}
}

View File

@ -508,6 +508,8 @@ namespace IRaCIS.Core.Infra.EFCore
public virtual DbSet<ReadingTableQuestionAnswer> ReadingTableQuestionAnswer { get; set; }
public virtual DbSet<PublishLog> PublishLog { get; set; }
public virtual DbSet<UserLog> UserLog { get; set; }

View File

@ -0,0 +1,46 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace IRaCIS.Core.Infrastructure
{
public class SymmetricEncryption
{
public static string Encrypt(string plainText, string key)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
byte[] ivBytes = new byte[16]; // Initialization vector (IV)
using (Aes aes = Aes.Create())
{
aes.Key = keyBytes;
aes.IV = ivBytes;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
byte[] encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
return Convert.ToBase64String(encryptedBytes);
}
}
public static string Decrypt(string cipherText, string key)
{
byte[] keyBytes = Encoding.UTF8.GetBytes(key);
byte[] ivBytes = new byte[16]; // Initialization vector (IV)
using (Aes aes = Aes.Create())
{
aes.Key = keyBytes;
aes.IV = ivBytes;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] cipherBytes = Convert.FromBase64String(cipherText);
byte[] decryptedBytes = decryptor.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length);
return Encoding.UTF8.GetString(decryptedBytes);
}
}
}
}